1use bumpalo::Bump;
74
75#[derive(Debug)]
80pub struct Arena {
81 inner: Bump,
82}
83
84impl Arena {
85 pub fn new() -> Self {
86 Self { inner: Bump::new() }
87 }
88
89 pub fn with_capacity(capacity: usize) -> Self {
90 Self {
91 inner: Bump::with_capacity(capacity),
92 }
93 }
94
95 pub fn alloc<T>(&self, value: T) -> &mut T {
96 self.inner.alloc(value)
97 }
98
99 pub fn alloc_slice<T: Copy>(&self, slice: &[T]) -> &mut [T] {
100 self.inner.alloc_slice_copy(slice)
101 }
102
103 pub fn alloc_str(&self, s: &str) -> &mut str {
104 self.inner.alloc_str(s)
105 }
106
107 pub fn allocated_bytes(&self) -> usize {
108 self.inner.allocated_bytes()
109 }
110
111 pub fn reset(&mut self) {
112 self.inner.reset();
113 }
114
115 pub fn inner(&self) -> &Bump {
116 &self.inner
117 }
118}
119
120impl Default for Arena {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126pub struct ArenaPool {
131 arenas: Vec<Arena>,
132 current: std::sync::atomic::AtomicUsize,
133}
134
135impl ArenaPool {
136 pub fn new(arena_count: usize) -> Self {
137 let arenas = (0..arena_count).map(|_| Arena::new()).collect();
138 Self {
139 arenas,
140 current: std::sync::atomic::AtomicUsize::new(0),
141 }
142 }
143
144 pub fn with_capacity(arena_count: usize, capacity: usize) -> Self {
145 let arenas = (0..arena_count)
146 .map(|_| Arena::with_capacity(capacity))
147 .collect();
148 Self {
149 arenas,
150 current: std::sync::atomic::AtomicUsize::new(0),
151 }
152 }
153
154 pub fn get_arena(&self) -> &Arena {
155 use std::sync::atomic::Ordering;
156 let idx = self.current.fetch_add(1, Ordering::Relaxed) % self.arenas.len();
157 &self.arenas[idx]
158 }
159
160 pub fn reset_all(&mut self) {
161 for arena in &mut self.arenas {
162 arena.reset();
163 }
164 }
165
166 pub fn total_allocated(&self) -> usize {
167 self.arenas.iter().map(|a| a.allocated_bytes()).sum()
168 }
169}
170
171pub struct ArenaTokenizer<'a> {
173 arena: &'a Bump,
174}
175
176impl<'a> ArenaTokenizer<'a> {
177 pub fn new(arena: &'a Bump) -> Self {
178 Self { arena }
179 }
180
181 pub fn tokenize(&self, text: &str) -> Vec<&'a str> {
182 text.split_whitespace()
183 .map(|word| self.arena.alloc_str(word) as &str)
184 .collect()
185 }
186
187 pub fn tokenize_with_sep(&self, text: &str, sep: char) -> Vec<&'a str> {
188 text.split(sep)
189 .filter(|word| !word.is_empty())
190 .map(|word| self.arena.alloc_str(word) as &str)
191 .collect()
192 }
193}
194
195pub struct ArenaVec<'a, T> {
197 arena: &'a Bump,
198 items: Vec<&'a mut T>,
199}
200
201impl<'a, T> ArenaVec<'a, T> {
202 pub fn new(arena: &'a Bump) -> Self {
203 Self {
204 arena,
205 items: Vec::new(),
206 }
207 }
208
209 pub fn push(&mut self, value: T) {
210 let item = self.arena.alloc(value);
211 self.items.push(item);
212 }
213
214 pub fn len(&self) -> usize {
215 self.items.len()
216 }
217
218 pub fn is_empty(&self) -> bool {
219 self.items.is_empty()
220 }
221
222 pub fn get(&self, index: usize) -> Option<&T> {
223 self.items.get(index).map(|item| &**item)
224 }
225
226 pub fn iter(&self) -> impl Iterator<Item = &T> {
227 self.items.iter().map(|item| &**item)
228 }
229}
230
231pub struct ArenaStringBuilder<'a> {
233 arena: &'a Bump,
234 buffer: Vec<&'a str>,
235}
236
237impl<'a> ArenaStringBuilder<'a> {
238 pub fn new(arena: &'a Bump) -> Self {
239 Self {
240 arena,
241 buffer: Vec::new(),
242 }
243 }
244
245 pub fn append(&mut self, s: &str) {
246 let slice = self.arena.alloc_str(s);
247 self.buffer.push(slice);
248 }
249
250 pub fn build(&self) -> String {
251 self.buffer.concat()
252 }
253
254 pub fn slices(&self) -> &[&'a str] {
255 &self.buffer
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn test_arena_basic() {
265 let mut arena = Arena::new();
266
267 let a = arena.alloc(42);
268 let b = arena.alloc("hello");
269
270 assert_eq!(*a, 42);
271 assert_eq!(*b, "hello");
272
273 arena.reset();
274 let c = arena.alloc(100);
275 assert_eq!(*c, 100);
276 }
277
278 #[test]
279 fn test_arena_slice() {
280 let arena = Arena::new();
281
282 let slice = arena.alloc_slice(&[1, 2, 3, 4, 5]);
283 assert_eq!(slice.len(), 5);
284 assert_eq!(slice[0], 1);
285 assert_eq!(slice[4], 5);
286 }
287
288 #[test]
289 fn test_arena_string() {
290 let arena = Arena::new();
291
292 let s = arena.alloc_str("hello world");
293 assert_eq!(s, "hello world");
294 }
295
296 #[test]
297 fn test_arena_pool() {
298 let pool = ArenaPool::new(4);
299
300 let arena1 = pool.get_arena();
301 let _ = arena1.alloc(1);
302
303 let arena2 = pool.get_arena();
304 let _ = arena2.alloc(2);
305
306 assert!(pool.total_allocated() > 0);
307 }
308
309 #[test]
310 fn test_arena_tokenizer() {
311 let arena = Arena::new();
312 let tokenizer = ArenaTokenizer::new(arena.inner());
313
314 let tokens = tokenizer.tokenize("hello world rust");
315 assert_eq!(tokens.len(), 3);
316 assert_eq!(tokens[0], "hello");
317 assert_eq!(tokens[1], "world");
318 assert_eq!(tokens[2], "rust");
319 }
320
321 #[test]
322 fn test_arena_vec() {
323 let arena = Arena::new();
324 let mut vec = ArenaVec::new(arena.inner());
325
326 vec.push(1);
327 vec.push(2);
328 vec.push(3);
329
330 assert_eq!(vec.len(), 3);
331 assert_eq!(vec.get(0), Some(&1));
332 assert_eq!(vec.get(1), Some(&2));
333 assert_eq!(vec.get(2), Some(&3));
334 }
335
336 #[test]
337 fn test_arena_string_builder() {
338 let arena = Arena::new();
339 let mut builder = ArenaStringBuilder::new(arena.inner());
340
341 builder.append("hello");
342 builder.append(" ");
343 builder.append("world");
344
345 assert_eq!(builder.build(), "hello world");
346 }
347}