1use crate::Heap;
2use crate::brand::{BrandedBlock, BrandedCell};
3use crate::heap::BlockFreeGuard;
4use core::marker::PhantomData;
5use core::ops::{Deref, DerefMut};
6use core::ptr::NonNull;
7use melinoe::ReadPermit;
8use mnemosyne_core::AllocPolicy;
9use mnemosyne_local::LocalAllocatorSelector;
10use mnemosyne_local::internal::HasSegmentPool;
11
12pub struct BrandedBox<
16 'brand,
17 'heap,
18 T: ?Sized,
19 P: AllocPolicy = mnemosyne_core::StandardPolicy,
20 B: HasSegmentPool + LocalAllocatorSelector<B> = mnemosyne_backend::MemoryBackendWrapper,
21> {
22 pub(crate) ptr: NonNull<T>,
23 pub(crate) heap: &'heap Heap<'brand, P, B>,
24 pub(crate) _non_send_sync: core::marker::PhantomData<*mut ()>,
25}
26
27impl<'brand, 'heap, T, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
28 BrandedBox<'brand, 'heap, T, P, B>
29{
30 #[inline(always)]
32 pub fn new<Permit>(heap: &'heap Heap<'brand, P, B>, permit: Permit, val: T) -> Option<Self>
33 where
34 Permit: ReadPermit<'brand>,
35 {
36 if core::mem::size_of::<T>() == 0 {
37 let ptr: NonNull<T> = NonNull::dangling();
38 unsafe {
43 ptr.as_ptr().write(val);
44 }
45 return Some(Self {
46 ptr,
47 heap,
48 _non_send_sync: core::marker::PhantomData,
49 });
50 }
51
52 let block = heap.alloc_init(permit, val)?;
53 Some(Self {
54 ptr: block.ptr,
55 heap,
56 _non_send_sync: core::marker::PhantomData,
57 })
58 }
59}
60
61impl<'brand, 'heap, T: ?Sized, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
62 BrandedBox<'brand, 'heap, T, P, B>
63{
64 #[inline(always)]
66 pub fn into_raw(self) -> BrandedBlock<'brand, T> {
67 let block = BrandedBlock {
68 ptr: self.ptr,
69 _marker: PhantomData,
70 };
71 core::mem::forget(self);
72 block
73 }
74
75 #[inline(always)]
79 pub fn into_cell(self) -> BrandedCell<'brand, T> {
80 let block = self.into_raw();
81 unsafe { BrandedCell::from_block(block) }
87 }
88
89 #[inline(always)]
95 pub unsafe fn from_cell(heap: &'heap Heap<'brand, P, B>, cell: BrandedCell<'brand, T>) -> Self {
96 unsafe { Self::from_raw(heap, cell.into_block()) }
102 }
103
104 #[inline(always)]
109 pub unsafe fn from_raw(
110 heap: &'heap Heap<'brand, P, B>,
111 block: BrandedBlock<'brand, T>,
112 ) -> Self {
113 Self {
114 ptr: block.ptr,
115 heap,
116 _non_send_sync: core::marker::PhantomData,
117 }
118 }
119}
120
121impl<'brand, 'heap, T: ?Sized, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Deref
122 for BrandedBox<'brand, 'heap, T, P, B>
123{
124 type Target = T;
125 #[inline(always)]
126 fn deref(&self) -> &Self::Target {
127 unsafe { self.ptr.as_ref() }
132 }
133}
134
135impl<'brand, 'heap, T: ?Sized, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
136 DerefMut for BrandedBox<'brand, 'heap, T, P, B>
137{
138 #[inline(always)]
139 fn deref_mut(&mut self) -> &mut Self::Target {
140 unsafe { self.ptr.as_mut() }
145 }
146}
147
148impl<'brand, 'heap, T: ?Sized, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>> Drop
149 for BrandedBox<'brand, 'heap, T, P, B>
150{
151 #[inline]
152 fn drop(&mut self) {
153 unsafe {
164 if core::mem::size_of_val(self.ptr.as_ref()) == 0 {
165 core::ptr::drop_in_place(self.ptr.as_ptr());
166 } else {
167 let _free = BlockFreeGuard::new(self.heap, self.ptr.as_ptr() as *mut u8);
168 core::ptr::drop_in_place(self.ptr.as_ptr());
169 }
170 }
171 }
172}
173
174impl<'brand, 'heap, T: Clone, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
175 BrandedBox<'brand, 'heap, T, P, B>
176{
177 #[inline]
181 pub fn clone_in<Permit>(&self, permit: &Permit) -> Option<Self>
182 where
183 for<'token> &'token Permit: ReadPermit<'brand>,
184 {
185 Self::new(self.heap, permit, (**self).clone())
186 }
187}
188
189impl<
190 'brand,
191 'heap,
192 T: ?Sized + core::fmt::Debug,
193 P: AllocPolicy,
194 B: HasSegmentPool + LocalAllocatorSelector<B>,
195> core::fmt::Debug for BrandedBox<'brand, 'heap, T, P, B>
196{
197 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
198 core::fmt::Debug::fmt(&**self, f)
199 }
200}
201
202impl<
203 'brand,
204 'heap,
205 T: ?Sized + core::fmt::Display,
206 P: AllocPolicy,
207 B: HasSegmentPool + LocalAllocatorSelector<B>,
208> core::fmt::Display for BrandedBox<'brand, 'heap, T, P, B>
209{
210 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211 core::fmt::Display::fmt(&**self, f)
212 }
213}
214
215impl<'brand, 'heap, T: ?Sized, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
216 core::fmt::Pointer for BrandedBox<'brand, 'heap, T, P, B>
217{
218 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
219 core::fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
220 }
221}
222
223impl<
224 'brand,
225 'heap,
226 T: ?Sized + PartialEq,
227 P: AllocPolicy,
228 B: HasSegmentPool + LocalAllocatorSelector<B>,
229> PartialEq for BrandedBox<'brand, 'heap, T, P, B>
230{
231 #[inline]
232 fn eq(&self, other: &Self) -> bool {
233 **self == **other
234 }
235}
236impl<'brand, 'heap, T: ?Sized + Eq, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
237 Eq for BrandedBox<'brand, 'heap, T, P, B>
238{
239}
240
241impl<
242 'brand,
243 'heap,
244 T: ?Sized + PartialOrd,
245 P: AllocPolicy,
246 B: HasSegmentPool + LocalAllocatorSelector<B>,
247> PartialOrd for BrandedBox<'brand, 'heap, T, P, B>
248{
249 #[inline]
250 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
251 (**self).partial_cmp(&**other)
252 }
253}
254impl<'brand, 'heap, T: ?Sized + Ord, P: AllocPolicy, B: HasSegmentPool + LocalAllocatorSelector<B>>
255 Ord for BrandedBox<'brand, 'heap, T, P, B>
256{
257 #[inline]
258 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
259 (**self).cmp(&**other)
260 }
261}
262impl<
263 'brand,
264 'heap,
265 T: ?Sized + core::hash::Hash,
266 P: AllocPolicy,
267 B: HasSegmentPool + LocalAllocatorSelector<B>,
268> core::hash::Hash for BrandedBox<'brand, 'heap, T, P, B>
269{
270 #[inline]
271 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
272 (**self).hash(state);
273 }
274}