Skip to main content

const_tools/
from_indices.rs

1/// Creates an array by evaluating a function for each index in `0..N` in const contexts.
2///
3/// # Examples
4///
5/// ```
6/// use const_tools::from_indices;
7///
8/// const fn powers_of_two<const N: usize>() -> [u32; N] {
9///     from_indices!(N, |index| 1 << index)
10/// }
11///
12/// assert!(matches!(powers_of_two::<4>(), [1, 2, 4, 8]));
13/// ```
14#[macro_export]
15macro_rules! from_indices {
16    ($($from_indices_args:tt)*) => {
17        $crate::__from_indices__parse!([$($from_indices_args)*] $crate::__from_indices__expand!(<>))
18    };
19}
20
21#[doc(hidden)]
22#[macro_export]
23macro_rules! __from_indices__parse {
24    // [args] [cb]
25    ([$N:expr, |$iip:pat_param| $($body:tt)*] $($cb:tt)*) => {
26        $crate::__call!($($cb)*([$N] [$iip] [$($body)*]))
27    };
28    ([$N:expr, $fn:expr] $($cb:tt)*) => {
29        $crate::__call!($($cb)*([$N] [index] [$fn(index)]))
30    };
31}
32
33#[doc(hidden)]
34#[macro_export]
35macro_rules! __from_indices__expand {
36    // [N] [iip] [body]
37    ([$N:expr] [$iip:pat_param] [$body:expr]) => {{
38        let mut oa = $crate::__maybe_uninit_array_uninit::<_, { $N }>();
39        let mut index = 0;
40        #[deny(unreachable_code)]
41        while index < oa.len() {
42            let $iip = index;
43            oa[index].write($body);
44            index += 1;
45        }
46        assert!(
47            index == oa.len(),
48            "break is not allowed because a value must be written into every array element"
49        );
50        unsafe { $crate::__maybe_uninit_array_assume_init(oa) }
51    }};
52}