Skip to main content

ordinal_map/ordinal/impls/
array.rs

1use crate::array_builder::ArrayBuilder;
2use crate::Ordinal;
3
4impl<T: Ordinal, const N: usize> Ordinal for [T; N] {
5    const ORDINAL_SIZE: usize = {
6        let mut s = 1usize;
7        let mut i = 0;
8        while i < N {
9            s = s.checked_mul(T::ORDINAL_SIZE).unwrap();
10            i += 1;
11        }
12        s
13    };
14
15    fn ordinal(&self) -> usize {
16        let mut r = 0usize;
17        for v in self {
18            r = r.checked_mul(T::ORDINAL_SIZE).unwrap();
19            r += v.ordinal();
20        }
21        r
22    }
23
24    fn from_ordinal(ordinal: usize) -> Option<Self> {
25        let mut n = ordinal;
26        let mut array = ArrayBuilder::new();
27        for _ in 0..N {
28            let Some(i) = n.checked_rem(T::ORDINAL_SIZE) else {
29                return None;
30            };
31            array.push(T::from_ordinal(i).unwrap());
32            n /= T::ORDINAL_SIZE;
33        }
34        if n != 0 {
35            None
36        } else {
37            let mut array = array.finish();
38            array.reverse();
39            Some(array)
40        }
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use std::convert::Infallible;
47
48    use crate::tests::util::test_ordinal;
49
50    #[test]
51    fn test_array_of_empty() {
52        test_ordinal::<[Infallible; 0]>([[]]);
53        test_ordinal::<[Infallible; 1]>([]);
54        test_ordinal::<[Infallible; 2]>([]);
55    }
56
57    #[test]
58    fn test_array_0() {
59        test_ordinal::<[u16; 0]>([[]]);
60    }
61
62    #[test]
63    fn test_array_1() {
64        test_ordinal([[false], [true]]);
65    }
66
67    #[test]
68    fn test_array_2() {
69        test_ordinal([[false, false], [false, true], [true, false], [true, true]]);
70        // Should be compatible with ordinal for tuple.
71        test_ordinal([(false, false), (false, true), (true, false), (true, true)]);
72    }
73}