bump_scope/
raw_bump_box.rs

1use core::{
2    marker::PhantomData,
3    mem::{self, transmute},
4    ptr::{self, NonNull},
5};
6
7use crate::{
8    BumpBox,
9    polyfill::{non_null, transmute_mut, transmute_ref},
10};
11
12/// Like [`BumpBox`] but without its lifetime.
13#[repr(transparent)]
14pub struct RawBumpBox<T: ?Sized> {
15    pub(crate) ptr: NonNull<T>,
16
17    /// Marks ownership over T. (<https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking>)
18    marker: PhantomData<T>,
19}
20
21unsafe impl<T: ?Sized + Send> Send for RawBumpBox<T> {}
22unsafe impl<T: ?Sized + Sync> Sync for RawBumpBox<T> {}
23
24#[cfg(feature = "nightly-dropck-eyepatch")]
25unsafe impl<#[may_dangle] T: ?Sized> Drop for RawBumpBox<T> {
26    #[inline(always)]
27    fn drop(&mut self) {
28        unsafe { self.ptr.as_ptr().drop_in_place() }
29    }
30}
31
32#[cfg(not(feature = "nightly-dropck-eyepatch"))]
33impl<T: ?Sized> Drop for RawBumpBox<T> {
34    #[inline(always)]
35    fn drop(&mut self) {
36        unsafe { self.ptr.as_ptr().drop_in_place() }
37    }
38}
39
40impl<T: ?Sized> RawBumpBox<T> {
41    #[expect(dead_code)]
42    #[inline(always)]
43    pub(crate) unsafe fn cook<'a>(self) -> BumpBox<'a, T> {
44        unsafe { transmute(self) }
45    }
46
47    #[expect(dead_code)]
48    #[inline(always)]
49    pub(crate) unsafe fn cook_ref<'a>(&self) -> &BumpBox<'a, T> {
50        unsafe { transmute_ref(self) }
51    }
52
53    #[expect(dead_code)]
54    #[inline(always)]
55    pub(crate) unsafe fn cook_mut<'a>(&mut self) -> &mut BumpBox<'a, T> {
56        unsafe { transmute_mut(self) }
57    }
58
59    #[inline(always)]
60    pub(crate) unsafe fn from_cooked(cooked: BumpBox<'_, T>) -> Self {
61        Self {
62            ptr: cooked.into_raw(),
63            marker: PhantomData,
64        }
65    }
66
67    #[inline(always)]
68    pub(crate) const unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
69        Self {
70            ptr,
71            marker: PhantomData,
72        }
73    }
74
75    #[inline(always)]
76    pub(crate) fn into_ptr(self) -> NonNull<T> {
77        let ptr = unsafe { ptr::read(&raw const self.ptr) };
78        mem::forget(self);
79        ptr
80    }
81
82    #[must_use]
83    #[inline(always)]
84    pub(crate) const fn as_ptr(&self) -> *const T {
85        self.ptr.as_ptr()
86    }
87
88    #[must_use]
89    #[inline(always)]
90    pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
91        self.ptr.as_ptr()
92    }
93
94    #[must_use]
95    #[inline(always)]
96    pub const fn as_non_null(&self) -> NonNull<T> {
97        self.ptr
98    }
99}
100
101impl<T> RawBumpBox<[T]> {
102    pub(crate) const EMPTY: Self = Self {
103        ptr: NonNull::slice_from_raw_parts(NonNull::dangling(), 0),
104        marker: PhantomData,
105    };
106
107    #[inline(always)]
108    pub(crate) const fn len(&self) -> usize {
109        self.ptr.len()
110    }
111
112    #[inline(always)]
113    pub(crate) unsafe fn set_ptr(&mut self, new_ptr: NonNull<T>) {
114        non_null::set_ptr(&mut self.ptr, new_ptr);
115    }
116
117    #[inline(always)]
118    pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
119        non_null::set_len(&mut self.ptr, new_len);
120    }
121}
122
123impl RawBumpBox<str> {
124    pub(crate) const EMPTY_STR: Self = Self {
125        ptr: non_null::str_from_utf8(NonNull::slice_from_raw_parts(NonNull::dangling(), 0)),
126        marker: PhantomData,
127    };
128
129    #[inline(always)]
130    pub(crate) const fn len(&self) -> usize {
131        non_null::str_bytes(self.ptr).len()
132    }
133
134    #[inline(always)]
135    pub(crate) unsafe fn set_ptr(&mut self, new_ptr: NonNull<u8>) {
136        let len = self.len();
137        self.ptr = non_null::str_from_utf8(NonNull::slice_from_raw_parts(new_ptr, len));
138    }
139
140    #[inline(always)]
141    pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
142        let ptr = self.ptr.cast::<u8>();
143        self.ptr = non_null::str_from_utf8(NonNull::slice_from_raw_parts(ptr, new_len));
144    }
145}