1#![doc = include_str!("../README.md")]
2
3use std::{cmp::Ordering, fmt, marker::PhantomData, num::NonZeroU32, ops};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
6pub struct Span {
7 start: u32,
8 end: u32,
9}
10
11impl Span {
12 pub const UNDEFINED: Self = Self { start: 0, end: 0 };
13
14 pub const fn new(start: u32, end: u32) -> Self {
15 debug_assert!(start <= end, "Span start must be <= end");
16 Span { start, end }
17 }
18
19 pub fn is_defined(&self) -> bool {
20 self.start != self.end
21 }
22
23 pub fn length(&self) -> u32 {
24 self.end - self.start
25 }
26}
27
28impl std::ops::Index<Span> for str {
29 type Output = str;
30
31 #[inline]
32 fn index(&self, span: Span) -> &str {
33 &self[span.start as usize..span.end as usize]
34 }
35}
36
37type Index = NonZeroU32;
38
39pub struct Handle<T> {
40 index: Index,
41 marker: PhantomData<T>,
42}
43
44impl<T> Clone for Handle<T> {
45 fn clone(&self) -> Self {
46 *self
47 }
48}
49
50impl<T> Copy for Handle<T> {}
51
52impl<T> PartialEq for Handle<T> {
53 fn eq(&self, other: &Self) -> bool {
54 self.index == other.index
55 }
56}
57
58impl<T> Eq for Handle<T> {}
59
60impl<T> PartialOrd for Handle<T> {
61 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
62 Some(self.cmp(other))
63 }
64}
65
66impl<T> Ord for Handle<T> {
67 fn cmp(&self, other: &Self) -> Ordering {
68 self.index.cmp(&other.index)
69 }
70}
71
72impl<T> fmt::Debug for Handle<T> {
73 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
74 write!(formatter, "[{}]", self.index)
75 }
76}
77
78impl<T> Handle<T> {
79 #[cfg(test)]
80 pub const DUMMY: Self = Handle {
81 index: NonZeroU32::new(u32::MAX).unwrap(),
82 marker: PhantomData,
83 };
84
85 #[inline]
86 pub const fn new(index: Index) -> Self {
87 Handle {
88 index,
89 marker: PhantomData,
90 }
91 }
92
93 #[inline]
94 pub const fn index(self) -> usize {
95 let index = self.index.get() - 1;
96 index as usize
97 }
98
99 #[inline]
100 fn from_usize(index: usize) -> Self {
101 let handle_index = u32::try_from(index + 1)
102 .ok()
103 .and_then(Index::new)
104 .expect("failed to insert into arena");
105 Handle::new(handle_index)
106 }
107
108 #[inline]
109 const unsafe fn from_usize_unchecked(index: usize) -> Self {
110 Handle::new(Index::new_unchecked((index + 1) as u32))
111 }
112}
113
114#[derive(Clone)]
115pub struct Arena<T> {
116 data: Vec<T>,
117 span_info: Vec<Span>, free_spans: Vec<Span>, }
120
121impl<T: Clone> Default for Arena<T> {
122 fn default() -> Self {
123 Self::new()
124 }
125}
126
127impl<T: fmt::Debug + Clone> fmt::Debug for Arena<T> {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 f.debug_map().entries(self.iter()).finish()
130 }
131}
132
133impl<T: Clone> Arena<T> {
134 pub const fn new() -> Self {
135 Arena {
136 data: Vec::new(),
137 span_info: Vec::new(),
138 free_spans: Vec::new(),
139 }
140 }
141
142 pub fn with_capacity(capacity: usize) -> Self {
143 Arena {
144 data: Vec::with_capacity(capacity),
145 span_info: Vec::new(),
146 free_spans: Vec::new(),
147 }
148 }
149
150 pub fn into_inner(self) -> Vec<T> {
151 self.data
152 }
153
154 pub fn len(&self) -> usize {
155 self.span_info
156 .iter()
157 .map(|span| span.length() as usize)
158 .sum()
159 }
160
161 pub fn capacity(&self) -> usize {
162 self.data.capacity()
163 }
164
165 pub fn buffer_len(&self) -> usize {
166 self.data.len()
167 }
168
169 pub fn is_empty(&self) -> bool {
170 self.span_info.is_empty()
171 }
172
173 pub fn iter(&self) -> impl DoubleEndedIterator<Item = (Handle<T>, &T)> + '_ {
174 self.span_info
175 .iter()
176 .flat_map(move |&span| (span.start..span.end))
177 .map(move |i| {
178 let handle = unsafe { Handle::from_usize_unchecked(i as usize) };
179 (handle, &self.data[i as usize])
180 })
181 }
182
183 pub fn drain(&mut self) -> impl Iterator<Item = (Handle<T>, T, Span)> + '_ {
184 let arena = std::mem::take(self);
185 arena
186 .data
187 .into_iter()
188 .zip(
189 arena
190 .span_info
191 .into_iter()
192 .flat_map(|span| std::iter::repeat_n(span, span.length() as usize)),
193 )
194 .enumerate()
195 .map(|(i, (v, span))| unsafe { (Handle::from_usize_unchecked(i), v, span) })
196 }
197
198 pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (Handle<T>, &mut T)> + '_ {
199 let data_ptr = self.data.as_mut_ptr();
200 self.span_info
201 .iter()
202 .flat_map(move |&span| (span.start..span.end))
203 .map(move |i| {
204 let handle = unsafe { Handle::from_usize_unchecked(i as usize) };
205 let value_ref = unsafe { &mut *data_ptr.add(i as usize) };
206 (handle, value_ref)
207 })
208 }
209
210 fn find_free_span(&mut self, count: u32) -> Option<Span> {
211 if let Some(pos) = self
212 .free_spans
213 .iter()
214 .position(|span| span.length() >= count)
215 {
216 let span = self.free_spans.remove(pos);
217
218 if span.length() > count {
219 let remaining_span = Span {
220 start: span.start + count,
221 end: span.end,
222 };
223 match self.free_spans.binary_search(&remaining_span) {
224 Ok(idx) => self.free_spans.insert(idx, remaining_span),
225 Err(idx) => self.free_spans.insert(idx, remaining_span),
226 }
227 }
228 Some(Span {
229 start: span.start,
230 end: span.start + count,
231 })
232 } else {
233 None
234 }
235 }
236
237 pub fn append(&mut self, value: T, count: usize) -> Handle<T> {
238 assert!(count > 0);
239 let u_count = count as u32;
240
241 if let Some(target_span) = self.find_free_span(u_count) {
242 let start = target_span.start as usize;
243 let end = target_span.end as usize;
244 for i in start..end - 1 {
245 self.data[i] = value.clone();
246 }
247 self.data[end - 1] = value;
248
249 match self
250 .span_info
251 .binary_search_by_key(&target_span.start, |s| s.start)
252 {
253 Ok(_) => unreachable!("should not find existing span at reused start"),
254 Err(idx) => self.span_info.insert(idx, target_span),
255 }
256
257 return Handle::from_usize(start);
258 }
259
260 let start_idx = self.data.len();
261 let end_idx = start_idx + count;
262
263 self.data.resize(end_idx, value);
264
265 let new_span = Span::new(start_idx as u32, end_idx as u32);
266 self.span_info.push(new_span);
267
268 Handle::from_usize(start_idx)
269 }
270
271 pub fn fetch_if<F: Fn(&T) -> bool>(&self, fun: F) -> Option<Handle<T>> {
272 self.iter()
273 .find(|(_, data)| fun(data))
274 .map(|(handle, _)| handle)
275 }
276
277 pub fn fetch_if_or_append<F: Fn(&T, &T) -> bool>(
278 &mut self,
279 value: T,
280 count: usize,
281 fun: F,
282 ) -> Handle<T> {
283 let found_handle = self
284 .iter()
285 .find(|(_, data)| fun(data, &value))
286 .map(|(h, _)| h);
287
288 if let Some(handle) = found_handle {
289 handle
290 } else {
291 self.append(value, count)
292 }
293 }
294
295 pub fn fetch_or_append(&mut self, value: T, count: usize) -> Handle<T>
296 where
297 T: PartialEq,
298 {
299 self.fetch_if_or_append(value, count, T::eq)
300 }
301
302 pub fn try_get(&self, handle: Handle<T>) -> Result<&T, &'static str> {
303 let index = handle.index();
304 if index < self.data.len()
305 && self
306 .span_info
307 .binary_search_by(|probe| {
308 if index < probe.start as usize {
309 Ordering::Greater
310 } else if index >= probe.end as usize {
311 Ordering::Less
312 } else {
313 Ordering::Equal
314 }
315 })
316 .is_ok()
317 {
318 Ok(unsafe { self.data.get_unchecked(index) })
319 } else {
320 Err("Handle out of range or points to freed memory")
321 }
322 }
323
324 pub fn get_mut(&mut self, handle: Handle<T>) -> &mut T {
325 let index = handle.index();
326 let data_len = self.data.len();
327 let span_exists = self
328 .span_info
329 .binary_search_by(|probe| {
330 if index < probe.start as usize {
331 Ordering::Greater
332 } else if index >= probe.end as usize {
333 Ordering::Less
334 } else {
335 Ordering::Equal
336 }
337 })
338 .is_ok();
339
340 if index < data_len && span_exists {
341 unsafe { self.data.get_unchecked_mut(index) }
342 } else {
343 panic!("Handle out of range or points to freed memory");
344 }
345 }
346
347 pub fn clear(&mut self) {
348 self.data.clear();
349 self.span_info.clear();
350 self.free_spans.clear();
351 }
352
353 pub fn get_span(&self, handle: Handle<T>) -> Span {
354 let index = handle.index() as u32;
355 self.span_info
356 .binary_search_by(|probe| {
357 if index < probe.start {
358 Ordering::Greater
359 } else if index >= probe.end {
360 Ordering::Less
361 } else {
362 Ordering::Equal
363 }
364 })
365 .map(|idx| self.span_info[idx])
366 .expect("Handle does not point to a valid span")
367 }
368
369 pub fn check_contains_handle(&self, handle: Handle<T>) -> Result<(), &'static str> {
370 self.try_get(handle).map(|_| ())
371 }
372
373 pub fn retain_mut<P>(&mut self, mut predicate: P)
374 where
375 P: FnMut(Handle<T>, &mut T) -> bool,
376 {
377 let mut handles_to_free = Vec::new();
378 let data_ptr = self.data.as_mut_ptr();
379
380 for span in &self.span_info {
381 let mut keep_span = false;
382 for i in span.start..span.end {
383 let handle = unsafe { Handle::from_usize_unchecked(i as usize) };
384 let value_ref = unsafe { &mut *data_ptr.add(i as usize) };
385 if predicate(handle, value_ref) {
386 keep_span = true;
387 }
388 }
389 if !keep_span {
390 handles_to_free.push(unsafe { Handle::from_usize_unchecked(span.start as usize) });
391 }
392 }
393
394 for handle in handles_to_free {
395 self.free(handle);
396 }
397 }
398
399 pub fn free(&mut self, handle: Handle<T>) {
400 let index = handle.index() as u32;
401 let span_idx = match self.span_info.binary_search_by_key(&index, |s| s.start) {
402 Ok(idx) if self.span_info[idx].start == index => idx,
403 _ => panic!(
404 "attempted to free an invalid handle (not start of a span) or already freed span"
405 ),
406 };
407
408 let span_to_free = self.span_info.remove(span_idx);
409
410 let mut merged_span = span_to_free;
411
412 if let Ok(right_idx) = self
413 .free_spans
414 .binary_search_by_key(&merged_span.end, |s| s.start) {
415 merged_span.end = self.free_spans.remove(right_idx).end;
416 }
417
418 let left_search = self
419 .free_spans
420 .binary_search_by(|probe| probe.end.cmp(&merged_span.start));
421 match left_search {
422 Ok(left_idx) => {
423 merged_span.start = self.free_spans.remove(left_idx).start;
424 }
425 Err(idx) if idx > 0 => {
426 if self.free_spans[idx - 1].end == merged_span.start {
427 merged_span.start = self.free_spans.remove(idx - 1).start;
428 }
429 }
430 _ => {}
431 }
432
433 match self.free_spans.binary_search(&merged_span) {
434 Ok(_) => unreachable!("Should not have duplicate free spans"),
435 Err(idx) => self.free_spans.insert(idx, merged_span),
436 }
437 }
438
439 #[inline]
440 pub fn as_slice(&self) -> &[T] {
441 &self.data
442 }
443
444 #[inline]
445 pub fn as_mut_slice(&mut self) -> &mut [T] {
446 &mut self.data
447 }
448
449 #[inline]
450 pub fn spans(&self) -> &[Span] {
451 &self.span_info
452 }
453
454 #[inline]
455 pub fn free_spans(&self) -> &[Span] {
456 &self.free_spans
457 }
458}
459
460impl<T: Clone> ops::Index<Handle<T>> for Arena<T> {
461 type Output = T;
462 #[inline]
463 fn index(&self, handle: Handle<T>) -> &T {
464 match self.try_get(handle) {
465 Ok(val) => val,
466 Err(msg) => panic!("{}", msg),
467 }
468 }
469}
470
471impl<T: Clone> ops::IndexMut<Handle<T>> for Arena<T> {
472 #[inline]
473 fn index_mut(&mut self, handle: Handle<T>) -> &mut T {
474 self.get_mut(handle)
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481
482 #[derive(Default)]
483 struct SplitMix64 {
484 x: u64,
485 }
486
487 impl SplitMix64 {
488 fn next_u64(&mut self) -> u64 {
489 self.x = self.x.wrapping_add(0x9e3779b97f4a7c15);
490 let mut z = self.x;
491 z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
492 z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
493 z ^ (z >> 31)
494 }
495 }
496
497 #[test]
498 fn append_non_unique() {
499 let mut arena: Arena<u8> = Arena::new();
500 let t1 = arena.append(0, 1);
501 let t2 = arena.append(0, 1);
502 assert!(t1 != t2);
503 assert!(arena[t1] == arena[t2]);
504 assert_eq!(arena.len(), 2);
505 }
506
507 #[test]
508 fn append_unique() {
509 let mut arena: Arena<u8> = Arena::new();
510 let t1 = arena.append(0, 1);
511 let t2 = arena.append(1, 1);
512 assert!(t1 != t2);
513 assert!(arena[t1] != arena[t2]);
514 assert_eq!(arena.len(), 2);
515 }
516
517 #[test]
518 fn fetch_or_append_non_unique() {
519 let mut arena: Arena<u8> = Arena::new();
520 let t1 = arena.fetch_or_append(0, 1);
521 let t2 = arena.fetch_or_append(0, 1);
522 assert!(t1 == t2);
523 assert!(arena[t1] == arena[t2]);
524 assert_eq!(arena.len(), 1);
525 }
526
527 #[test]
528 fn fetch_or_append_unique() {
529 let mut arena: Arena<u8> = Arena::new();
530 let t1 = arena.fetch_or_append(0, 1);
531 let t2 = arena.fetch_or_append(1, 1);
532 assert!(t1 != t2);
533 assert!(arena[t1] != arena[t2]);
534 assert_eq!(arena.len(), 2);
535 }
536
537 #[test]
538 fn iterators_live_only() {
539 let mut arena: Arena<u8> = Arena::new();
540 let h1 = arena.append(1, 3); let _h2 = arena.append(2, 2); arena.free(h1);
543 let _h3 = arena.append(3, 1); let _h4 = arena.append(4, 2); let mut live_elements = arena.iter().map(|(_, &v)| v).collect::<Vec<_>>();
547 live_elements.sort_unstable();
548 assert_eq!(live_elements, vec![2, 2, 3, 4, 4]);
549
550 assert_eq!(arena.len(), 5);
551
552 for (_, val) in arena.iter_mut() {
553 *val *= 10;
554 }
555 let mut live_elements_mut = arena.iter().map(|(_, &v)| v).collect::<Vec<_>>();
556 live_elements_mut.sort_unstable();
557 assert_eq!(live_elements_mut, vec![20, 20, 30, 40, 40]);
558 }
559
560 #[test]
561 fn reuse_spans() {
562 let mut arena: Arena<u8> = Arena::new();
563 let t1 = arena.append(5, 10); assert_eq!(arena.len(), 10);
565 assert_eq!(arena.spans(), &[Span::new(0, 10)]);
566 arena.free(t1); assert!(arena.is_empty());
568 assert_eq!(arena.free_spans(), &[Span::new(0, 10)]);
569
570 let t2 = arena.append(52, 10); assert_eq!(t1, t2); assert!(arena.free_spans().is_empty());
573 assert_eq!(arena.spans(), &[Span::new(0, 10)]);
574 assert_eq!(arena.len(), 10);
575
576 assert_eq!(arena[t2], 52);
577 for i in 1..10 {
578 let handle = unsafe { Handle::from_usize_unchecked(t1.index() + i as usize) };
579 assert_eq!(arena[handle], 52);
580 }
581
582 let t3 = arena.append(7, 42); assert_ne!(t2, t3); assert_eq!(arena.spans(), &[Span::new(0, 10), Span::new(10, 52)]);
585 assert_eq!(arena.len(), 10 + 42);
586
587 arena.free(t2); assert_eq!(arena.free_spans(), &[Span::new(0, 10)]);
589 assert_eq!(arena.spans(), &[Span::new(10, 52)]);
590 assert_eq!(arena.len(), 42);
591
592 let t4 = arena.append(255, 20); assert_ne!(t4.index(), 0); assert_eq!(t4.index(), 52);
595 assert_eq!(arena.free_spans(), &[Span::new(0, 10)]);
596 assert_eq!(arena.spans(), &[Span::new(10, 52), Span::new(52, 72)]);
597 assert_eq!(arena.len(), 42 + 20);
598
599 arena.free(t4); assert_eq!(arena.free_spans(), &[Span::new(0, 10), Span::new(52, 72)]);
601 assert_eq!(arena.spans(), &[Span::new(10, 52)]);
602 assert_eq!(arena.len(), 42);
603
604 let t5 = arena.append(123, 5); assert_eq!(t5.index(), 0);
606 assert_eq!(arena[t5], 123);
607 assert_eq!(arena.free_spans(), &[Span::new(5, 10), Span::new(52, 72)]); assert_eq!(arena.spans(), &[Span::new(0, 5), Span::new(10, 52)]); assert_eq!(arena.len(), 5 + 42);
610
611 arena.free(t3); assert_eq!(arena.free_spans(), &[Span::new(5, 72)]);
613 assert_eq!(arena.spans(), &[Span::new(0, 5)]); assert_eq!(arena.len(), 5);
615 }
616
617 #[test]
618 fn fuzz() {
619 const NUM_ITERATIONS: usize = 1000;
620
621 let mut arena: Arena<u64> = Arena::new();
622 let mut rng = SplitMix64::default();
623 let mut live_handles = Vec::new();
624
625 for j in 0..NUM_ITERATIONS {
626 let cnt = (rng.next_u64() % 10 + 1) as usize;
627 let v = rng.next_u64();
628 let t = arena.append(v, cnt);
629 live_handles.push((t, v, cnt));
630
631 assert_eq!(arena[t], v);
632 for i in 1..cnt {
633 let handle = unsafe { Handle::from_usize_unchecked(t.index() + i) };
634 assert_eq!(arena[handle], v);
635 }
636
637 if j > 10 && j % 5 == 0 && !live_handles.is_empty() {
638 let idx_to_check = rng.next_u64() as usize % live_handles.len();
639 let (prev_handle, prev_v, prev_cnt) = live_handles[idx_to_check];
640 assert_eq!(arena[prev_handle], prev_v);
641 for i in 1..prev_cnt {
642 let handle = unsafe { Handle::from_usize_unchecked(prev_handle.index() + i) };
643 assert_eq!(arena[handle], prev_v);
644 }
645 }
646
647 if j > 5 && j % 10 == 0 && !live_handles.is_empty() {
648 let idx_to_remove = rng.next_u64() as usize % live_handles.len();
649 let (handle_to_free, _, _) = live_handles.remove(idx_to_remove);
650 arena.free(handle_to_free);
651 assert!(arena.try_get(handle_to_free).is_err());
652 }
653 }
654
655 let mut total_len = 0;
656 for (handle, v, cnt) in &live_handles {
657 assert_eq!(arena[*handle], *v);
658 total_len += cnt;
659 for i in 1..*cnt {
660 let h = unsafe { Handle::from_usize_unchecked(handle.index() + i) };
661 assert_eq!(arena[h], *v);
662 }
663 }
664 assert_eq!(arena.len(), total_len);
665 }
666
667 #[test]
668 fn arena_retain_mut() {
669 let mut arena: Arena<i32> = Arena::new();
670 let h1 = arena.append(5, 10); let h2 = arena.append(52, 10); let h3 = arena.append(7, 10); let h4 = arena.append(123, 21); let h5 = arena.append(-7952812, 300); let initial_len = arena.len();
677 assert_eq!(initial_len, 10 + 10 + 10 + 21 + 300);
678
679 arena.retain_mut(|h, v| {
680 let h_idx = h.index();
681 if h_idx >= h2.index() && h_idx < h3.index() + 10 {
682 if *v == 7 {
683 *v = 49;
684 }
685 true
686 } else {
687 false
688 }
689 });
690
691 assert!(arena.try_get(h1).is_err());
692 assert!(arena.try_get(h4).is_err());
693 assert!(arena.try_get(h5).is_err());
694
695 assert!(arena.try_get(h2).is_ok());
696 assert!(arena.try_get(h3).is_ok());
697
698 assert_eq!(arena[h2], 52);
699 for i in 0..10 {
700 let handle = unsafe { Handle::from_usize_unchecked(h2.index() + i) };
701 assert_eq!(arena[handle], 52);
702 }
703 assert_eq!(arena[h3], 49);
704 for i in 0..10 {
705 let handle = unsafe { Handle::from_usize_unchecked(h3.index() + i) };
706 assert_eq!(arena[handle], 49);
707 }
708
709 assert_eq!(arena.len(), 10 + 10);
710
711 assert_eq!(arena.free_spans(), &[Span::new(0, 10), Span::new(30, 351)]);
712 }
713
714 #[test]
715 fn get_span_test() {
716 let mut arena: Arena<u8> = Arena::new();
717 let h1 = arena.append(1, 5); let h2 = arena.append(2, 10); arena.free(h1);
720 let h3 = arena.append(3, 3); let h4 = arena.append(4, 4); let handle_in_h3 = unsafe { Handle::from_usize_unchecked(h3.index() + 1) }; let handle_in_h2 = unsafe { Handle::from_usize_unchecked(h2.index() + 5) }; let handle_in_h4 = unsafe { Handle::from_usize_unchecked(h4.index() + 2) }; assert_eq!(arena.get_span(handle_in_h3), Span::new(0, 3));
728 assert_eq!(arena.get_span(handle_in_h2), Span::new(5, 15));
729 assert_eq!(arena.get_span(handle_in_h4), Span::new(15, 19));
730 }
731
732 #[test]
733 #[should_panic]
734 fn get_span_panic_freed() {
735 let mut arena: Arena<u8> = Arena::new();
736 let h1 = arena.append(1, 5);
737 arena.free(h1);
738 arena.get_span(h1);
739 }
740
741 #[test]
742 #[should_panic]
743 fn index_panic_freed() {
744 let mut arena: Arena<u8> = Arena::new();
745 let h1 = arena.append(1, 5);
746 arena.free(h1);
747 let _ = arena[h1];
748 }
749
750 #[test]
751 #[should_panic]
752 fn index_mut_panic_freed() {
753 let mut arena: Arena<u8> = Arena::new();
754 let h1 = arena.append(1, 5);
755 arena.free(h1);
756 arena[h1] = 9;
757 }
758
759 #[test]
760 #[should_panic]
761 fn free_panic_middle_of_span() {
762 let mut arena: Arena<u8> = Arena::new();
763 let h1 = arena.append(1, 5); let handle_in_middle = unsafe { Handle::from_usize_unchecked(h1.index() + 2) }; arena.free(handle_in_middle);
766 }
767
768 #[test]
769 fn append_after_free_all() {
770 let mut arena: Arena<u8> = Arena::new();
771 let h1 = arena.append(1, 5); let h2 = arena.append(2, 5); arena.free(h1);
774 arena.free(h2);
775 assert!(arena.is_empty());
776 assert_eq!(arena.free_spans(), &[Span::new(0, 10)]);
777
778 let h3 = arena.append(3, 10); assert_eq!(h3.index(), 0);
780 assert_eq!(arena[h3], 3);
781 for i in 0..10 {
782 let handle = unsafe { Handle::from_usize_unchecked(i) };
783 assert_eq!(arena[handle], 3);
784 }
785 assert_eq!(arena.spans(), &[Span::new(0, 10)]);
786 assert!(arena.free_spans().is_empty());
787 }
788
789 #[test]
790 fn merge_free_spans() {
791 let mut arena: Arena<u8> = Arena::new();
792 let h1 = arena.append(1, 5); let h2 = arena.append(2, 5); let h3 = arena.append(3, 5); arena.free(h1); arena.free(h3); assert_eq!(arena.free_spans(), &[Span::new(0, 5), Span::new(10, 15)]);
798
799 arena.free(h2); assert_eq!(arena.free_spans(), &[Span::new(0, 15)]);
801 assert!(arena.spans().is_empty());
802 }
803
804 #[test]
805 fn append_exact_fit() {
806 let mut arena: Arena<u8> = Arena::new();
807 let h1 = arena.append(1, 10); arena.free(h1); let h2 = arena.append(2, 10); assert_eq!(h2.index(), 0);
811 assert_eq!(arena[h2], 2);
812 assert_eq!(arena.spans(), &[Span::new(0, 10)]);
813 assert!(arena.free_spans().is_empty());
814 }
815
816 #[test]
817 fn append_larger_than_free() {
818 let mut arena: Arena<u8> = Arena::new();
819 let h1 = arena.append(1, 5); arena.free(h1); let h2 = arena.append(2, 10); assert_eq!(h2.index(), 5);
823 assert_eq!(arena[h2], 2);
824 assert_eq!(arena.spans(), &[Span::new(5, 15)]);
825 assert_eq!(arena.free_spans(), &[Span::new(0, 5)]);
826 }
827
828 #[test]
829 fn multiple_handles_same_span() {
830 let mut arena: Arena<u8> = Arena::new();
831 let h1 = arena.append(1, 5); for i in 0..5 {
833 let handle = unsafe { Handle::from_usize_unchecked(h1.index() + i) };
834 assert_eq!(arena.get_span(handle), Span::new(0, 5));
835 }
836 }
837
838 #[test]
839 fn iterate_arena() {
840 let mut arena: Arena<u8> = Arena::new();
841 let h1 = arena.append(1, 3); let h2 = arena.append(2, 2); let mut iter = arena.iter();
844 assert_eq!(iter.next(), Some((h1, &1)));
845 assert_eq!(
846 iter.next(),
847 Some((unsafe { Handle::from_usize_unchecked(1) }, &1))
848 );
849 assert_eq!(
850 iter.next(),
851 Some((unsafe { Handle::from_usize_unchecked(2) }, &1))
852 );
853 assert_eq!(iter.next(), Some((h2, &2)));
854 assert_eq!(
855 iter.next(),
856 Some((unsafe { Handle::from_usize_unchecked(4) }, &2))
857 );
858 assert_eq!(iter.next(), None);
859 }
860
861 #[test]
862 fn drain_arena() {
863 let mut arena: Arena<u8> = Arena::new();
864 let h1 = arena.append(1, 3); let h2 = arena.append(2, 2); let drained: Vec<_> = arena.drain().collect();
867 assert_eq!(drained.len(), 5);
868 assert_eq!(drained[0], (h1, 1, Span::new(0, 3)));
869 assert_eq!(
870 drained[1],
871 (
872 unsafe { Handle::from_usize_unchecked(1) },
873 1,
874 Span::new(0, 3)
875 )
876 );
877 assert_eq!(
878 drained[2],
879 (
880 unsafe { Handle::from_usize_unchecked(2) },
881 1,
882 Span::new(0, 3)
883 )
884 );
885 assert_eq!(drained[3], (h2, 2, Span::new(3, 5)));
886 assert_eq!(
887 drained[4],
888 (
889 unsafe { Handle::from_usize_unchecked(4) },
890 2,
891 Span::new(3, 5)
892 )
893 );
894 assert!(arena.is_empty());
895 assert!(arena.spans().is_empty());
896 assert!(arena.free_spans().is_empty());
897 }
898
899 #[test]
900 fn test_with_struct() {
901 #[derive(Debug, Clone, PartialEq)]
902 struct TestStruct {
903 a: u32,
904 b: u32,
905 }
906
907 let mut arena: Arena<TestStruct> = Arena::new();
908 let val1 = TestStruct { a: 1, b: 2 };
909 let val2 = TestStruct { a: 3, b: 4 };
910 let h1 = arena.append(val1.clone(), 5);
911 let h2 = arena.append(val2.clone(), 5);
912 assert_eq!(arena[h1], val1);
913 assert_eq!(arena[h2], val2);
914 arena.free(h1);
915 let h3 = arena.append(val2.clone(), 5);
916 assert_eq!(h3.index(), 0);
917 assert_eq!(arena[h3], val2);
918 }
919
920 #[test]
921 fn test_zero_sized() {
922 #[derive(Clone, Debug, PartialEq)]
923 struct ZeroSized;
924
925 let mut arena: Arena<ZeroSized> = Arena::new();
926 let h1 = arena.append(ZeroSized, 10);
927 assert_eq!(arena.len(), 10);
928 for i in 0..10 {
929 let handle = unsafe { Handle::from_usize_unchecked(h1.index() + i) };
930 assert_eq!(arena[handle], ZeroSized);
931 }
932 arena.free(h1);
933 assert!(arena.is_empty());
934 }
935
936 #[test]
937 fn test_fetch_if() {
938 let mut arena: Arena<u8> = Arena::new();
939 let _h1 = arena.append(1, 5);
940 let h2 = arena.append(2, 5);
941 let found = arena.fetch_if(|&v| v == 2);
942 assert_eq!(found, Some(h2));
943 let not_found = arena.fetch_if(|&v| v == 3);
944 assert_eq!(not_found, None);
945 }
946
947 #[test]
948 fn test_fetch_if_or_append_custom() {
949 #[derive(Clone, Debug)]
950 struct Person {
951 name: String,
952 age: u32,
953 }
954
955 let mut arena: Arena<Person> = Arena::new();
956 let alice1 = Person {
957 name: "Alice".to_string(),
958 age: 30,
959 };
960 let alice2 = Person {
961 name: "Alice".to_string(),
962 age: 31,
963 };
964 let bob = Person {
965 name: "Bob".to_string(),
966 age: 25,
967 };
968
969 let h1 = arena.fetch_if_or_append(alice1.clone(), 1, |p1, p2| p1.name == p2.name);
970 let h2 = arena.fetch_if_or_append(alice2.clone(), 1, |p1, p2| p1.name == p2.name);
971 assert_eq!(h1, h2); assert_eq!(arena[h1].age, 30);
973
974 let h3 = arena.fetch_if_or_append(bob.clone(), 1, |p1, p2| p1.name == p2.name);
975 assert_ne!(h1, h3);
976 assert_eq!(arena[h3].name, "Bob");
977 }
978
979 #[test]
980 fn test_clear() {
981 let mut arena: Arena<u8> = Arena::new();
982 let h1 = arena.append(1, 5);
983 let h2 = arena.append(2, 5);
984 assert_eq!(arena.len(), 10);
985 arena.clear();
986 assert!(arena.is_empty());
987 assert!(arena.spans().is_empty());
988 assert!(arena.free_spans().is_empty());
989 assert!(arena.try_get(h1).is_err());
990 assert!(arena.try_get(h2).is_err());
991 }
992
993 #[test]
994 fn free_and_reuse_partially() {
995 let mut arena: Arena<u8> = Arena::new();
996 let h1 = arena.append(1, 10); arena.free(h1); let h2 = arena.append(2, 3); let h3 = arena.append(3, 4); assert_eq!(h2.index(), 0);
1001 assert_eq!(h3.index(), 3);
1002 assert_eq!(arena.spans(), &[Span::new(0, 3), Span::new(3, 7)]);
1003 assert_eq!(arena.free_spans(), &[Span::new(7, 10)]);
1004 assert_eq!(arena[h2], 2);
1005 assert_eq!(arena[h3], 3);
1006 }
1007
1008 #[test]
1009 fn handle_ordering() {
1010 let mut arena: Arena<u8> = Arena::new();
1011 let h1 = arena.append(1, 1);
1012 let h2 = arena.append(2, 1);
1013 assert!(h1 < h2);
1014 arena.free(h1);
1015 let h3 = arena.append(3, 1); assert_eq!(h3, h1);
1017 assert!(h3 < h2);
1018 }
1019
1020 #[test]
1021 fn large_counts() {
1022 let mut arena: Arena<u8> = Arena::new();
1023 let h1 = arena.append(1, 1000);
1024 assert_eq!(arena.len(), 1000);
1025 for i in 0..1000 {
1026 let handle = unsafe { Handle::from_usize_unchecked(h1.index() + i) };
1027 assert_eq!(arena[handle], 1);
1028 }
1029 arena.free(h1);
1030 assert!(arena.is_empty());
1031 }
1032}