bump_scope/
raw_fixed_bump_string.rs

1use core::{mem::transmute, ptr::NonNull};
2
3use crate::{
4    BumpAllocatorExt, FixedBumpString, MutBumpAllocatorExt,
5    error_behavior::ErrorBehavior,
6    polyfill::{non_null, transmute_mut, transmute_ref},
7    raw_bump_box::RawBumpBox,
8};
9
10/// Like [`FixedBumpVec`](crate::FixedBumpVec) but without its lifetime.
11#[repr(C)]
12pub struct RawFixedBumpString {
13    initialized: RawBumpBox<str>,
14    capacity: usize,
15}
16
17impl RawFixedBumpString {
18    pub(crate) const EMPTY: Self = RawFixedBumpString {
19        initialized: RawBumpBox::EMPTY_STR,
20        capacity: 0,
21    };
22
23    #[inline(always)]
24    pub(crate) const unsafe fn cook<'a>(self) -> FixedBumpString<'a> {
25        unsafe { transmute(self) }
26    }
27
28    #[inline(always)]
29    pub(crate) const unsafe fn cook_ref<'a>(&self) -> &FixedBumpString<'a> {
30        unsafe { transmute_ref(self) }
31    }
32
33    #[inline(always)]
34    pub(crate) unsafe fn cook_mut<'a>(&mut self) -> &mut FixedBumpString<'a> {
35        unsafe { transmute_mut(self) }
36    }
37
38    #[inline(always)]
39    pub(crate) unsafe fn from_cooked(cooked: FixedBumpString<'_>) -> Self {
40        let capacity = cooked.capacity();
41        let initialized = cooked.into_boxed_str();
42        let initialized = unsafe { RawBumpBox::from_cooked(initialized) };
43        Self { initialized, capacity }
44    }
45
46    #[inline(always)]
47    pub(crate) unsafe fn allocate<B: ErrorBehavior>(allocator: &impl BumpAllocatorExt, len: usize) -> Result<Self, B> {
48        let ptr = B::allocate_slice::<u8>(allocator, len)?;
49        let initialized = unsafe { RawBumpBox::from_ptr(non_null::str_from_utf8(NonNull::slice_from_raw_parts(ptr, 0))) };
50        Ok(Self {
51            initialized,
52            capacity: len,
53        })
54    }
55
56    #[inline(always)]
57    pub(crate) unsafe fn prepare_allocation<B: ErrorBehavior>(
58        allocator: &mut impl MutBumpAllocatorExt,
59        len: usize,
60    ) -> Result<Self, B> {
61        unsafe {
62            let allocation = B::prepare_slice_allocation::<u8>(allocator, len)?;
63            let initialized = RawBumpBox::from_ptr(non_null::str_from_utf8(NonNull::slice_from_raw_parts(
64                non_null::as_non_null_ptr(allocation),
65                0,
66            )));
67
68            Ok(Self {
69                initialized,
70                capacity: allocation.len(),
71            })
72        }
73    }
74
75    #[inline(always)]
76    pub(crate) const fn len(&self) -> usize {
77        non_null::str_bytes(self.initialized.as_non_null()).len()
78    }
79
80    #[inline(always)]
81    pub(crate) const fn capacity(&self) -> usize {
82        self.capacity
83    }
84
85    #[inline(always)]
86    pub(crate) fn as_ptr(&self) -> *const u8 {
87        self.initialized.as_non_null().as_ptr().cast()
88    }
89
90    #[inline(always)]
91    pub(crate) fn as_mut_ptr(&mut self) -> *mut u8 {
92        self.initialized.as_non_null().as_ptr().cast()
93    }
94
95    #[must_use]
96    #[inline(always)]
97    pub const fn as_non_null(&self) -> NonNull<u8> {
98        self.initialized.as_non_null().cast()
99    }
100
101    #[expect(dead_code)]
102    #[inline(always)]
103    pub(crate) unsafe fn set_ptr(&mut self, new_ptr: NonNull<u8>) {
104        unsafe { self.initialized.set_ptr(new_ptr) };
105    }
106
107    #[inline(always)]
108    pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
109        unsafe { self.initialized.set_len(new_len) };
110    }
111
112    #[inline(always)]
113    #[expect(dead_code)]
114    pub(crate) unsafe fn set_cap(&mut self, new_cap: usize) {
115        self.capacity = new_cap;
116    }
117
118    #[inline(always)]
119    #[expect(dead_code)]
120    pub(crate) fn into_raw_parts(self) -> (NonNull<str>, usize) {
121        let Self { initialized, capacity } = self;
122        (initialized.into_ptr(), capacity)
123    }
124
125    #[inline(always)]
126    #[cfg(feature = "panic-on-alloc")]
127    pub(crate) unsafe fn from_raw_parts(slice: NonNull<str>, capacity: usize) -> Self {
128        Self {
129            initialized: unsafe { RawBumpBox::from_ptr(slice) },
130            capacity,
131        }
132    }
133}