shadow_nft_common/
array_from_fn.rs

1//! Unfortunately... I used core::array::from_fn which, although is stable
2//! on stable Rust, is not stable with cargo-build-sbf that ships with
3//! solana 1.14.18. So, this library will build in stable Rust. Solana 1.16
4//! ships with a rust compiler that stabilizes, but until 1.16 is live and
5//! compatible with anchor, we are left to use this alternative.
6use core::mem::MaybeUninit;
7
8/// A `core::array::from_fn` that we got off wish.com
9pub fn from_fn<T, F: FnMut(usize) -> T, const L: usize>(mut f: F) -> [T; L] {
10    // Initialize array with uninitialized values
11    let mut array: [MaybeUninit<T>; L] = [(); L].map(|_| MaybeUninit::uninit());
12
13    // Initialize values in array
14    for i in 0..L {
15        array[i].write(f(i));
16    }
17    // Mark array values as initialized.
18    // # SAFETY: we just initialized all `L` items in the loop above.
19    
20    unsafe { array.map(|ui| ui.assume_init()) }
21}
22
23#[test]
24fn test_stable_array_from_fn() {
25    // Identity
26    let result = from_fn(|i| i);
27    let expected = [0, 1, 2, 3, 4, 5];
28    assert_eq!(result, expected);
29
30    // Some non-identity closure
31    let result = from_fn(|i| i * i);
32    let expected = [0, 1, 4, 9, 16, 25];
33    assert_eq!(result, expected);
34
35    // Some closure which borrows a value from another (Fn)
36    let some_other_array = [5, 4, 3, 2, 1];
37    let result = from_fn(|i| some_other_array[i]);
38    assert_eq!(result, some_other_array);
39
40    // Some closure which moves a value (Fn)
41    let some_other_array = [5, 4, 3, 2, 1];
42    let result = from_fn(move |i| some_other_array[i]);
43    assert_eq!(result, some_other_array);
44
45    // Some closure which mutable borrows values from another (FnMut)
46    let mut some_other_array = [5, 4, 3, 2, 1, 0];
47    let result = from_fn(|i| {
48        some_other_array[i] = i;
49        i * i
50    });
51    let expected_some = [0, 1, 2, 3, 4, 5];
52    let expected_result = [0, 1, 4, 9, 16, 25];
53    assert_eq!(some_other_array, expected_some);
54    assert_eq!(result, expected_result);
55}