Skip to main content

ordinal_map/map/total/
array_map.rs

1use std::convert::Infallible;
2use std::fmt::Debug;
3use std::marker::PhantomData;
4use std::mem;
5use std::ops::Index;
6use std::ops::IndexMut;
7use std::slice;
8
9use crate::array_as_mut::array_as_mut;
10use crate::array_builder::ArrayBuilder;
11use crate::array_from_iter::array_from_iter;
12use crate::map::total::IntoIterArray;
13use crate::map::total::Iter;
14use crate::map::total::IterMut;
15use crate::Ordinal;
16
17/// Like [`OrdinalTotalMap`](crate::map::total::OrdinalTotalMap), but without heap allocation.
18///
19/// Due to limitations of stable Rust, ordinal size must be passed as a third type parameter.
20///
21/// # Example
22///
23/// ```
24/// use ordinal_map::map::total::OrdinalTotalArrayMap;
25/// use ordinal_map::Ordinal;
26///
27/// #[derive(Ordinal, Debug)]
28/// enum Color {
29///     Red,
30///     Green,
31///     Blue,
32/// }
33///
34/// let map: OrdinalTotalArrayMap<Color, String, { Color::ORDINAL_SIZE }> =
35///     OrdinalTotalArrayMap::new(|color| format!("{color:?}").to_lowercase());
36///
37/// assert_eq!("green", map[&Color::Green]);
38/// ```
39#[repr(C)]
40pub struct OrdinalTotalArrayMap<K, V, const S: usize> {
41    map: [V; S],
42    _phantom: PhantomData<K>,
43}
44
45impl<K: Ordinal, V, const S: usize> OrdinalTotalArrayMap<K, V, S> {
46    const ASSERT: () = {
47        assert!(K::ORDINAL_SIZE == S, "K::ORDINAL_SIZE != S");
48    };
49
50    /// Create a new map by initializing each value with a function.
51    pub fn try_new<E>(mut init: impl FnMut(K) -> Result<V, E>) -> Result<Self, E> {
52        const { Self::ASSERT };
53        let mut a = ArrayBuilder::new();
54        for v in K::all_values() {
55            a.push(init(v)?);
56        }
57        Ok(OrdinalTotalArrayMap {
58            map: a.finish(),
59            _phantom: PhantomData,
60        })
61    }
62
63    /// Create a new map by initializing each value with a function.
64    pub fn new(mut init: impl FnMut(K) -> V) -> Self {
65        const { Self::ASSERT };
66        match Self::try_new(move |k| Ok::<_, Infallible>(init(k))) {
67            Ok(map) => map,
68            Err(infallible) => match infallible {},
69        }
70    }
71
72    /// Create a new map from an array of values in ordinal order of keys.
73    pub fn from_array(array: [V; S]) -> Self {
74        OrdinalTotalArrayMap {
75            map: array,
76            _phantom: PhantomData,
77        }
78    }
79
80    /// Returns the number of elements in the map, which is
81    /// always equal to [`K::ORDINAL_SIZE`](Ordinal::ORDINAL_SIZE).
82    pub const fn len(&self) -> usize {
83        S
84    }
85
86    /// Return true if the map container no elements.
87    pub const fn is_empty(&self) -> bool {
88        self.len() == 0
89    }
90
91    /// Returns a reference to the value corresponding to the key.
92    pub fn get<'a>(&'a self, key: &K) -> &'a V {
93        &self.map[key.ordinal()]
94    }
95
96    /// Returns a mutable reference to the value corresponding to the key.
97    pub fn get_mut<'a>(&'a mut self, key: &K) -> &'a mut V {
98        &mut self.map[key.ordinal()]
99    }
100
101    /// Return a new map with values as references to values of the original map.
102    pub fn as_ref(&self) -> OrdinalTotalArrayMap<K, &V, S> {
103        OrdinalTotalArrayMap::new(|k| self.get(&k))
104    }
105
106    /// Return a new map with values as mutable references to values of the original map.
107    pub fn as_mut(&mut self) -> OrdinalTotalArrayMap<K, &mut V, S> {
108        OrdinalTotalArrayMap::from_array(array_as_mut(&mut self.map))
109    }
110
111    /// Combine two maps into one.
112    pub fn zip<W>(
113        self,
114        other: OrdinalTotalArrayMap<K, W, S>,
115    ) -> OrdinalTotalArrayMap<K, (V, W), S> {
116        OrdinalTotalArrayMap {
117            map: array_from_iter(self.map.into_iter().zip(other.map)),
118            _phantom: PhantomData,
119        }
120    }
121
122    /// Map the values of the map.
123    pub fn map<W>(self, mut f: impl FnMut(K, V) -> W) -> OrdinalTotalArrayMap<K, W, S> {
124        OrdinalTotalArrayMap {
125            map: array_from_iter(self.into_iter().map(|(k, v)| f(k, v))),
126            _phantom: PhantomData,
127        }
128    }
129
130    /// Map the values of the map.
131    pub fn map_values<W>(self, mut f: impl FnMut(V) -> W) -> OrdinalTotalArrayMap<K, W, S> {
132        self.map(|_k, v| f(v))
133    }
134
135    /// Iterate over the map.
136    pub fn iter<'a>(&'a self) -> Iter<'a, K, V> {
137        Iter::new(self.map.iter(), 0)
138    }
139
140    /// Iterate over the map mutably.
141    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, K, V> {
142        IterMut::new(self.map.iter_mut())
143    }
144
145    /// Iterate keys of the map, which is equivalent to iterating all possible values of `K`.
146    pub fn keys(&self) -> crate::OrdinalValues<K> {
147        K::all_values()
148    }
149
150    /// Convert the map into an iterator over keys.
151    ///
152    /// This operation is identical to [`keys`](OrdinalTotalArrayMap::keys),
153    /// but added here for consistency with other map implementations.
154    pub fn into_keys(self) -> crate::OrdinalValues<K> {
155        self.keys()
156    }
157
158    /// Iterate values of the map.
159    pub fn values<'a>(&'a self) -> slice::Iter<'a, V> {
160        self.map.iter()
161    }
162
163    /// Values arrays.
164    pub fn values_array(&self) -> &[V; S] {
165        &self.map
166    }
167
168    /// Iterate mutable references to values of the map.
169    pub fn values_mut<'a>(&'a mut self) -> slice::IterMut<'a, V> {
170        self.map.iter_mut()
171    }
172
173    /// Values arrays.
174    pub fn values_array_mut(&mut self) -> &mut [V; S] {
175        &mut self.map
176    }
177
178    /// Convert the map into an array of values.
179    pub fn into_values(self) -> [V; S] {
180        self.map
181    }
182
183    /// Insert a value into the map, returning the previous value.
184    #[inline]
185    pub fn insert(&mut self, key: K, value: V) -> V {
186        mem::replace(&mut self.map[key.ordinal()], value)
187    }
188}
189
190impl<'a, K: Ordinal, V, const S: usize> Index<&'a K> for OrdinalTotalArrayMap<K, V, S> {
191    type Output = V;
192
193    fn index(&self, index: &'a K) -> &Self::Output {
194        &self.map[index.ordinal()]
195    }
196}
197
198impl<'a, K: Ordinal, V, const S: usize> IndexMut<&'a K> for OrdinalTotalArrayMap<K, V, S> {
199    fn index_mut(&mut self, index: &'a K) -> &mut Self::Output {
200        &mut self.map[index.ordinal()]
201    }
202}
203
204impl<K, V: Clone, const S: usize> Clone for OrdinalTotalArrayMap<K, V, S> {
205    fn clone(&self) -> Self {
206        OrdinalTotalArrayMap {
207            map: self.map.clone(),
208            _phantom: PhantomData,
209        }
210    }
211}
212
213impl<K: Ordinal, V: Default, const S: usize> Default for OrdinalTotalArrayMap<K, V, S> {
214    fn default() -> Self {
215        OrdinalTotalArrayMap::new(|_| V::default())
216    }
217}
218
219impl<K: Ordinal + Debug, V: Debug, const S: usize> Debug for OrdinalTotalArrayMap<K, V, S> {
220    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221        f.debug_map().entries(self.iter()).finish()
222    }
223}
224
225impl<K: Ordinal, V, const S: usize> IntoIterator for OrdinalTotalArrayMap<K, V, S> {
226    type Item = (K, V);
227    type IntoIter = IntoIterArray<K, V, S>;
228
229    fn into_iter(self) -> Self::IntoIter {
230        IntoIterArray::new(self.map.into_iter())
231    }
232}
233
234impl<'a, K: Ordinal, V, const S: usize> IntoIterator for &'a OrdinalTotalArrayMap<K, V, S> {
235    type Item = (K, &'a V);
236    type IntoIter = Iter<'a, K, V>;
237
238    fn into_iter(self) -> Self::IntoIter {
239        self.iter()
240    }
241}
242
243#[cfg(test)]
244mod tests {
245    #[test]
246    fn test() {}
247}