bump_scope/
raw_fixed_bump_string.rs1use 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#[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}