solverforge_solver/heuristic/move/
arena.rs1use std::fmt::Debug;
8use std::mem::MaybeUninit;
9use std::ptr;
10
11pub struct MoveArena<M> {
50 storage: Vec<MaybeUninit<M>>,
52 len: usize,
54}
55
56impl<M> MoveArena<M> {
57 #[inline]
59 pub fn new() -> Self {
60 Self {
61 storage: Vec::new(),
62 len: 0,
63 }
64 }
65
66 #[inline]
68 pub fn with_capacity(capacity: usize) -> Self {
69 Self {
70 storage: Vec::with_capacity(capacity),
71 len: 0,
72 }
73 }
74
75 #[inline]
80 pub fn reset(&mut self) {
81 for i in 0..self.len {
85 unsafe {
86 ptr::drop_in_place(self.storage[i].as_mut_ptr());
87 }
88 }
89 self.len = 0;
90 }
91
92 #[inline]
94 pub fn push(&mut self, m: M) {
95 if self.len < self.storage.len() {
96 self.storage[self.len] = MaybeUninit::new(m);
98 } else {
99 self.storage.push(MaybeUninit::new(m));
101 }
102 self.len += 1;
103 }
104
105 #[inline]
107 pub fn len(&self) -> usize {
108 self.len
109 }
110
111 #[inline]
113 pub fn is_empty(&self) -> bool {
114 self.len == 0
115 }
116
117 #[inline]
119 pub fn iter(&self) -> impl Iterator<Item = &M> {
120 self.storage[..self.len]
121 .iter()
122 .map(|slot| unsafe { slot.assume_init_ref() })
123 }
124
125 #[inline]
127 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut M> {
128 self.storage[..self.len]
129 .iter_mut()
130 .map(|slot| unsafe { slot.assume_init_mut() })
131 }
132
133 #[inline]
135 pub fn get(&self, index: usize) -> Option<&M> {
136 if index < self.len {
137 Some(unsafe { self.storage[index].assume_init_ref() })
138 } else {
139 None
140 }
141 }
142
143 #[inline]
145 pub fn extend<I: IntoIterator<Item = M>>(&mut self, iter: I) {
146 for m in iter {
147 self.push(m);
148 }
149 }
150
151 #[inline]
153 pub fn capacity(&self) -> usize {
154 self.storage.capacity()
155 }
156}
157
158impl<M> Default for MoveArena<M> {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164impl<M: Debug> Debug for MoveArena<M> {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 f.debug_struct("MoveArena")
167 .field("len", &self.len)
168 .field("capacity", &self.storage.capacity())
169 .finish()
170 }
171}
172
173impl<M> Drop for MoveArena<M> {
174 fn drop(&mut self) {
175 for i in 0..self.len {
177 unsafe {
178 ptr::drop_in_place(self.storage[i].as_mut_ptr());
179 }
180 }
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_arena_basic() {
190 let mut arena: MoveArena<i32> = MoveArena::new();
191 assert!(arena.is_empty());
192
193 arena.push(1);
194 arena.push(2);
195 arena.push(3);
196
197 assert_eq!(arena.len(), 3);
198 assert_eq!(arena.get(0), Some(&1));
199 assert_eq!(arena.get(1), Some(&2));
200 assert_eq!(arena.get(2), Some(&3));
201 assert_eq!(arena.get(3), None);
202 }
203
204 #[test]
205 fn test_arena_reset() {
206 let mut arena: MoveArena<i32> = MoveArena::new();
207 arena.push(1);
208 arena.push(2);
209 arena.push(3);
210
211 let capacity_before = arena.capacity();
212
213 arena.reset();
214
215 assert!(arena.is_empty());
216 assert_eq!(arena.len(), 0);
217 assert_eq!(arena.capacity(), capacity_before);
219 }
220
221 #[test]
222 fn test_arena_reuse_after_reset() {
223 let mut arena: MoveArena<i32> = MoveArena::new();
224
225 arena.push(1);
227 arena.push(2);
228 assert_eq!(arena.len(), 2);
229
230 arena.reset();
231
232 arena.push(10);
234 arena.push(20);
235 arena.push(30);
236 assert_eq!(arena.len(), 3);
237 assert_eq!(arena.get(0), Some(&10));
238 assert_eq!(arena.get(1), Some(&20));
239 assert_eq!(arena.get(2), Some(&30));
240 }
241
242 #[test]
243 fn test_arena_iter() {
244 let mut arena: MoveArena<i32> = MoveArena::new();
245 arena.push(1);
246 arena.push(2);
247 arena.push(3);
248
249 let collected: Vec<_> = arena.iter().copied().collect();
250 assert_eq!(collected, vec![1, 2, 3]);
251 }
252
253 #[test]
254 fn test_arena_extend() {
255 let mut arena: MoveArena<i32> = MoveArena::new();
256 arena.extend(vec![1, 2, 3]);
257 assert_eq!(arena.len(), 3);
258
259 let collected: Vec<_> = arena.iter().copied().collect();
260 assert_eq!(collected, vec![1, 2, 3]);
261 }
262
263 #[test]
264 fn test_arena_with_capacity() {
265 let arena: MoveArena<i32> = MoveArena::with_capacity(100);
266 assert!(arena.is_empty());
267 assert!(arena.capacity() >= 100);
268 }
269}