Home > Mobile >  Load file contents into a static array of bytes
Load file contents into a static array of bytes

Time:12-16

I have a static array initialized with some constant value:

static PROG_ROM: [u8; 850] = [0x12, 0x1d, ...];

I would like to instead load at compile-time the contents of a file into it. Sounds like a job for std::include_bytes!, however, I have two problems with it:

  1. The type of include_bytes!("foo.dat") is &[u8; 850] i.e. it is a reference. I need this to be a bonafide static array.

  2. Even if there was an include_bytes_static! macro with type [u8;850], I would have to use it like this:

    static PROG_ROM: [u8; 850] = include_bytes_static!("foo.dat");
    

    I.e. I would have to hardcode the length of the file. Instead, I would like to take the length from the length of the file contents.

So the ideal replacement for my code would be a macro to replace the whole definition, i.e. look something like this:

define_included_bytes!(PROG_ROM, "foo.dat")

and it would expand to

static PROG_ROM: [u8; 850] = [0x12, 0x1d, ...];

So how do I do this?

CodePudding user response:

Use *include_bytes!(..) to get a [u8; _] instead of &[u8; _] (since arrays implement Copy), and use include_bytes!(..).len() (which is a const method) to specify the length of the array in the type:

static PROG_ROM: [u8; include_bytes!("foo.dat").len()] = *include_bytes!("foo.dat");

CodePudding user response:

As Chayim Friedman pointed out you can easily define that proc macro yourself:

#[proc_macro]
fn define_included_bytes(token_stream: TokenStream) -> TokenStream {
    let [ident, _, file] = &token_stream.into_iter().collect::<Vec<_>>()[..] else {
        panic!("expected invocation: `define_included_bytes!(IDENTIFIER, \"file_name\");");
    };
    let file = file.to_string().trim_matches('\"').to_string();
    let data: Vec<u8> = std::fs::read(&file).expect(&format!("File {:?} could not be read", file));
    format!("const {ident}: [u8; {}] = {:?};", data.len(), data).parse().unwrap()
}

Obviously this is just a hacked together proof of concept and you should thouroughly check the tokens instead of just assuming they're correct.

  • Related