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}