ruststring-literals

Types from array of strings, need a string literal to pass into a function


In the following Rust code, I have an array of strings and I try to iterate over the names so that I can add them to my egui UI. I get two errors:

error: expected a literal and error: argument must be a string literal and it highlights the image variable on the egui::Image::new... line.

const images: [&str; 3] = [
    "../images/map.png",
    "../images/camera.png",
    "../images/users.png",
];

for image in images {
    ui.add(egui::Image::new(egui::include_image!(image)));
}

What is the type of image when it's being passed into include_image!? Isn't it a string already? What do I need to do to fix this?


Solution

  • A variable, no matter it's type is never a literal, only things like 4, "foo", true, … are literal expressions.

    Now the problem in your case is include_image! internally uses concat! and include_bytes! which both, like println!, require a string literal, not a variable containing a String or string slice (&str).

    So you can't use a for-loop with your literals, they have to be passed to include_image! directly:

        const images: [egui::ImageSource; 3] = [
            egui::include_image!("../images/map.png"),
            egui::include_image!("../images/camera.png"),
            egui::include_image!("../images/users.png"),
        ];
    
        for image in images {
            ui.add(egui::Image::new(image));
        }
    

    You can use a macro to avoid having to repeat include_image! multiple times:

    macro_rules! include_images {
        ($($s:literal),* $(,)?) => {
            [$(::egui::include_image!($s)),*]
        };
    }
    
        const images: [egui::ImageSource; 3] = include_images![
            "../images/map.png",
            "../images/camera.png",
            "../images/users.png",
        ];
    
        for image in images {
            ui.add(egui::Image::new(image));
        }
    

    See Dynamically load and display images from disk using eframe/egui if you want to include the files at runtime instead.