How can I generate a long const array with values taken from a range? Bonus: 1) working with no_std, 2) without using any crates
What I would like to do:
struct A {
a: i32,
b: B
}
enum B {
One,
Two
}
const AS: [A; 1024] = [A{a: 1, b: B::One}, A{a: 2, b: B::One}, ..., A{a: 1024, b: B::One}]
The furthest I got so far is:
macro_rules! generate_list {
($($a:expr)+, $variant:expr) => {
[ $( A { a: $a, b: $variant } )* ]
}
}
const AS: [A; 1024] = generate_list!(1..1025i32, B::One);
At least one problem with this seems to be that the macro is evaluated before the range expression is expanded to a list of literals.
I'm not sure if its idiomatic, but perhaps the following might work for your use case:
#[derive(Debug, Copy, Clone)]
pub struct A {
a: i32,
b: B,
}
#[derive(Debug, Copy, Clone)]
pub enum B {
One,
Two,
}
const fn gen_array<const N: usize>(offset: i32, b: B) -> [A; N] {
let mut res = [A { a: offset, b }; N];
let mut i = 0;
while i < N as i32 {
res[i as usize].a = offset + i;
i += 1;
}
res
}
const AS: [A; 42] = gen_array(0, B::One);
fn main() {
println!("{:#?}", AS);
}
I used a while
loop, as a for
loop is currently not allowed within a const
context as E0744
indicates.
The above would generate 42 values for AS
with an offset of 0
:
[
A {
a: 0,
b: One,
},
A {
a: 1,
b: One,
},
...
A {
a: 41,
b: One,
},
]
The Godbolt Compiler Explorer shows that it generates the same instructions as writing it out manually.