Skip to main content

bump_scope/fixed_bump_string/
raw.rs

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