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