How to concatenate array literals in compile time?


#1

I have a constant of type array which I would like to put some elements into and after that fill it with a fixed element. What I want is something like:

const TABLE: &'static [u8; 256] = concat_array!([1, 2, 3, 4], [0; 252])

How do I do that?


#2

You basically cannot do this simply at this point in Rust.

At some point in time, you will be able to write this:

const TABLE: [u8; 256] = {
    let mut x = [0; 256];
    x[0] = 1;
    x[1] = 2;
    x[2] = 3;
    x[3] = 4;
    x
};

You can’t easily use a macro to do this.

You could write a procedural macro now that those have been stabilized and are riding the release trains, but they haven’t hit stable yet.

I’d recommend writing a build script that generates that array and then bring in the generated file.


#3

Take a look at the approach in const-concat, it should work for array literals as well.


#4

I don’t think I can use a build script to generate an array of something that isn’t u8. Specially in my case, which is fn pointer. Sorry, I should have mentioned it. The example with u8 is merely an example.


#5

Working implementation: Playground


#6

Why do you think that? If you try it, then you could be sure if it worked or not. In fact, I tried it and it works:

build.rs

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let mut dest_path = PathBuf::from(out_dir);
    dest_path.push("array.rs");
    let mut f = File::create(&dest_path).unwrap();

    f.write_all(b"
        const TABLE: [fn(u8) -> u8; 4] = [
            a,
            b,
    ").unwrap();

    for _ in 2..4 {
        f.write_all(b"
            no_op,
        ").unwrap();
    }

    f.write_all(b"
        ];
    ").unwrap();
}

main.rs

fn a(a: u8)-> u8 { a + 1 }
fn b(a: u8)-> u8 { a + 2 }
fn no_op(a: u8)-> u8 { a }

include!(concat!(env!("OUT_DIR"), "/array.rs"));

fn main() {
    let mut x = 0;
    for f in &TABLE {
        x = f(x);
    }
    println!("{}", x); // 3
}

#7

I see… Sorry. I lacked attention and didn’t see include! macro on documentation when looking for it.