foundation_arena/boxed.rs
1// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. <hello@foundationdevices.com>
2// SPDX-License-Identifier: GPL-3.0-or-later
3//
4// Based on code from bumpalo and Rust std.
5
6/// Alternative to `std::boxed::Box`, but using an arena allcator.
7///
8/// # Example
9///
10/// Recursive data structure:
11///
12/// ```rust
13/// use foundation_arena::{Arena, boxed::Box};
14///
15/// let a: Arena<_, 2> = Arena::new();
16/// let b: Arena<_, 2> = Arena::new();
17///
18/// #[derive(Debug, PartialEq)]
19/// enum List<'a, T> {
20/// Cons(T, Box<'a, List<'a, T>>),
21/// Nil,
22/// }
23///
24/// let list = List::<i32>::Cons(
25/// 1,
26/// Box::new_in(List::Cons(2, Box::new_in(List::Nil, &a).unwrap()), &a).unwrap(),
27/// );
28///
29/// let clone = List::<i32>::Cons(
30/// 1,
31/// Box::new_in(List::Cons(2, Box::new_in(List::Nil, &b).unwrap()), &b).unwrap(),
32/// );
33///
34/// println!("{:?}", list);
35///
36/// assert_eq!(list, clone);
37/// ```
38use core::{ops::Deref, ptr};
39
40use crate::Arena;
41
42#[derive(Debug)]
43pub struct Box<'a, T>(&'a mut T);
44
45impl<'a, T> Box<'a, T> {
46 pub fn new_in<const N: usize>(x: T, arena: &'a Arena<T, N>) -> Result<Self, T> {
47 arena.alloc(x).map(Self)
48 }
49}
50
51impl<'a, T> Deref for Box<'a, T> {
52 type Target = T;
53
54 fn deref(&self) -> &Self::Target {
55 &*self.0
56 }
57}
58
59impl<'a, 'b, T: PartialEq> PartialEq<Box<'b, T>> for Box<'a, T> {
60 fn eq(&self, other: &Box<'b, T>) -> bool {
61 PartialEq::eq(&**self, &**other)
62 }
63
64 fn ne(&self, other: &Box<'b, T>) -> bool {
65 PartialEq::ne(&**self, &**other)
66 }
67}
68
69impl<'a, T> Drop for Box<'a, T> {
70 fn drop(&mut self) {
71 unsafe { ptr::drop_in_place(self.0) }
72 }
73}