1use std::iter::Enumerate;
2use std::marker::PhantomData;
3
4use crate::Idx;
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct ArenaMap<IDX, V> {
10 v: Vec<Option<V>>,
11 _ty: PhantomData<IDX>,
12}
13
14impl<T, V> ArenaMap<Idx<T>, V> {
15 pub const fn new() -> Self {
17 Self { v: Vec::new(), _ty: PhantomData }
18 }
19
20 pub fn with_capacity(capacity: usize) -> Self {
22 Self { v: Vec::with_capacity(capacity), _ty: PhantomData }
23 }
24
25 pub fn reserve(&mut self, additional: usize) {
27 self.v.reserve(additional);
28 }
29
30 pub fn clear(&mut self) {
32 self.v.clear();
33 }
34
35 pub fn shrink_to_fit(&mut self) {
37 let min_len = self.v.iter().rposition(|slot| slot.is_some()).map_or(0, |i| i + 1);
38 self.v.truncate(min_len);
39 self.v.shrink_to_fit();
40 }
41
42 pub fn contains_idx(&self, idx: Idx<T>) -> bool {
44 matches!(self.v.get(Self::to_idx(idx)), Some(Some(_)))
45 }
46
47 pub fn remove(&mut self, idx: Idx<T>) -> Option<V> {
49 self.v.get_mut(Self::to_idx(idx))?.take()
50 }
51
52 pub fn insert(&mut self, idx: Idx<T>, t: V) -> Option<V> {
57 let idx = Self::to_idx(idx);
58
59 self.v.resize_with((idx + 1).max(self.v.len()), || None);
60 self.v[idx].replace(t)
61 }
62
63 pub fn get(&self, idx: Idx<T>) -> Option<&V> {
66 self.v.get(Self::to_idx(idx)).and_then(|it| it.as_ref())
67 }
68
69 pub fn get_mut(&mut self, idx: Idx<T>) -> Option<&mut V> {
72 self.v.get_mut(Self::to_idx(idx)).and_then(|it| it.as_mut())
73 }
74
75 pub fn values(&self) -> impl DoubleEndedIterator<Item = &V> {
77 self.v.iter().filter_map(|o| o.as_ref())
78 }
79
80 pub fn values_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut V> {
82 self.v.iter_mut().filter_map(|o| o.as_mut())
83 }
84
85 pub fn iter(&self) -> impl DoubleEndedIterator<Item = (Idx<T>, &V)> {
87 self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
88 }
89
90 pub fn iter_mut(&mut self) -> impl Iterator<Item = (Idx<T>, &mut V)> {
92 self.v
93 .iter_mut()
94 .enumerate()
95 .filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_mut()?)))
96 }
97
98 pub fn entry(&mut self, idx: Idx<T>) -> Entry<'_, Idx<T>, V> {
100 let idx = Self::to_idx(idx);
101 self.v.resize_with((idx + 1).max(self.v.len()), || None);
102 match &mut self.v[idx] {
103 slot @ Some(_) => Entry::Occupied(OccupiedEntry { slot, _ty: PhantomData }),
104 slot @ None => Entry::Vacant(VacantEntry { slot, _ty: PhantomData }),
105 }
106 }
107
108 fn to_idx(idx: Idx<T>) -> usize {
109 u32::from(idx.into_raw()) as usize
110 }
111
112 fn from_idx(idx: usize) -> Idx<T> {
113 Idx::from_raw((idx as u32).into())
114 }
115}
116
117impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> {
118 type Output = T;
119 fn index(&self, idx: Idx<V>) -> &T {
120 self.v[Self::to_idx(idx)].as_ref().unwrap()
121 }
122}
123
124impl<T, V> std::ops::IndexMut<Idx<V>> for ArenaMap<Idx<V>, T> {
125 fn index_mut(&mut self, idx: Idx<V>) -> &mut T {
126 self.v[Self::to_idx(idx)].as_mut().unwrap()
127 }
128}
129
130impl<T, V> Default for ArenaMap<Idx<V>, T> {
131 fn default() -> Self {
132 Self::new()
133 }
134}
135
136impl<T, V> Extend<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
137 fn extend<I: IntoIterator<Item = (Idx<V>, T)>>(&mut self, iter: I) {
138 iter.into_iter().for_each(move |(k, v)| {
139 self.insert(k, v);
140 });
141 }
142}
143
144impl<T, V> FromIterator<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
145 fn from_iter<I: IntoIterator<Item = (Idx<V>, T)>>(iter: I) -> Self {
146 let mut this = Self::new();
147 this.extend(iter);
148 this
149 }
150}
151
152pub struct ArenaMapIter<IDX, V> {
153 iter: Enumerate<std::vec::IntoIter<Option<V>>>,
154 _ty: PhantomData<IDX>,
155}
156
157impl<T, V> IntoIterator for ArenaMap<Idx<T>, V> {
158 type Item = (Idx<T>, V);
159
160 type IntoIter = ArenaMapIter<Idx<T>, V>;
161
162 fn into_iter(self) -> Self::IntoIter {
163 let iter = self.v.into_iter().enumerate();
164 Self::IntoIter { iter, _ty: PhantomData }
165 }
166}
167
168impl<T, V> ArenaMapIter<Idx<T>, V> {
169 fn mapper((idx, o): (usize, Option<V>)) -> Option<(Idx<T>, V)> {
170 Some((ArenaMap::<Idx<T>, V>::from_idx(idx), o?))
171 }
172}
173
174impl<T, V> Iterator for ArenaMapIter<Idx<T>, V> {
175 type Item = (Idx<T>, V);
176
177 #[inline]
178 fn next(&mut self) -> Option<Self::Item> {
179 for next in self.iter.by_ref() {
180 match Self::mapper(next) {
181 Some(r) => return Some(r),
182 None => continue,
183 }
184 }
185
186 None
187 }
188
189 #[inline]
190 fn size_hint(&self) -> (usize, Option<usize>) {
191 self.iter.size_hint()
192 }
193}
194
195impl<T, V> DoubleEndedIterator for ArenaMapIter<Idx<T>, V> {
196 #[inline]
197 fn next_back(&mut self) -> Option<Self::Item> {
198 while let Some(next_back) = self.iter.next_back() {
199 match Self::mapper(next_back) {
200 Some(r) => return Some(r),
201 None => continue,
202 }
203 }
204
205 None
206 }
207}
208
209pub enum Entry<'a, IDX, V> {
215 Vacant(VacantEntry<'a, IDX, V>),
217 Occupied(OccupiedEntry<'a, IDX, V>),
219}
220
221impl<'a, IDX, V> Entry<'a, IDX, V> {
222 pub fn or_insert(self, default: V) -> &'a mut V {
225 match self {
226 Self::Vacant(ent) => ent.insert(default),
227 Self::Occupied(ent) => ent.into_mut(),
228 }
229 }
230
231 pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
234 match self {
235 Self::Vacant(ent) => ent.insert(default()),
236 Self::Occupied(ent) => ent.into_mut(),
237 }
238 }
239
240 pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Self {
242 if let Self::Occupied(ent) = &mut self {
243 f(ent.get_mut());
244 }
245 self
246 }
247}
248
249impl<'a, IDX, V> Entry<'a, IDX, V>
250where
251 V: Default,
252{
253 #[allow(clippy::unwrap_or_default)]
257 pub fn or_default(self) -> &'a mut V {
258 self.or_insert_with(Default::default)
259 }
260}
261
262pub struct VacantEntry<'a, IDX, V> {
264 slot: &'a mut Option<V>,
265 _ty: PhantomData<IDX>,
266}
267
268impl<'a, IDX, V> VacantEntry<'a, IDX, V> {
269 pub fn insert(self, value: V) -> &'a mut V {
271 self.slot.insert(value)
272 }
273}
274
275pub struct OccupiedEntry<'a, IDX, V> {
277 slot: &'a mut Option<V>,
278 _ty: PhantomData<IDX>,
279}
280
281impl<'a, IDX, V> OccupiedEntry<'a, IDX, V> {
282 pub fn get(&self) -> &V {
284 self.slot.as_ref().expect("Occupied")
285 }
286
287 pub fn get_mut(&mut self) -> &mut V {
289 self.slot.as_mut().expect("Occupied")
290 }
291
292 pub fn into_mut(self) -> &'a mut V {
294 self.slot.as_mut().expect("Occupied")
295 }
296
297 pub fn insert(&mut self, value: V) -> V {
299 self.slot.replace(value).expect("Occupied")
300 }
301
302 pub fn remove(self) -> V {
304 self.slot.take().expect("Occupied")
305 }
306}