1mod tomb_vec_tests;
2
3use std::fmt::Debug;
4
5use std::cmp::Reverse;
6use std::collections::BinaryHeap;
7
8use std::{
9 mem,
10 ops::{Index, IndexMut},
11};
12
13use stable_id_traits::{CastUsize, Maximum};
14
15use crate::{Slot, Tec};
16
17impl<IndexT, DataT> Default for Tec<IndexT, DataT>
18where
19 IndexT: Maximum,
20{
21 fn default() -> Self {
22 Self {
23 vec: Default::default(),
24 next_free: Maximum::max_value(),
25 count: 0,
26 }
27 }
28}
29
30impl<IndexT, DataT> Tec<IndexT, DataT>
31where
32 IndexT: CastUsize + Ord + Copy + Maximum,
33{
34 fn set_sentinal(&mut self) {
35 self.next_free = Maximum::max_value();
36 }
37
38 fn check_free_link_invariant(&self, link: IndexT) -> bool {
39 let n = link.cast_to();
40 let m = IndexT::max_value().cast_to();
41
42 n <= self.capacity() || n == m
45 }
46
47 pub fn with_capacity(capacity: usize) -> Self {
48 Self {
49 vec: Vec::with_capacity(capacity),
50 ..Self::default()
51 }
52 }
53
54 pub fn len(&self) -> usize {
56 debug_assert_eq!(
57 self.iter().count(),
58 self.count,
59 "number of living items doesn't match self.count"
60 );
61 self.count
62 }
63
64 pub fn is_empty(&self) -> bool {
65 self.len() == 0
66 }
67
68 pub fn clear(&mut self) {
69 self.vec.clear();
70 self.count = 0;
71 self.set_sentinal();
72 }
73
74 pub fn alloc(&mut self, data: DataT) -> IndexT {
80 let original_free_index = self.next_free;
81
82 let next_slot = self.vec.get_mut(original_free_index.cast_to());
83
84 let result_index = if let Some(slot) = next_slot {
85 match slot {
86 Slot::Alive(..) => unimplemented!("next free slot is already occupied"),
87 Slot::Dead { next_free } => {
88 self.next_free = *next_free;
89 *slot = Slot::Alive(data);
90 }
91 }
92 original_free_index
93 } else {
94 let result_index = self.capacity();
95
96 assert!(
97 result_index < IndexT::max_value().cast_to(),
98 "exceed storage limit"
99 );
100
101 self.vec.push(Slot::Alive(data));
102 self.set_sentinal();
103 IndexT::cast_from(result_index)
104 };
105
106 self.count += 1;
107
108 debug_assert!(self.check_consistency());
109
110 result_index
111 }
112
113 pub fn remove(&mut self, index: IndexT) -> DataT {
115 assert!(!self.is_empty(), "removing an item from an empty container");
116
117 self.count -= 1;
123
124 let index_usize = index.cast_to();
125 let removal_candidate = &mut self.vec[index_usize];
126
127 let data = match removal_candidate {
128 Slot::Alive(_) => {
129 let mut temp_dead_slot = Slot::Dead {
131 next_free: self.next_free,
132 };
133 mem::swap(&mut temp_dead_slot, removal_candidate);
134
135 self.next_free = index;
138
139 match temp_dead_slot {
140 Slot::Alive(data) => data,
141 Slot::Dead { .. } => unreachable!("cannot unwrap a dead item"),
142 }
143 }
144 Slot::Dead { .. } => panic!("removing a dead item"),
145 };
146
147 data
148 }
149
150 pub fn get(&self, index: IndexT) -> Option<&DataT> {
151 self.vec.get(index.cast_to()).and_then(|slot| match slot {
152 Slot::Alive(data) => Some(data),
153 Slot::Dead { .. } => None,
154 })
155 }
156
157 pub fn get_mut(&mut self, index: IndexT) -> Option<&mut DataT> {
158 self.vec
159 .get_mut(index.cast_to())
160 .and_then(|slot| match slot {
161 Slot::Alive(data) => Some(data),
162 Slot::Dead { .. } => None,
163 })
164 }
165
166 pub fn iter(&self) -> impl Iterator<Item = &DataT> + DoubleEndedIterator {
167 self.vec.iter().filter_map(|data| match data {
168 Slot::Alive(data) => Some(data),
169 Slot::Dead { .. } => None,
170 })
171 }
172
173 pub fn iter_with_id(&self) -> impl Iterator<Item = (IndexT, &DataT)> + DoubleEndedIterator {
174 self.vec
175 .iter()
176 .enumerate()
177 .filter_map(|(id, data)| match data {
178 Slot::Alive(data) => Some((IndexT::cast_from(id), data)),
179 Slot::Dead { .. } => None,
180 })
181 }
182
183 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut DataT> + DoubleEndedIterator {
184 self.vec.iter_mut().filter_map(|data| match data {
185 Slot::Alive(data) => Some(data),
186 Slot::Dead { .. } => None,
187 })
188 }
189
190 pub fn iter_mut_with_id(
191 &mut self,
192 ) -> impl Iterator<Item = (IndexT, &mut DataT)> + DoubleEndedIterator {
193 self.vec
194 .iter_mut()
195 .enumerate()
196 .filter_map(|(id, data)| match data {
197 Slot::Alive(data) => Some((CastUsize::cast_from(id), data)),
198 Slot::Dead { .. } => None,
199 })
200 }
201
202 pub fn into_iter_with_id(self) -> impl Iterator<Item = (IndexT, DataT)> + DoubleEndedIterator {
203 self.vec
204 .into_iter()
205 .enumerate()
206 .filter_map(|(id, data)| match data {
207 Slot::Alive(data) => Some((CastUsize::cast_from(id), data)),
208 Slot::Dead { .. } => None,
209 })
210 }
211
212 pub fn capacity(&self) -> usize {
218 self.vec.len()
219 }
220
221 fn get_free_list(&self) -> Vec<IndexT> {
222 let max = Maximum::max_value();
223 let capacity = self.capacity();
224 let len = self.len();
225 assert!(capacity >= len);
226
227 let mut cur = self.next_free;
228 let mut acc = Vec::with_capacity(capacity - len);
229
230 loop {
231 if cur == max {
232 break;
233 }
234
235 if let Slot::Dead { next_free } = &self.vec[cur.cast_to()] {
236 acc.push(cur);
237 cur = *next_free;
238 } else {
239 unreachable!("found a living slot in free list")
240 }
241 }
242 acc
243 }
244
245 fn heap_based_coalesce<F>(&mut self, mut f: F) -> usize
255 where
256 F: FnMut(IndexT, IndexT),
257 {
258 let mut free_heap = {
259 let free_list: Vec<_> = self.get_free_list().into_iter().map(Reverse).collect();
260
261 BinaryHeap::from(free_list)
262 };
263 let removed_len = free_heap.len();
264
265 let mut backward_cursor = self.capacity() - 1;
266 let max = Maximum::max_value();
267 'main_loop: while let Some(Reverse(forward_cursor)) = free_heap.pop() {
268 let mut living_target = loop {
270 let swap_target = &mut self.vec[backward_cursor];
271
272 let forward_cursor_usize = forward_cursor.cast_to();
273 if forward_cursor_usize >= backward_cursor {
274 break 'main_loop;
275 }
276
277 if matches!(swap_target, Slot::Alive(_)) {
278 let mut dummy = Slot::Dead { next_free: max };
281 mem::swap(swap_target, &mut dummy);
282 break dummy;
283 }
284
285 backward_cursor -= 1;
286
287 debug_assert!(backward_cursor != 0);
289 };
290
291 let dead_target = &mut self.vec[forward_cursor.cast_to()];
292 debug_assert!(matches!(dead_target, Slot::Dead { .. }));
293
294 mem::swap(&mut living_target, dead_target);
296 f(IndexT::cast_from(backward_cursor), forward_cursor);
297 }
298
299 removed_len
300 }
301
302 pub fn coalesce<F>(&mut self, f: F)
312 where
313 F: FnMut(IndexT, IndexT),
314 {
315 let next_usize = self.next_free.cast_to();
316 let capacity = self.capacity();
317 if next_usize >= capacity {
318 return;
319 } else {
320 debug_assert!(!self.is_empty());
322 }
323
324 let removed_len = self.heap_based_coalesce(f);
325
326 self.vec.truncate(capacity - removed_len);
328
329 self.set_sentinal();
331
332 debug_assert_eq!(self.len(), self.capacity());
333 }
334
335 fn check_consistency(&self) -> bool {
336 use std::collections::HashSet;
337
338 debug_assert!(self.check_free_link_invariant(self.next_free));
339
340 if self.is_empty() {
341 debug_assert!(self.next_free == IndexT::max_value());
342 debug_assert!(self.vec.is_empty());
343 return true;
344 }
345
346 let dead_set: HashSet<usize> = self
348 .vec
349 .iter()
350 .enumerate()
351 .filter(|(_, slot)| matches!(slot, Slot::Dead { .. }))
352 .map(|(i, _)| i)
353 .collect();
354
355 let linked_dead_set = self
356 .get_free_list()
357 .into_iter()
358 .map(CastUsize::cast_to)
359 .collect();
360
361 assert_eq!(dead_set, linked_dead_set);
365
366 true
367 }
368}
369
370impl<IndexT, DataT> Tec<IndexT, DataT>
371where
372 IndexT: CastUsize + Ord + Copy + Maximum,
373 DataT: Clone,
374{
375 pub fn populate(data: DataT, count: usize) -> Self {
379 let vec = vec![Slot::Alive(data); count];
380 let count = vec.len();
381
382 Self {
383 vec,
384 next_free: Maximum::max_value(),
385 count,
386 }
387 }
388}
389
390impl<IndexT, DataT> Tec<IndexT, DataT>
391where
392 IndexT: CastUsize + Ord + Copy + Maximum,
393 DataT: Clone + Default,
394{
395 pub fn populate_defaults(count: usize) -> Self {
399 Self::populate(Default::default(), count)
400 }
401}
402
403impl<IndexT, DataT> Tec<IndexT, DataT>
404where
405 IndexT: CastUsize + Ord + Copy + Maximum,
406 DataT: Default,
407{
408 pub fn alloc_default(&mut self) -> IndexT {
409 self.alloc(Default::default())
410 }
411}
412
413impl<IndexT, DataT> Index<IndexT> for Tec<IndexT, DataT>
414where
415 IndexT: CastUsize + Ord + Copy + Maximum,
416{
417 type Output = DataT;
418
419 fn index(&self, index: IndexT) -> &Self::Output {
420 self.get(index).expect("element not exist")
421 }
422}
423
424impl<IndexT, DataT> IndexMut<IndexT> for Tec<IndexT, DataT>
425where
426 IndexT: CastUsize + Ord + Copy + Maximum,
427{
428 fn index_mut(&mut self, index: IndexT) -> &mut Self::Output {
429 self.get_mut(index).expect("element not exist")
430 }
431}
432
433impl<IndexT, DataT> Debug for Tec<IndexT, DataT>
434where
435 IndexT: Debug,
436 DataT: Debug,
437{
438 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
439 f.debug_struct("Tec")
440 .field("vec", &self.vec)
441 .field("next_free", &self.next_free)
442 .field("count", &self.count)
443 .finish()
444 }
445}