1use crate::elem::ListElem;
4use crate::Index;
5use std::fmt;
6
7#[derive(Debug, PartialEq, Eq)]
12pub enum IndexError {
13 IndexIsNone,
15 IndexOutOfBounds,
17 ElementIsFree,
19 ElementIsFreeSentinel,
21 BrokenPrevLink,
23 BrokenNextLink,
25}
26
27impl std::error::Error for IndexError {}
28
29impl fmt::Display for IndexError {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::IndexIsNone => write!(f, "Index is NONE"),
33 Self::IndexOutOfBounds => write!(f, "Index is out of bounds"),
34 Self::ElementIsFree => write!(f, "Element is on the free list"),
35 Self::ElementIsFreeSentinel => write!(f, "Element is the free list sentinel"),
36 Self::BrokenPrevLink => write!(f, "Element's previous link is inconsistent"),
37 Self::BrokenNextLink => write!(f, "Element's next link is inconsistent"),
38 }
39 }
40}
41
42#[derive(Clone, Debug)]
58pub struct ElemPool<T> {
59 elems: Vec<ListElem<T>>,
61 freed: usize,
63 used: usize,
66}
67
68impl<T> Default for ElemPool<T> {
69 fn default() -> Self {
72 let sentinel_index = Self::free_sentinel_index();
73 let mut sentinel_elem = ListElem::default();
74 let _ = sentinel_elem.new_links(sentinel_index, sentinel_index);
76 Self {
77 elems: vec![sentinel_elem],
78 freed: 0,
79 used: 0,
80 }
81 }
82}
83
84impl<T> ElemPool<T> {
86 pub fn new() -> Self {
91 Default::default()
92 }
93
94 #[inline(always)]
96 fn free_sentinel_index() -> Index<T> {
97 Index::from(0u32)
98 }
99
100 #[inline]
106 pub fn len(&self) -> usize {
107 self.used
108 }
109
110 #[inline]
112 pub fn is_empty(&self) -> bool {
113 self.used == 0
114 }
115
116 #[inline]
120 pub fn capacity(&self) -> usize {
121 self.elems.len() - 1
122 }
123
124 #[inline]
126 pub fn free_len(&self) -> usize {
127 self.freed
128 }
129
130 #[inline]
136 pub fn list_count(&self) -> usize {
137 self.capacity() - self.used - self.freed
138 }
139
140 #[inline]
154 pub fn reserve(&mut self, additional: usize) {
155 self.elems.reserve(additional);
156 }
157
158 #[inline]
163 pub fn contains(&self, index: Index<T>) -> bool {
164 index
165 .get()
166 .and_then(|n| self.elems.get(n))
167 .is_some_and(|e| e.is_used())
168 }
169
170 #[inline]
183 pub fn validate_index(&self, index: Index<T>) -> Result<(), IndexError> {
184 let ndx = index.get().ok_or(IndexError::IndexIsNone)?;
185 let elem = self.elems.get(ndx).ok_or(IndexError::IndexOutOfBounds)?;
186 if !elem.is_used() {
187 return Err(IndexError::ElementIsFree);
188 }
189 let prev_ndx = elem.prev.get().ok_or(IndexError::BrokenPrevLink)?;
190 let prev_elem = self
191 .elems
192 .get(prev_ndx)
193 .ok_or(IndexError::BrokenPrevLink)?;
194 if prev_elem.next != index {
195 return Err(IndexError::BrokenPrevLink);
196 }
197 let next_ndx = elem.next.get().ok_or(IndexError::BrokenNextLink)?;
198 let next_elem = self
199 .elems
200 .get(next_ndx)
201 .ok_or(IndexError::BrokenNextLink)?;
202 if next_elem.prev != index {
203 return Err(IndexError::BrokenNextLink);
204 }
205 Ok(())
206 }
207
208 pub(crate) fn index_new(&mut self) -> Result<Index<T>, IndexError> {
215 let free_sentinel_ndx = Self::free_sentinel_index();
216 let ndx_to_reuse = self.next(free_sentinel_ndx);
217
218 if ndx_to_reuse != free_sentinel_ndx {
219 self.index_linkout(ndx_to_reuse)?;
221 self.freed -= 1;
222 Ok(ndx_to_reuse)
223 } else {
224 let ndx = Index::from(self.elems.len());
227 let mut new_elem = ListElem::default();
228 let _ = new_elem.new_links(ndx, ndx);
230 self.elems.push(new_elem);
231 Ok(ndx)
232 }
233 }
234
235 pub(crate) fn index_del(&mut self, index: Index<T>) -> Result<(), IndexError> {
241 let free_sentinel_ndx = Self::free_sentinel_index();
242 if index == free_sentinel_ndx {
243 return Err(IndexError::ElementIsFreeSentinel);
244 }
245 self.get(index)?;
247 self.index_link_after(index, free_sentinel_ndx)?;
249 self.freed += 1;
250 Ok(())
251 }
252
253 #[inline]
255 pub(crate) fn get(&self, index: Index<T>) -> Result<&ListElem<T>, IndexError> {
256 let n = index.get().ok_or(IndexError::IndexIsNone)?;
257 self.elems.get(n).ok_or(IndexError::IndexOutOfBounds)
258 }
259
260 #[inline]
262 pub(crate) fn get_mut(&mut self, index: Index<T>) -> Result<&mut ListElem<T>, IndexError> {
263 let n = index.get().ok_or(IndexError::IndexIsNone)?;
264 self.elems.get_mut(n).ok_or(IndexError::IndexOutOfBounds)
265 }
266
267 #[inline]
269 pub(crate) fn next(&self, index: Index<T>) -> Index<T> {
270 self.get(index).map(|i| i.next).unwrap_or_default()
272 }
273
274 #[inline]
276 pub(crate) fn prev(&self, index: Index<T>) -> Index<T> {
277 self.get(index).map(|i| i.prev).unwrap_or_default()
278 }
279
280 #[inline]
282 pub(crate) fn data(&self, index: Index<T>) -> Option<&T> {
283 self.get(index).ok().and_then(|i| i.data.as_ref())
284 }
285
286 #[inline]
288 pub(crate) fn data_mut(&mut self, index: Index<T>) -> Option<&mut T> {
289 self.get_mut(index).ok().and_then(|i| i.data.as_mut())
290 }
291
292 #[inline]
297 pub(crate) fn data_swap(&mut self, index: Index<T>, data: Option<T>) -> Option<T> {
298 let elem = self.get_mut(index).ok()?;
299 let old_data = elem.new_data(data);
300 match (old_data.is_some(), elem.data.is_some()) {
301 (false, true) => self.used += 1, (true, false) => self.used -= 1, _ => {} }
305 old_data
306 }
307
308 #[inline]
311 pub(crate) fn index_linkout(&mut self, index: Index<T>) -> Result<(), IndexError> {
312 let (prev_ndx, next_ndx) = self.get_mut(index)?.new_links(index, index);
313 self.get_mut(prev_ndx)?.new_next(next_ndx);
314 self.get_mut(next_ndx)?.new_prev(prev_ndx);
315 Ok(())
316 }
317
318 #[inline]
320 pub(crate) fn index_link_after(
321 &mut self,
322 this: Index<T>,
323 after: Index<T>,
324 ) -> Result<(), IndexError> {
325 let next_ndx = self.get_mut(after)?.new_next(this);
326 let _ = self.get_mut(this)?.new_links(after, next_ndx);
327 self.get_mut(next_ndx)?.new_prev(this);
328 Ok(())
329 }
330
331 #[inline]
333 pub(crate) fn index_link_before(
334 &mut self,
335 this: Index<T>,
336 before: Index<T>,
337 ) -> Result<(), IndexError> {
338 let prev_ndx = self.get_mut(before)?.new_prev(this);
339 let _ = self.get_mut(this)?.new_links(prev_ndx, before);
340 self.get_mut(prev_ndx)?.new_next(this);
341 Ok(())
342 }
343}
344
345impl<T> fmt::Display for ElemPool<T>
346where
347 T: fmt::Display,
348{
349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350 writeln!(
351 f,
352 "ElemPool used {}/{}, {} free:",
353 self.len(),
354 self.capacity(),
355 self.freed
356 )?;
357 for (i, elem) in self.elems.iter().enumerate() {
358 writeln!(f, " [{}]: {}", i, elem)?;
359 }
360 Ok(())
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use super::*;
367 use crate::list::PieList;
368
369 fn create_pool_with_elems<T>(count: usize, default_data: T) -> (ElemPool<T>, Vec<Index<T>>)
371 where
372 T: Clone,
373 {
374 let mut pool = ElemPool::new();
375 let mut indices = Vec::new();
376 for _i in 0..count {
377 let index = pool.index_new().unwrap();
378 pool.data_swap(index, Some(default_data.clone()));
380 indices.push(index);
381 }
382 (pool, indices)
383 }
384
385 #[test]
386 fn test_pool_creation_and_len() {
387 let pool: ElemPool<i32> = ElemPool::new();
388 assert_eq!(pool.len(), 0); assert_eq!(pool.capacity(), 0);
390 assert!(pool.is_empty());
391 assert_eq!(pool.elems.len(), 1); }
393
394 #[test]
395 fn test_index_new_and_len() {
396 let (pool, indices) = create_pool_with_elems(3, 100);
397 assert_eq!(pool.len(), 3); assert_eq!(pool.capacity(), 3);
399 assert!(!pool.is_empty());
400 assert_eq!(indices.len(), 3);
401 assert_eq!(indices[0].get(), Some(1));
402 assert_eq!(indices[1].get(), Some(2));
403 assert_eq!(indices[2].get(), Some(3));
404 }
405
406 #[test]
407 fn test_del_and_reuse() {
408 let (mut pool, indices) = create_pool_with_elems(5, 0);
409 assert_eq!(pool.len(), 5);
410 assert_eq!(pool.freed, 0);
411
412 let deleted_index = indices[2];
413 let _data = pool.data_swap(deleted_index, None);
415 assert_eq!(pool.len(), 4);
417
418 pool.index_del(deleted_index).unwrap();
420 assert_eq!(pool.freed, 1);
421 assert!(!pool.contains(deleted_index));
422 assert_eq!(pool.next(ElemPool::free_sentinel_index()), deleted_index);
423
424 let reused_index = pool.index_new().unwrap();
426 assert_eq!(reused_index, deleted_index);
427 assert_eq!(pool.len(), 4);
429 assert_eq!(pool.freed, 0);
430
431 pool.data_swap(reused_index, Some(999));
433 assert_eq!(pool.len(), 5);
434 }
435
436 #[test]
437 fn test_del_errors() {
438 let mut pool: ElemPool<i32> = ElemPool::new();
439 let index = pool.index_new().unwrap();
440 pool.data_swap(index, Some(100));
441
442 assert_eq!(
444 pool.index_del(ElemPool::free_sentinel_index()),
445 Err(IndexError::ElementIsFreeSentinel)
446 );
447
448 }
453
454 #[test]
455 fn test_contains() {
456 let (pool, indices) = create_pool_with_elems(2, 0);
457 assert!(pool.contains(indices[0]));
458 assert!(pool.contains(indices[1]));
459 let nonexistent_index = Index::from(99 as u32);
460 assert!(!pool.contains(nonexistent_index));
461 assert!(!pool.contains(Index::NONE));
462 }
463
464 #[test]
465 fn test_linking_logic() {
466 let (mut pool, indices) = create_pool_with_elems(3, 0);
467 let i1 = indices[0];
468 let i2 = indices[1];
469 let i3 = indices[2];
470
471 assert_eq!(pool.next(i1), i1);
473 assert_eq!(pool.prev(i1), i1);
474
475 pool.index_link_after(i2, i1).unwrap();
477 pool.index_link_after(i3, i2).unwrap();
478 pool.get_mut(i1).unwrap().new_prev(i3);
480 pool.get_mut(i3).unwrap().new_next(i1);
481
482 assert_eq!(pool.next(i1), i2);
483 assert_eq!(pool.next(i2), i3);
484 assert_eq!(pool.next(i3), i1);
485
486 assert_eq!(pool.prev(i1), i3);
487 assert_eq!(pool.prev(i3), i2);
488 assert_eq!(pool.prev(i2), i1);
489
490 pool.index_linkout(i2).unwrap();
492
493 assert_eq!(pool.next(i2), i2);
495 assert_eq!(pool.prev(i2), i2);
496 assert_eq!(pool.next(i1), i3);
498 assert_eq!(pool.prev(i3), i1);
499
500 pool.index_link_before(i2, i3).unwrap();
502
503 assert_eq!(pool.next(i1), i2);
504 assert_eq!(pool.next(i2), i3);
505 assert_eq!(pool.prev(i3), i2);
506 assert_eq!(pool.prev(i2), i1);
507 }
508
509 #[test]
510 fn test_validate_index() {
511 let (mut pool, _) = create_pool_with_elems(0, 0);
513 let mut list = PieList::new(&mut pool);
514 list.push_back(10, &mut pool).unwrap();
515 list.push_back(20, &mut pool).unwrap();
516 list.push_back(30, &mut pool).unwrap();
517
518 let i1 = pool.next(list.sentinel);
519 let i2 = pool.next(i1);
520 let i3 = pool.next(i2);
521
522 assert_eq!(pool.validate_index(i1), Ok(()));
524 assert_eq!(pool.validate_index(i2), Ok(()));
525 assert_eq!(pool.validate_index(i3), Ok(()));
526
527 assert_eq!(
529 pool.validate_index(Index::NONE),
530 Err(IndexError::IndexIsNone)
531 );
532 assert_eq!(
533 pool.validate_index(Index::from(99_u32)),
534 Err(IndexError::IndexOutOfBounds)
535 );
536
537 pool.data_swap(i2, None);
539 assert_eq!(pool.validate_index(i2), Err(IndexError::ElementIsFree));
540 pool.data_swap(i2, Some(20)); pool.get_mut(i1).unwrap().next = i3;
545
546 assert_eq!(pool.validate_index(i2), Err(IndexError::BrokenPrevLink));
548 assert_eq!(pool.validate_index(i1), Err(IndexError::BrokenNextLink));
550 }
551}