Skip to main content

dada_util/
arena.rs

1use std::{any::Any, cell::RefCell, pin::Pin};
2
3/// A really dumb arena implementation intended not for efficiency
4/// but rather to prolong lifetimes.
5pub struct Arena {
6    /// List of values inserted into the arena.
7    /// They cannot be moved out from the box or dropped until the arena is dropped.
8    ///
9    /// The use of Box is needed to ensure the address of the value is stable.
10    /// The `Pin` and `dyn Any` parts are just for fun and/or convenience.
11    /// The pin is expressing the "don't move" constraint but is neither necessary
12    /// nor sufficient for soundness (it doesn't prevent drops),
13    /// and the `dyn Any` is just to capture the destructor but we don't do
14    /// any downcasting.
15    data: RefCell<Vec<Pin<Box<dyn Any>>>>,
16}
17
18impl Default for Arena {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl Arena {
25    pub fn new() -> Self {
26        Self {
27            data: Default::default(),
28        }
29    }
30
31    pub fn insert<T>(&self, value: T) -> &T
32    where
33        T: Any,
34    {
35        let data = Box::pin(value);
36        let ptr: *const T = &*data;
37        self.data.borrow_mut().push(data);
38
39        // UNSAFE: WE don't ever remove anything from `self.data` until self is dropped.
40        // UNSAFE: The value is guaranteed to be valid for the lifetime of `self`
41        unsafe { &*ptr }
42    }
43}