veloren_world/util/
map_array.rs1use 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 #[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 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 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]
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}