1#![forbid(unsafe_code)]
43#![deny(missing_docs)]
44
45use std::marker::PhantomData;
46
47pub struct Arena<T> {
63 items: Vec<T>,
64}
65
66pub struct Idx<T> {
79 index: usize,
80 _marker: PhantomData<T>,
81}
82
83pub struct Checkpoint<T> {
88 len: usize,
89 _marker: PhantomData<T>,
90}
91
92impl<T> Arena<T> {
95 #[must_use]
97 pub const fn new() -> Self {
98 Self { items: Vec::new() }
99 }
100
101 #[must_use]
103 pub fn with_capacity(capacity: usize) -> Self {
104 Self {
105 items: Vec::with_capacity(capacity),
106 }
107 }
108
109 pub fn alloc(&mut self, value: T) -> Idx<T> {
113 let index = self.items.len();
114 self.items.push(value);
115 Idx {
116 index,
117 _marker: PhantomData,
118 }
119 }
120
121 #[must_use]
127 pub fn get(&self, idx: Idx<T>) -> &T {
128 &self.items[idx.index]
129 }
130
131 #[must_use]
137 pub fn get_mut(&mut self, idx: Idx<T>) -> &mut T {
138 &mut self.items[idx.index]
139 }
140
141 #[must_use]
143 pub const fn len(&self) -> usize {
144 self.items.len()
145 }
146
147 #[must_use]
149 pub const fn is_empty(&self) -> bool {
150 self.items.is_empty()
151 }
152
153 #[must_use]
155 pub const fn capacity(&self) -> usize {
156 self.items.capacity()
157 }
158
159 #[must_use]
164 pub const fn checkpoint(&self) -> Checkpoint<T> {
165 Checkpoint {
166 len: self.items.len(),
167 _marker: PhantomData,
168 }
169 }
170
171 pub fn rollback(&mut self, cp: Checkpoint<T>) {
180 assert!(
181 cp.len <= self.items.len(),
182 "checkpoint {} beyond current length {}",
183 cp.len,
184 self.items.len(),
185 );
186 self.items.truncate(cp.len);
187 }
188
189 pub fn reset(&mut self) {
193 self.items.clear();
194 }
195
196 pub fn iter(&self) -> std::slice::Iter<'_, T> {
198 self.items.iter()
199 }
200
201 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
203 self.items.iter_mut()
204 }
205
206 pub fn alloc_extend(&mut self, iter: impl IntoIterator<Item = T>) -> Option<Idx<T>> {
213 let start = self.items.len();
214 self.items.extend(iter);
215 if self.items.len() > start {
216 Some(Idx {
217 index: start,
218 _marker: PhantomData,
219 })
220 } else {
221 None
222 }
223 }
224
225 #[must_use]
230 pub const fn is_valid(&self, idx: Idx<T>) -> bool {
231 idx.index < self.items.len()
232 }
233
234 #[must_use]
237 pub fn try_get(&self, idx: Idx<T>) -> Option<&T> {
238 self.items.get(idx.index)
239 }
240
241 #[must_use]
244 pub fn try_get_mut(&mut self, idx: Idx<T>) -> Option<&mut T> {
245 self.items.get_mut(idx.index)
246 }
247
248 pub fn drain(&mut self) -> std::vec::Drain<'_, T> {
254 self.items.drain(..)
255 }
256
257 #[must_use]
259 pub fn iter_indexed(&self) -> IterIndexed<'_, T> {
260 IterIndexed {
261 inner: self.items.iter().enumerate(),
262 }
263 }
264
265 pub fn iter_indexed_mut(&mut self) -> IterIndexedMut<'_, T> {
268 IterIndexedMut {
269 inner: self.items.iter_mut().enumerate(),
270 }
271 }
272
273 pub fn reserve(&mut self, additional: usize) {
275 self.items.reserve(additional);
276 }
277
278 pub fn shrink_to_fit(&mut self) {
280 self.items.shrink_to_fit();
281 }
282}
283
284impl<T> Default for Arena<T> {
285 fn default() -> Self {
286 Self::new()
287 }
288}
289
290impl<T> std::ops::Index<Idx<T>> for Arena<T> {
291 type Output = T;
292
293 fn index(&self, idx: Idx<T>) -> &T {
294 self.get(idx)
295 }
296}
297
298impl<T> std::ops::IndexMut<Idx<T>> for Arena<T> {
299 fn index_mut(&mut self, idx: Idx<T>) -> &mut T {
300 self.get_mut(idx)
301 }
302}
303
304impl<'a, T> IntoIterator for &'a Arena<T> {
305 type Item = &'a T;
306 type IntoIter = std::slice::Iter<'a, T>;
307
308 fn into_iter(self) -> Self::IntoIter {
309 self.iter()
310 }
311}
312
313impl<'a, T> IntoIterator for &'a mut Arena<T> {
314 type Item = &'a mut T;
315 type IntoIter = std::slice::IterMut<'a, T>;
316
317 fn into_iter(self) -> Self::IntoIter {
318 self.iter_mut()
319 }
320}
321
322impl<T> Extend<T> for Arena<T> {
323 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
324 self.items.extend(iter);
325 }
326}
327
328impl<T> std::iter::FromIterator<T> for Arena<T> {
329 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
330 Self {
331 items: iter.into_iter().collect(),
332 }
333 }
334}
335
336impl<T> IntoIterator for Arena<T> {
337 type Item = T;
338 type IntoIter = std::vec::IntoIter<T>;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.items.into_iter()
342 }
343}
344
345pub struct IterIndexed<'a, T> {
351 inner: std::iter::Enumerate<std::slice::Iter<'a, T>>,
352}
353
354impl<'a, T> Iterator for IterIndexed<'a, T> {
355 type Item = (Idx<T>, &'a T);
356
357 fn next(&mut self) -> Option<Self::Item> {
358 self.inner.next().map(|(i, v)| {
359 (
360 Idx {
361 index: i,
362 _marker: PhantomData,
363 },
364 v,
365 )
366 })
367 }
368
369 fn size_hint(&self) -> (usize, Option<usize>) {
370 self.inner.size_hint()
371 }
372}
373
374impl<T> ExactSizeIterator for IterIndexed<'_, T> {}
375
376pub struct IterIndexedMut<'a, T> {
382 inner: std::iter::Enumerate<std::slice::IterMut<'a, T>>,
383}
384
385impl<'a, T> Iterator for IterIndexedMut<'a, T> {
386 type Item = (Idx<T>, &'a mut T);
387
388 fn next(&mut self) -> Option<Self::Item> {
389 self.inner.next().map(|(i, v)| {
390 (
391 Idx {
392 index: i,
393 _marker: PhantomData,
394 },
395 v,
396 )
397 })
398 }
399
400 fn size_hint(&self) -> (usize, Option<usize>) {
401 self.inner.size_hint()
402 }
403}
404
405impl<T> ExactSizeIterator for IterIndexedMut<'_, T> {}
406
407impl<T> Idx<T> {
410 #[must_use]
412 pub const fn into_raw(self) -> usize {
413 self.index
414 }
415
416 #[must_use]
420 pub const fn from_raw(index: usize) -> Self {
421 Self {
422 index,
423 _marker: PhantomData,
424 }
425 }
426}
427
428impl<T> Clone for Idx<T> {
429 fn clone(&self) -> Self {
430 *self
431 }
432}
433
434impl<T> Copy for Idx<T> {}
435
436impl<T> PartialEq for Idx<T> {
437 fn eq(&self, other: &Self) -> bool {
438 self.index == other.index
439 }
440}
441
442impl<T> Eq for Idx<T> {}
443
444impl<T> std::hash::Hash for Idx<T> {
445 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
446 self.index.hash(state);
447 }
448}
449
450impl<T> std::fmt::Debug for Idx<T> {
451 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
452 write!(f, "Idx({})", self.index)
453 }
454}
455
456impl<T> PartialOrd for Idx<T> {
457 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
458 Some(self.cmp(other))
459 }
460}
461
462impl<T> Ord for Idx<T> {
463 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
464 self.index.cmp(&other.index)
465 }
466}
467
468impl<T> Checkpoint<T> {
471 #[must_use]
473 pub const fn len(&self) -> usize {
474 self.len
475 }
476
477 #[must_use]
479 pub const fn is_empty(&self) -> bool {
480 self.len == 0
481 }
482}
483
484impl<T> Clone for Checkpoint<T> {
485 fn clone(&self) -> Self {
486 *self
487 }
488}
489
490impl<T> Copy for Checkpoint<T> {}
491
492impl<T> PartialEq for Checkpoint<T> {
493 fn eq(&self, other: &Self) -> bool {
494 self.len == other.len
495 }
496}
497
498impl<T> Eq for Checkpoint<T> {}
499
500impl<T> std::hash::Hash for Checkpoint<T> {
501 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
502 self.len.hash(state);
503 }
504}
505
506impl<T> std::fmt::Debug for Checkpoint<T> {
507 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508 write!(f, "Checkpoint({})", self.len)
509 }
510}
511
512impl<T> PartialOrd for Checkpoint<T> {
513 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
514 Some(self.cmp(other))
515 }
516}
517
518impl<T> Ord for Checkpoint<T> {
519 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
520 self.len.cmp(&other.len)
521 }
522}
523
524#[cfg(test)]
527mod tests {
528 use std::cell::Cell;
529 use std::rc::Rc;
530
531 use super::*;
532
533 #[test]
534 fn empty_arena() {
535 let arena: Arena<i32> = Arena::new();
536 assert!(arena.is_empty());
537 assert_eq!(arena.len(), 0);
538 }
539
540 #[test]
541 fn alloc_and_access() {
542 let mut arena = Arena::new();
543 let a = arena.alloc(42);
544 let b = arena.alloc(99);
545
546 assert_eq!(arena[a], 42);
547 assert_eq!(arena[b], 99);
548 assert_eq!(arena.len(), 2);
549 }
550
551 #[test]
552 fn alloc_strings() {
553 let mut arena = Arena::new();
554 let a = arena.alloc(String::from("hello"));
555 let b = arena.alloc(String::from("world"));
556
557 assert_eq!(arena[a], "hello");
558 assert_eq!(arena[b], "world");
559 }
560
561 #[test]
562 fn get_mut_modifies() {
563 let mut arena = Arena::new();
564 let a = arena.alloc(String::from("old"));
565
566 arena[a] = String::from("new");
567 assert_eq!(arena[a], "new");
568 }
569
570 #[test]
571 fn with_capacity() {
572 let arena: Arena<u64> = Arena::with_capacity(100);
573 assert!(arena.capacity() >= 100);
574 assert!(arena.is_empty());
575 }
576
577 #[test]
578 fn checkpoint_rollback() {
579 let mut arena = Arena::new();
580 let a = arena.alloc(1);
581 let b = arena.alloc(2);
582 let cp = arena.checkpoint();
583
584 let _c = arena.alloc(3);
585 let _d = arena.alloc(4);
586 assert_eq!(arena.len(), 4);
587
588 arena.rollback(cp);
589 assert_eq!(arena.len(), 2);
590 assert_eq!(arena[a], 1);
591 assert_eq!(arena[b], 2);
592 }
593
594 #[test]
595 fn rollback_runs_drop() {
596 let drop_count = Rc::new(Cell::new(0u32));
597
598 struct Tracked(Rc<Cell<u32>>);
599 impl Drop for Tracked {
600 fn drop(&mut self) {
601 self.0.set(self.0.get() + 1);
602 }
603 }
604
605 let mut arena = Arena::new();
606 let _a = arena.alloc(Tracked(Rc::clone(&drop_count)));
607 let cp = arena.checkpoint();
608 let _b = arena.alloc(Tracked(Rc::clone(&drop_count)));
609 let _c = arena.alloc(Tracked(Rc::clone(&drop_count)));
610
611 assert_eq!(drop_count.get(), 0);
612 arena.rollback(cp);
613 assert_eq!(drop_count.get(), 2); }
615
616 #[test]
617 fn reset_runs_drop() {
618 let drop_count = Rc::new(Cell::new(0u32));
619
620 struct Tracked(Rc<Cell<u32>>);
621 impl Drop for Tracked {
622 fn drop(&mut self) {
623 self.0.set(self.0.get() + 1);
624 }
625 }
626
627 let mut arena = Arena::new();
628 let _a = arena.alloc(Tracked(Rc::clone(&drop_count)));
629 let _b = arena.alloc(Tracked(Rc::clone(&drop_count)));
630
631 arena.reset();
632 assert_eq!(drop_count.get(), 2);
633 assert!(arena.is_empty());
634 }
635
636 #[test]
637 fn reset_preserves_capacity() {
638 let mut arena = Arena::with_capacity(100);
639 for i in 0..50 {
640 arena.alloc(i);
641 }
642 let cap_before = arena.capacity();
643
644 arena.reset();
645 assert!(arena.is_empty());
646 assert_eq!(arena.capacity(), cap_before);
647 }
648
649 #[test]
650 fn nested_checkpoints() {
651 let mut arena = Arena::new();
652 let a = arena.alloc(1);
653
654 let cp1 = arena.checkpoint();
655 let _b = arena.alloc(2);
656
657 let cp2 = arena.checkpoint();
658 let _c = arena.alloc(3);
659
660 arena.rollback(cp2);
661 assert_eq!(arena.len(), 2);
662
663 arena.rollback(cp1);
664 assert_eq!(arena.len(), 1);
665 assert_eq!(arena[a], 1);
666 }
667
668 #[test]
669 fn rollback_to_empty() {
670 let mut arena = Arena::new();
671 let cp = arena.checkpoint();
672
673 arena.alloc(1);
674 arena.alloc(2);
675 arena.rollback(cp);
676
677 assert!(arena.is_empty());
678 }
679
680 #[test]
681 #[should_panic(expected = "checkpoint 5 beyond current length 2")]
682 fn rollback_beyond_length_panics() {
683 let mut arena = Arena::new();
684 arena.alloc(1);
685 arena.alloc(2);
686
687 let bad_cp = Checkpoint::<i32> {
688 len: 5,
689 _marker: PhantomData,
690 };
691 arena.rollback(bad_cp);
692 }
693
694 #[test]
695 #[should_panic]
696 fn stale_index_panics() {
697 let mut arena = Arena::new();
698 let _a = arena.alloc(1);
699 let b = arena.alloc(2);
700
701 arena.reset();
702 let _ = arena[b]; }
704
705 #[test]
706 fn idx_is_copy() {
707 let mut arena = Arena::new();
708 let a = arena.alloc(42);
709 let b = a; assert_eq!(arena[a], arena[b]);
711 }
712
713 #[test]
714 fn idx_equality() {
715 let a = Idx::<i32>::from_raw(5);
716 let b = Idx::<i32>::from_raw(5);
717 let c = Idx::<i32>::from_raw(3);
718
719 assert_eq!(a, b);
720 assert_ne!(a, c);
721 }
722
723 #[test]
724 fn idx_ordering() {
725 let a = Idx::<i32>::from_raw(1);
726 let b = Idx::<i32>::from_raw(5);
727
728 assert!(a < b);
729 }
730
731 #[test]
732 fn idx_raw_roundtrip() {
733 let idx = Idx::<String>::from_raw(42);
734 assert_eq!(idx.into_raw(), 42);
735 }
736
737 #[test]
738 fn iter() {
739 let mut arena = Arena::new();
740 arena.alloc(10);
741 arena.alloc(20);
742 arena.alloc(30);
743
744 let sum: i32 = arena.iter().sum();
745 assert_eq!(sum, 60);
746 }
747
748 #[test]
749 fn default_is_empty() {
750 let arena: Arena<u8> = Arena::default();
751 assert!(arena.is_empty());
752 }
753
754 #[test]
755 fn many_allocations() {
756 let mut arena = Arena::with_capacity(0);
757 for i in 0..10_000 {
758 let idx = arena.alloc(i);
759 assert_eq!(arena[idx], i);
760 }
761 assert_eq!(arena.len(), 10_000);
762 }
763
764 #[test]
765 fn checkpoint_len() {
766 let mut arena = Arena::new();
767 arena.alloc(1);
768 arena.alloc(2);
769 let cp = arena.checkpoint();
770 assert_eq!(cp.len(), 2);
771 }
772
773 #[test]
774 fn reuse_after_reset() {
775 let mut arena = Arena::new();
776 arena.alloc(String::from("first"));
777 arena.reset();
778
779 let a = arena.alloc(String::from("second"));
780 assert_eq!(arena[a], "second");
781 assert_eq!(arena.len(), 1);
782 }
783
784 #[test]
785 fn alloc_extend_returns_first_idx() {
786 let mut arena = Arena::new();
787 arena.alloc(0);
788
789 let first = arena.alloc_extend(vec![10, 20, 30]);
790 assert_eq!(first, Some(Idx::from_raw(1)));
791 assert_eq!(arena.len(), 4);
792 assert_eq!(arena[Idx::from_raw(1)], 10);
793 assert_eq!(arena[Idx::from_raw(2)], 20);
794 assert_eq!(arena[Idx::from_raw(3)], 30);
795 }
796
797 #[test]
798 fn alloc_extend_empty_returns_none() {
799 let mut arena: Arena<i32> = Arena::new();
800 let result = arena.alloc_extend(std::iter::empty());
801 assert_eq!(result, None);
802 assert!(arena.is_empty());
803 }
804
805 #[test]
806 fn is_valid_after_rollback() {
807 let mut arena = Arena::new();
808 let a = arena.alloc(1);
809 let cp = arena.checkpoint();
810 let b = arena.alloc(2);
811
812 assert!(arena.is_valid(a));
813 assert!(arena.is_valid(b));
814
815 arena.rollback(cp);
816 assert!(arena.is_valid(a));
817 assert!(!arena.is_valid(b));
818 }
819
820 #[test]
821 fn is_valid_after_reset() {
822 let mut arena = Arena::new();
823 let a = arena.alloc(1);
824
825 assert!(arena.is_valid(a));
826 arena.reset();
827 assert!(!arena.is_valid(a));
828 }
829
830 #[test]
831 fn try_get_returns_none_for_stale() {
832 let mut arena = Arena::new();
833 let a = arena.alloc(42);
834 let cp = arena.checkpoint();
835 let b = arena.alloc(99);
836
837 arena.rollback(cp);
838 assert_eq!(arena.try_get(a), Some(&42));
839 assert_eq!(arena.try_get(b), None);
840 }
841
842 #[test]
843 fn try_get_mut_returns_none_for_stale() {
844 let mut arena = Arena::new();
845 let _a = arena.alloc(1);
846 let cp = arena.checkpoint();
847 let b = arena.alloc(2);
848
849 arena.rollback(cp);
850 assert_eq!(arena.try_get_mut(b), None);
851 }
852
853 #[test]
854 fn drain_returns_all_items() {
855 let mut arena = Arena::new();
856 arena.alloc(10);
857 arena.alloc(20);
858 arena.alloc(30);
859
860 let items: Vec<_> = arena.drain().collect();
861 assert_eq!(items, vec![10, 20, 30]);
862 assert!(arena.is_empty());
863 }
864
865 #[test]
866 fn drain_runs_no_extra_drops() {
867 let drop_count = Rc::new(Cell::new(0u32));
868
869 struct Tracked(Rc<Cell<u32>>);
870 impl Drop for Tracked {
871 fn drop(&mut self) {
872 self.0.set(self.0.get() + 1);
873 }
874 }
875
876 let mut arena = Arena::new();
877 arena.alloc(Tracked(Rc::clone(&drop_count)));
878 arena.alloc(Tracked(Rc::clone(&drop_count)));
879
880 let items: Vec<_> = arena.drain().collect();
881 assert_eq!(drop_count.get(), 0); drop(items);
883 assert_eq!(drop_count.get(), 2); }
885
886 #[test]
887 fn iter_indexed_yields_correct_pairs() {
888 let mut arena = Arena::new();
889 let a = arena.alloc("x");
890 let b = arena.alloc("y");
891 let c = arena.alloc("z");
892
893 let pairs: Vec<_> = arena.iter_indexed().collect();
894 assert_eq!(pairs.len(), 3);
895 assert_eq!(pairs[0], (a, &"x"));
896 assert_eq!(pairs[1], (b, &"y"));
897 assert_eq!(pairs[2], (c, &"z"));
898 }
899
900 #[test]
901 fn iter_indexed_empty() {
902 let arena: Arena<i32> = Arena::new();
903 assert_eq!(arena.iter_indexed().count(), 0);
904 }
905
906 #[test]
907 fn iter_indexed_exact_size() {
908 let mut arena = Arena::new();
909 arena.alloc(1);
910 arena.alloc(2);
911 arena.alloc(3);
912
913 let iter = arena.iter_indexed();
914 assert_eq!(iter.len(), 3);
915 }
916
917 #[test]
918 fn shrink_to_fit_reduces_capacity() {
919 let mut arena: Arena<u64> = Arena::with_capacity(1000);
920 arena.alloc(1);
921 arena.alloc(2);
922 assert!(arena.capacity() >= 1000);
923
924 arena.shrink_to_fit();
925 assert!(arena.capacity() < 1000);
926 assert_eq!(arena.len(), 2);
927 }
928
929 #[test]
930 fn iter_mut_modifies_all() {
931 let mut arena = Arena::new();
932 arena.alloc(1);
933 arena.alloc(2);
934 arena.alloc(3);
935
936 for item in &mut arena {
937 *item *= 10;
938 }
939
940 let values: Vec<_> = arena.iter().copied().collect();
941 assert_eq!(values, vec![10, 20, 30]);
942 }
943
944 #[test]
945 fn iter_indexed_mut_yields_correct_pairs() {
946 let mut arena = Arena::new();
947 let a = arena.alloc(String::from("x"));
948 let b = arena.alloc(String::from("y"));
949
950 let pairs: Vec<_> = arena
951 .iter_indexed_mut()
952 .map(|(idx, val)| (idx, val.clone()))
953 .collect();
954 assert_eq!(pairs.len(), 2);
955 assert_eq!(pairs[0], (a, String::from("x")));
956 assert_eq!(pairs[1], (b, String::from("y")));
957 }
958
959 #[test]
960 fn iter_indexed_mut_modifies() {
961 let mut arena = Arena::new();
962 arena.alloc(1);
963 arena.alloc(2);
964 arena.alloc(3);
965
966 for (_, val) in arena.iter_indexed_mut() {
967 *val += 100;
968 }
969
970 assert_eq!(arena[Idx::from_raw(0)], 101);
971 assert_eq!(arena[Idx::from_raw(1)], 102);
972 assert_eq!(arena[Idx::from_raw(2)], 103);
973 }
974
975 #[test]
976 fn iter_indexed_mut_exact_size() {
977 let mut arena = Arena::new();
978 arena.alloc(1);
979 arena.alloc(2);
980
981 let iter = arena.iter_indexed_mut();
982 assert_eq!(iter.len(), 2);
983 }
984
985 #[test]
986 fn reserve_increases_capacity() {
987 let mut arena: Arena<u64> = Arena::new();
988 arena.reserve(500);
989 assert!(arena.capacity() >= 500);
990 assert!(arena.is_empty());
991 }
992
993 #[test]
994 fn extend_trait() {
995 let mut arena = Arena::new();
996 arena.alloc(1);
997 arena.extend(vec![2, 3, 4]);
998 assert_eq!(arena.len(), 4);
999
1000 let values: Vec<_> = arena.iter().copied().collect();
1001 assert_eq!(values, vec![1, 2, 3, 4]);
1002 }
1003
1004 #[test]
1005 fn from_iterator() {
1006 let arena: Arena<i32> = (0..5).collect();
1007 assert_eq!(arena.len(), 5);
1008 assert_eq!(arena[Idx::from_raw(0)], 0);
1009 assert_eq!(arena[Idx::from_raw(4)], 4);
1010 }
1011
1012 #[test]
1013 fn checkpoint_equality() {
1014 let mut arena = Arena::new();
1015 let cp1 = arena.checkpoint();
1016 let cp2 = arena.checkpoint();
1017 assert_eq!(cp1, cp2);
1018
1019 arena.alloc(1);
1020 let cp3 = arena.checkpoint();
1021 assert_ne!(cp1, cp3);
1022 }
1023
1024 #[test]
1025 fn checkpoint_ordering() {
1026 let mut arena = Arena::new();
1027 let cp1 = arena.checkpoint();
1028 arena.alloc(1);
1029 let cp2 = arena.checkpoint();
1030 arena.alloc(2);
1031 let cp3 = arena.checkpoint();
1032
1033 assert!(cp1 < cp2);
1034 assert!(cp2 < cp3);
1035 }
1036
1037 #[test]
1038 fn into_iter_consuming() {
1039 let mut arena = Arena::new();
1040 arena.alloc(String::from("a"));
1041 arena.alloc(String::from("b"));
1042 arena.alloc(String::from("c"));
1043
1044 let collected: Vec<String> = arena.into_iter().collect();
1045 assert_eq!(collected, vec!["a", "b", "c"]);
1046 }
1047}