1#[derive(Debug, Clone, Default)]
11pub struct IdPool {
12 free_array: Vec<i32>,
13 next_index: i32,
14}
15
16impl IdPool {
17 pub fn new() -> IdPool {
19 IdPool {
20 free_array: Vec::with_capacity(32),
22 next_index: 0,
23 }
24 }
25
26 pub fn destroy(&mut self) {
28 *self = IdPool {
29 free_array: Vec::new(),
30 next_index: 0,
31 };
32 }
33
34 pub fn alloc_id(&mut self) -> i32 {
36 if let Some(id) = self.free_array.pop() {
37 return id;
38 }
39
40 let id = self.next_index;
41 self.next_index += 1;
42 id
43 }
44
45 pub fn free_id(&mut self, id: i32) {
47 debug_assert!(self.next_index > 0);
48 debug_assert!(0 <= id && id < self.next_index);
49 self.free_array.push(id);
50 }
51
52 pub fn id_count(&self) -> i32 {
54 self.next_index - self.free_array.len() as i32
55 }
56
57 pub fn id_capacity(&self) -> i32 {
59 self.next_index
60 }
61
62 pub fn id_bytes(&self) -> i32 {
64 (self.free_array.capacity() * core::mem::size_of::<i32>()) as i32
65 }
66
67 pub fn validate_free_id(&self, id: i32) {
69 if self.free_array.contains(&id) {
70 return;
71 }
72
73 debug_assert!(false, "id {id} is not free");
74 }
75
76 pub fn validate_used_id(&self, id: i32) {
78 debug_assert!(!self.free_array.contains(&id), "id {id} is free");
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[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 pool.validate_used_id(2);
102 assert_eq!(pool.id_count(), 2);
103
104 assert_eq!(pool.alloc_id(), 1);
105 assert_eq!(pool.id_count(), 3);
106
107 assert_eq!(pool.alloc_id(), 3);
109 assert_eq!(pool.id_capacity(), 4);
110
111 pool.destroy();
112 assert_eq!(pool.id_count(), 0);
113 }
114}