1use crate::{
2 errors::IntoErr,
3 ffi::{
4 NotZeroable,
5 slice::{InvalidSliceError, Slice},
6 },
7};
8
9#[derive(Debug, Clone, Copy)]
10#[repr(transparent)]
14pub struct Str(Slice<u8>);
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum InvalidStrError {
19 InvalidSliceError(InvalidSliceError),
20 Utf8Error,
21}
22
23impl From<InvalidSliceError> for InvalidStrError {
24 fn from(value: InvalidSliceError) -> Self {
25 Self::InvalidSliceError(value)
26 }
27}
28
29impl IntoErr for InvalidStrError {
30 fn into_err(self) -> crate::errors::ErrorStatus {
31 match self {
32 Self::InvalidSliceError(e) => e.into_err(),
33 Self::Utf8Error => crate::errors::ErrorStatus::InvalidStr,
34 }
35 }
36}
37
38impl Str {
39 pub const fn from_str(s: &str) -> Self {
41 Self(Slice::from_slice(s.as_bytes()))
42 }
43
44 pub const fn as_bytes(&self) -> &Slice<u8> {
45 &self.0
46 }
47
48 pub const fn as_ptr(&self) -> *const u8 {
49 self.0.as_ptr()
50 }
51
52 pub const fn len(&self) -> usize {
53 self.0.len()
54 }
55
56 #[inline]
58 pub unsafe fn try_as_str_mut_custom<'a>(
59 &self,
60 custom_validate: impl FnOnce(*const ()) -> bool,
61 ) -> Result<&'a mut str, InvalidStrError> {
62 unsafe {
63 let byte_slice = self
64 .0
65 .try_as_slice_mut_custom(custom_validate)
66 .map_err(|e| InvalidStrError::InvalidSliceError(e))?;
67 core::str::from_utf8_mut(byte_slice).map_err(|_| InvalidStrError::Utf8Error)
68 }
69 }
70 #[inline]
72 pub unsafe fn try_as_str_custom<'a>(
73 &self,
74 custom_validate: impl FnOnce(*const ()) -> bool,
75 ) -> Result<&'a str, InvalidStrError> {
76 unsafe {
77 match self.try_as_str_mut_custom(custom_validate) {
78 Ok(str) => Ok(str),
79 Err(e) => Err(e),
80 }
81 }
82 }
83
84 #[inline]
86 pub unsafe fn try_as_str<'a>(&self) -> Result<&'a str, InvalidStrError> {
87 unsafe {
88 match self.try_as_str_custom(|_| true) {
89 Ok(str) => Ok(str),
90 Err(err) => Err(err),
91 }
92 }
93 }
94
95 #[inline]
97 pub unsafe fn try_as_str_mut<'a>(&self) -> Result<&'a mut str, InvalidStrError> {
98 unsafe {
99 match self.try_as_str_mut_custom(|_| true) {
100 Ok(str) => Ok(str),
101 Err(err) => Err(err),
102 }
103 }
104 }
105}
106
107impl Slice<Str> {
108 #[inline]
117 pub const unsafe fn from_str_slices_mut(slices: *mut [*mut str]) -> Self {
118 let old_slices = unsafe { &mut *slices };
119 let raw_slices = unsafe { &mut *(slices as *mut [Str]) };
120
121 let mut i = 0;
122 while i < old_slices.len() {
123 let slice = old_slices[i];
124 raw_slices[i] = unsafe { Str::from_str(&*slice) };
125 i += 1;
126 }
127
128 Slice::from_slice(raw_slices)
129 }
130
131 #[inline]
141 pub unsafe fn try_into_str_slices_mut<'a>(
142 self,
143 custom_validate: impl Fn(*const ()) -> bool,
144 ) -> Result<*mut [&'a str], InvalidStrError> {
145 let root = unsafe { self.try_as_slice_mut_custom(&custom_validate)? };
146 let root_ptr = root as *mut _;
147 let results = unsafe { &mut *(root_ptr as *mut [&'a str]) };
148
149 let mut i = 0;
150 while i < results.len() {
151 let slice = &root[i];
152 results[i] = unsafe { slice.try_as_str_custom(&custom_validate)? };
153 i += 1;
154 }
155
156 Ok(results)
157 }
158}
159
160impl NotZeroable for Str {
161 #[inline(always)]
162 fn is_zero(&self) -> bool {
163 self.0.is_zero()
164 }
165}