1#[derive(Debug, Clone, Default)]
11pub struct IdPool {
12 pub(crate) free_array: Vec<i32>,
14 pub(crate) next_index: i32,
15}
16
17impl IdPool {
18 pub fn new() -> IdPool {
20 IdPool {
21 free_array: Vec::with_capacity(32),
23 next_index: 0,
24 }
25 }
26
27 pub fn destroy(&mut self) {
29 *self = IdPool {
30 free_array: Vec::new(),
31 next_index: 0,
32 };
33 }
34
35 pub fn alloc_id(&mut self) -> i32 {
37 if let Some(id) = self.free_array.pop() {
38 return id;
39 }
40
41 let id = self.next_index;
42 self.next_index += 1;
43 id
44 }
45
46 pub fn free_id(&mut self, id: i32) {
52 debug_assert!(self.next_index > 0);
53 debug_assert!(0 <= id && id < self.next_index);
54 self.free_array.push(id);
55 }
56
57 pub fn id_count(&self) -> i32 {
59 self.next_index - self.free_array.len() as i32
60 }
61
62 pub fn id_capacity(&self) -> i32 {
64 self.next_index
65 }
66
67 pub fn id_bytes(&self) -> i32 {
69 (self.free_array.capacity() * core::mem::size_of::<i32>()) as i32
71 }
72
73 pub fn validate_free_id(&self, id: i32) {
75 if self.free_array.contains(&id) {
76 return;
77 }
78
79 debug_assert!(false, "id {id} is not free");
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
89 fn alloc_free_recycle() {
90 let mut pool = IdPool::new();
91
92 assert_eq!(pool.alloc_id(), 0);
93 assert_eq!(pool.alloc_id(), 1);
94 assert_eq!(pool.alloc_id(), 2);
95 assert_eq!(pool.id_count(), 3);
96 assert_eq!(pool.id_capacity(), 3);
97
98 pool.free_id(1);
100 pool.validate_free_id(1);
101 assert_eq!(pool.id_count(), 2);
102
103 assert_eq!(pool.alloc_id(), 1);
104 assert_eq!(pool.id_count(), 3);
105
106 assert_eq!(pool.alloc_id(), 3);
108 assert_eq!(pool.id_capacity(), 4);
109
110 pool.destroy();
111 assert_eq!(pool.id_count(), 0);
112 }
113}