Skip to main content

multilinear_parser/
index_map.rs

1use std::{
2    marker::PhantomData,
3    ops::{Index, IndexMut},
4};
5
6/// Stores index based maps.
7pub struct IndexMap<I: Into<usize> + From<usize>, V> {
8    pub(crate) entries: Vec<V>,
9    index: PhantomData<I>,
10}
11
12impl<I: Into<usize> + From<usize>, V> Default for IndexMap<I, V> {
13    fn default() -> Self {
14        Self {
15            entries: Vec::new(),
16            index: PhantomData,
17        }
18    }
19}
20
21impl<I: Into<usize> + From<usize>, V> IndexMap<I, V> {
22    /// Returns if the index map contains no elements.
23    #[must_use]
24    pub const fn is_empty(&self) -> bool {
25        self.entries.is_empty()
26    }
27
28    /// Returns the number of elements.
29    #[must_use]
30    pub const fn len(&self) -> usize {
31        self.entries.len()
32    }
33
34    /// Gets an entry by index.
35    pub fn get(&self, index: I) -> Option<&V> {
36        self.entries.get(index.into())
37    }
38
39    /// Gets a mutable entry by index.
40    pub fn get_mut(&self, index: I) -> Option<&V> {
41        self.entries.get(index.into())
42    }
43
44    /// Returns an iterator over the index map.
45    #[must_use]
46    pub fn iter(&self) -> Iter<'_, I, V> {
47        self.into_iter()
48    }
49
50    pub(crate) fn insert(&mut self, index: I, value: V) {
51        let i = index.into();
52        assert_eq!(i, self.entries.len(), "Wrong insertion order");
53        self.entries.push(value);
54    }
55}
56
57impl<I: Into<usize> + From<usize>, V> Index<I> for IndexMap<I, V> {
58    type Output = V;
59
60    #[expect(clippy::indexing_slicing)]
61    fn index(&self, index: I) -> &V {
62        &self.entries[index.into()]
63    }
64}
65
66impl<I: Into<usize> + From<usize>, V> IndexMut<I> for IndexMap<I, V> {
67    #[expect(clippy::indexing_slicing)]
68    fn index_mut(&mut self, index: I) -> &mut V {
69        &mut self.entries[index.into()]
70    }
71}
72
73/// An iterator over indices and values of an index map.
74pub struct IntoIter<I: Into<usize> + From<usize>, V> {
75    data: std::iter::Enumerate<std::vec::IntoIter<V>>,
76    index: PhantomData<I>,
77}
78
79impl<I: Into<usize> + From<usize>, V> Iterator for IntoIter<I, V> {
80    type Item = (I, V);
81
82    fn next(&mut self) -> Option<(I, V)> {
83        let (i, value) = self.data.next()?;
84        Some((i.into(), value))
85    }
86
87    fn size_hint(&self) -> (usize, Option<usize>) {
88        self.data.size_hint()
89    }
90}
91
92impl<I: Into<usize> + From<usize>, V> ExactSizeIterator for IntoIter<I, V> {}
93
94impl<I: Into<usize> + From<usize>, V> IntoIterator for IndexMap<I, V> {
95    type Item = (I, V);
96    type IntoIter = IntoIter<I, V>;
97
98    fn into_iter(self) -> IntoIter<I, V> {
99        IntoIter {
100            data: self.entries.into_iter().enumerate(),
101            index: PhantomData,
102        }
103    }
104}
105
106/// An iterator over indices and values of an index map as references.
107pub struct Iter<'a, I: Into<usize> + From<usize>, V> {
108    data: std::iter::Enumerate<std::slice::Iter<'a, V>>,
109    index: PhantomData<I>,
110}
111
112impl<'a, I: Into<usize> + From<usize>, V> Iterator for Iter<'a, I, V> {
113    type Item = (I, &'a V);
114
115    fn next(&mut self) -> Option<(I, &'a V)> {
116        let (i, value) = self.data.next()?;
117        Some((i.into(), value))
118    }
119
120    fn size_hint(&self) -> (usize, Option<usize>) {
121        self.data.size_hint()
122    }
123}
124
125impl<I: Into<usize> + From<usize>, V> ExactSizeIterator for Iter<'_, I, V> {}
126
127impl<'a, I: Into<usize> + From<usize>, V> IntoIterator for &'a IndexMap<I, V> {
128    type Item = (I, &'a V);
129    type IntoIter = Iter<'a, I, V>;
130
131    fn into_iter(self) -> Iter<'a, I, V> {
132        Iter {
133            data: self.entries.iter().enumerate(),
134            index: PhantomData,
135        }
136    }
137}