logicaffeine_base/
arena.rs1use bumpalo::Bump;
27
28pub struct Arena<T> {
34 bump: Bump,
35 _marker: std::marker::PhantomData<T>,
36}
37
38impl<T> Arena<T> {
39 pub fn new() -> Self {
41 Arena {
42 bump: Bump::new(),
43 _marker: std::marker::PhantomData,
44 }
45 }
46
47 pub fn alloc(&self, value: T) -> &T {
49 self.bump.alloc(value)
50 }
51
52 pub fn alloc_slice<I>(&self, items: I) -> &[T]
57 where
58 I: IntoIterator<Item = T>,
59 I::IntoIter: ExactSizeIterator,
60 {
61 self.bump.alloc_slice_fill_iter(items)
62 }
63
64 pub fn reset(&mut self) {
68 self.bump.reset();
69 }
70}
71
72impl<T> Default for Arena<T> {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn alloc_returns_stable_reference() {
84 let arena: Arena<i32> = Arena::new();
85 let r1 = arena.alloc(42);
86 let r2 = arena.alloc(100);
87 assert_eq!(*r1, 42);
88 assert_eq!(*r2, 100);
89 }
90
91 #[test]
92 fn references_remain_valid_after_many_allocations() {
93 let arena: Arena<i32> = Arena::new();
94 let refs: Vec<&i32> = (0..10000).map(|i| arena.alloc(i)).collect();
95 for (i, r) in refs.iter().enumerate() {
96 assert_eq!(**r, i as i32);
97 }
98 }
99
100 #[test]
101 fn works_with_structs() {
102 #[derive(Debug, PartialEq)]
103 struct Point {
104 x: i32,
105 y: i32,
106 }
107
108 let arena: Arena<Point> = Arena::new();
109 let p1 = arena.alloc(Point { x: 1, y: 2 });
110 let p2 = arena.alloc(Point { x: 3, y: 4 });
111 assert_eq!(p1, &Point { x: 1, y: 2 });
112 assert_eq!(p2, &Point { x: 3, y: 4 });
113 }
114
115 #[test]
116 fn alloc_slice_works() {
117 let arena: Arena<i32> = Arena::new();
118 let slice = arena.alloc_slice([1, 2, 3]);
119 assert_eq!(slice, &[1, 2, 3]);
120 }
121
122 #[test]
123 fn alloc_slice_from_vec() {
124 let arena: Arena<i32> = Arena::new();
125 let vec = vec![10, 20, 30];
126 let slice = arena.alloc_slice(vec);
127 assert_eq!(slice, &[10, 20, 30]);
128 }
129
130 #[test]
131 fn alloc_empty_slice() {
132 let arena: Arena<i32> = Arena::new();
133 let empty: Vec<i32> = vec![];
134 let slice = arena.alloc_slice(empty);
135 assert!(slice.is_empty());
136 }
137}