veloren_world/util/
map_array.rs

1use std::cmp::PartialEq;
2
3pub trait GenericIndex<V: Clone, const N: usize> {
4    const LENGTH: usize = N;
5    const VALUES: [V; N];
6
7    fn from_usize(n: usize) -> Self;
8    fn into_usize(self) -> usize;
9}
10
11#[derive(Debug)]
12pub struct NotFound();
13
14pub fn index_from_enum<E: Clone + PartialEq, I: GenericIndex<E, N>, const N: usize>(
15    val: E,
16) -> Result<I, NotFound> {
17    I::VALUES
18        .iter()
19        .position(|v| val == *v)
20        .ok_or(NotFound {})
21        .map(I::from_usize)
22}
23
24pub fn enum_from_index<E: Clone, I: GenericIndex<E, N>, const N: usize>(idx: I) -> E {
25    I::VALUES[idx.into_usize()].clone()
26}
27
28#[cfg(test)]
29mod tests {
30    use crate::util::map_array::{GenericIndex, NotFound, enum_from_index, index_from_enum};
31    use std::{
32        convert::{TryFrom, TryInto},
33        ops::{Index, IndexMut},
34    };
35
36    // the Values we want to generate an Index for
37    #[derive(Debug, Clone, PartialEq, Eq)]
38    enum MyEnum0 {
39        A,
40        B,
41    }
42
43    #[derive(Debug, Clone, PartialEq, Eq)]
44    enum MyEnum {
45        C(MyEnum0),
46        D,
47    }
48
49    // the opaque index type into the "map"
50    struct MyIndex(usize);
51
52    impl GenericIndex<MyEnum, 3> for MyIndex {
53        const VALUES: [MyEnum; MyIndex::LENGTH] =
54            [MyEnum::C(MyEnum0::B), MyEnum::C(MyEnum0::A), MyEnum::D];
55
56        fn from_usize(n: usize) -> Self { Self(n) }
57
58        fn into_usize(self) -> usize { self.0 }
59    }
60
61    impl TryFrom<MyEnum> for MyIndex {
62        type Error = NotFound;
63
64        fn try_from(e: MyEnum) -> Result<MyIndex, NotFound> { index_from_enum(e) }
65    }
66
67    impl From<MyIndex> for MyEnum {
68        fn from(idx: MyIndex) -> MyEnum { enum_from_index(idx) }
69    }
70
71    // the "map" itself
72    struct MyMap<V>([V; MyIndex::LENGTH]);
73
74    impl<V: Default + Copy> Default for MyMap<V> {
75        fn default() -> Self { MyMap([V::default(); MyIndex::LENGTH]) }
76    }
77
78    impl<V> Index<MyIndex> for MyMap<V> {
79        type Output = V;
80
81        fn index(&self, index: MyIndex) -> &Self::Output { &self.0[index.0] }
82    }
83
84    impl<V> IndexMut<MyIndex> for MyMap<V> {
85        fn index_mut(&mut self, index: MyIndex) -> &mut Self::Output { &mut self.0[index.0] }
86    }
87
88    impl<V> MyMap<V> {
89        pub fn iter(&self) -> impl Iterator<Item = (MyIndex, &V)> + '_ {
90            self.0.iter().enumerate().map(|(i, v)| (MyIndex(i), v))
91        }
92    }
93
94    // test: create a map, set some values and output it
95    // Output: m[C(B)]=19 m[C(A)]=42 m[D]=0
96    #[test]
97    fn test_map_array() {
98        let mut m = MyMap::default();
99        if let Ok(i) = MyEnum::C(MyEnum0::A).try_into() {
100            m[i] = 42.0;
101        }
102        if let Ok(i) = MyEnum::C(MyEnum0::B).try_into() {
103            m[i] = 19.0;
104        }
105        for (k, v) in m.iter() {
106            let k2: MyEnum = k.into();
107            println!("m[{:?}]={}", k2, *v);
108        }
109    }
110}