1use alloc::boxed::Box;
3use core::fmt;
4use core::marker::PhantomData;
5use core::ops::{Deref, DerefMut};
6use core::ptr::NonNull;
7
8use crate::State;
9use crate::arena::{Alloc, ArenaBox};
10
11pub struct Boxed<T: ?Sized> {
25 ptr: NonNull<T>,
26 alloc: Alloc,
27 _marker: PhantomData<T>,
28}
29
30unsafe impl<T: ?Sized + Send> Send for Boxed<T> {}
32unsafe impl<T: ?Sized + Sync> Sync for Boxed<T> {}
33
34impl<T: ?Sized> Boxed<T> {
35 #[inline(always)]
37 pub(crate) fn from_arena(value: ArenaBox<T>) -> Boxed<T> {
38 Boxed {
39 ptr: ArenaBox::into_raw(value),
40 alloc: Alloc::Arena,
41 _marker: PhantomData,
42 }
43 }
44
45 #[inline(always)]
48 pub(crate) fn into_raw(this: Boxed<T>) -> (NonNull<T>, Alloc) {
49 let rv = (this.ptr, this.alloc);
50 core::mem::forget(this);
51 rv
52 }
53
54 #[inline(always)]
61 pub(crate) unsafe fn from_raw(ptr: NonNull<T>, alloc: Alloc) -> Boxed<T> {
62 Boxed {
63 ptr,
64 alloc,
65 _marker: PhantomData,
66 }
67 }
68
69 #[inline(always)]
72 pub(crate) fn release(this: Boxed<T>, state: &mut State) {
73 let (ptr, alloc) = Boxed::into_raw(this);
74 unsafe {
76 match alloc {
77 Alloc::Arena => {
78 ArenaBox::release_in(ArenaBox::from_raw(ptr.as_ptr()), &mut state.arena)
79 }
80 Alloc::Heap => drop(Box::from_raw(ptr.as_ptr())),
81 }
82 }
83 }
84}
85
86impl<T> Boxed<T> {
87 #[inline(always)]
89 pub(crate) fn arena(value: T, state: &mut State) -> Boxed<T> {
90 Boxed::from_arena(ArenaBox::new(value, &mut state.arena))
91 }
92}
93
94impl<T: ?Sized> From<Box<T>> for Boxed<T> {
95 fn from(value: Box<T>) -> Boxed<T> {
97 Boxed {
98 ptr: unsafe { NonNull::new_unchecked(Box::into_raw(value)) },
100 alloc: Alloc::Heap,
101 _marker: PhantomData,
102 }
103 }
104}
105
106impl<T: ?Sized> Deref for Boxed<T> {
107 type Target = T;
108
109 #[inline(always)]
110 fn deref(&self) -> &T {
111 unsafe { self.ptr.as_ref() }
113 }
114}
115
116impl<T: ?Sized> DerefMut for Boxed<T> {
117 #[inline(always)]
118 fn deref_mut(&mut self) -> &mut T {
119 unsafe { self.ptr.as_mut() }
121 }
122}
123
124impl<T: ?Sized> Drop for Boxed<T> {
125 fn drop(&mut self) {
126 unsafe {
128 match self.alloc {
129 Alloc::Arena => drop(ArenaBox::from_raw(self.ptr.as_ptr())),
130 Alloc::Heap => drop(Box::from_raw(self.ptr.as_ptr())),
131 }
132 }
133 }
134}
135
136impl<T: ?Sized + fmt::Debug> fmt::Debug for Boxed<T> {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 fmt::Debug::fmt(&**self, f)
139 }
140}
141
142#[inline(always)]
146pub(crate) fn unsize<T, U: ?Sized>(value: Boxed<T>, cast: fn(*mut T) -> *mut U) -> Boxed<U> {
147 let (ptr, alloc) = Boxed::into_raw(value);
148 unsafe { Boxed::from_raw(NonNull::new_unchecked(cast(ptr.as_ptr())), alloc) }
150}