arena_rs/
lib.rs

1
2pub struct Arena {
3    container: Vec<u8>,
4    capacity: usize,
5    offset: usize,
6}
7
8impl<'a> Arena {
9    pub fn new(size: usize) -> Self {
10        Arena {
11            container: Vec::with_capacity(size),
12            capacity: size,
13            offset: 0,
14        }
15    }
16    pub fn alloc<T>(&mut self, value: T) -> Option<&'a mut T> {
17        let size = std::mem::size_of::<T>();
18        if self.offset + size > self.capacity {
19            return None;
20        }
21        for _ in 0..size {
22            self.container.push(0u8);
23        }
24        let ptr: *mut u8 = &mut self.container[self.offset];
25        let ptr = ptr.cast::<T>();
26        self.offset += size;
27        unsafe {
28            *ptr = value;
29            Some(&mut *ptr)
30        }
31    }
32}
33
34#[test]
35fn single_allocation() {
36    let mut arena = Arena::new(1024);
37    let value = arena.alloc(7).unwrap();
38    assert_eq!(*value, 7);
39}
40
41#[test]
42fn out_of_space() {
43    let mut arena = Arena::new(4);
44    arena.alloc(7).unwrap();
45    let value = arena.alloc(7);
46    assert_eq!(value, None);
47}
48
49#[test]
50fn multiple_allocations() {
51    let mut arena = Arena::new(1024);
52    let value_78 = arena.alloc(78).unwrap();
53    let value_42 = arena.alloc(42).unwrap();
54
55    {
56        let value_17  = arena.alloc(17).unwrap();
57        assert_eq!(*value_17, 17);
58    }
59    // value_17 is out of scope, and so cannot be used
60    // but it hasn't been freed
61
62    assert_eq!(*value_78, 78);
63    assert_eq!(*value_42, 42);
64    assert_eq!(*value_78 + *value_42, 78 + 42);
65
66    // All values are now freed in one giant batch
67}