cl_structures/
index_map.rs1#[macro_export]
37macro_rules! make_index {($($(#[$meta:meta])* $name:ident),*$(,)?) => {$(
38 $(#[$meta])*
39 #[repr(transparent)]
40 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
41 pub struct $name(usize);
42
43 impl $crate::index_map::MapIndex for $name {
44 #[doc = concat!("Constructs a [`", stringify!($name), "`] from a [`usize`] without checking bounds.\n")]
45 #[inline]
47 fn from_usize(value: usize) -> Self {
48 Self(value)
49 }
50 #[inline]
51 fn get(&self) -> usize {
52 self.0
53 }
54 }
55
56 impl From< $name > for usize {
57 fn from(value: $name) -> Self {
58 value.0
59 }
60 }
61)*}}
62
63use self::iter::MapIndexIter;
64use std::{
65 ops::{Index, IndexMut},
66 slice::GetDisjointMutError,
67};
68
69pub use make_index;
70
71pub trait MapIndex: std::fmt::Debug {
74 fn from_usize(value: usize) -> Self;
78 fn get(&self) -> usize;
80}
81
82#[derive(Clone, Debug, PartialEq, Eq)]
84pub struct IndexMap<K: MapIndex, V> {
85 map: Vec<V>,
86 id_type: std::marker::PhantomData<K>,
87}
88
89impl<V, K: MapIndex> IndexMap<K, V> {
90 pub fn new() -> Self {
92 Self::default()
93 }
94
95 pub fn get(&self, index: K) -> Option<&V> {
97 self.map.get(index.get())
98 }
99
100 pub fn get_mut(&mut self, index: K) -> Option<&mut V> {
102 self.map.get_mut(index.get())
103 }
104
105 pub fn get_disjoint_mut<const N: usize>(
109 &mut self,
110 indices: [K; N],
111 ) -> Result<[&mut V; N], GetDisjointMutError> {
112 self.map.get_disjoint_mut(indices.map(|id| id.get()))
113 }
114
115 pub fn values(&self) -> impl Iterator<Item = &V> {
117 self.map.iter()
118 }
119
120 pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
122 self.map.iter_mut()
123 }
124
125 pub fn keys(&self) -> iter::MapIndexIter<K> {
127 MapIndexIter::new(0..self.map.len())
129 }
130
131 #[doc(hidden)]
133 pub fn try_key_from(&self, value: usize) -> Option<K> {
134 (value < self.map.len()).then(|| K::from_usize(value))
135 }
136
137 pub fn insert(&mut self, value: V) -> K {
139 let id = self.map.len();
140 self.map.push(value);
141
142 K::from_usize(id)
144 }
145
146 pub fn replace(&mut self, key: K, value: V) -> V {
148 std::mem::replace(&mut self[key], value)
149 }
150}
151
152impl<K: MapIndex, V> Default for IndexMap<K, V> {
153 fn default() -> Self {
154 Self { map: vec![], id_type: std::marker::PhantomData }
155 }
156}
157
158impl<K: MapIndex, V> Index<K> for IndexMap<K, V> {
159 type Output = V;
160
161 fn index(&self, index: K) -> &Self::Output {
162 match self.map.get(index.get()) {
163 None => panic!("Index {:?} out of bounds in IndexMap!", index),
164 Some(value) => value,
165 }
166 }
167}
168
169impl<K: MapIndex, V> IndexMut<K> for IndexMap<K, V> {
170 fn index_mut(&mut self, index: K) -> &mut Self::Output {
171 match self.map.get_mut(index.get()) {
172 None => panic!("Index {:?} out of bounds in IndexMap!", index),
173 Some(value) => value,
174 }
175 }
176}
177
178mod iter {
179 use super::MapIndex;
181 use std::{marker::PhantomData, ops::Range};
182
183 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
188 pub struct MapIndexIter<K: MapIndex> {
189 range: Range<usize>,
190 _id: PhantomData<K>,
191 }
192
193 impl<K: MapIndex> MapIndexIter<K> {
194 pub(super) fn new(range: Range<usize>) -> Self {
196 Self { range, _id: PhantomData }
197 }
198 }
199
200 impl<ID: MapIndex> Iterator for MapIndexIter<ID> {
201 type Item = ID;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 Some(ID::from_usize(self.range.next()?))
205 }
206 fn size_hint(&self) -> (usize, Option<usize>) {
207 self.range.size_hint()
208 }
209 }
210
211 impl<ID: MapIndex> DoubleEndedIterator for MapIndexIter<ID> {
212 fn next_back(&mut self) -> Option<Self::Item> {
213 Some(ID::from_usize(self.range.next_back()?))
215 }
216 }
217
218 impl<ID: MapIndex> ExactSizeIterator for MapIndexIter<ID> {}
219}