1#[cfg(feature = "std")]
2use core::mem::ManuallyDrop;
3use core::{
4 fmt,
5 fmt::Debug,
6 hash::{Hash, Hasher},
7 marker::PhantomData,
8};
9#[cfg(feature = "std")]
10use std::borrow::Cow;
11
12#[cfg(feature = "std")]
13use crate::errors::SetBytesError;
14
15#[derive(Eq, PartialOrd, Ord)]
17pub struct Bytes<'a> {
18 data: BytesInner,
20 _lt: PhantomData<&'a [u8]>,
22}
23
24#[derive(PartialEq, Eq, PartialOrd, Ord)]
31enum BytesInner {
32 Borrowed(*const u8, u32),
34 #[cfg(feature = "std")]
38 Owned(*mut u8, u32),
39}
40
41impl<'a> PartialEq<str> for Bytes<'a> {
42 #[inline]
43 fn eq(&self, other: &str) -> bool {
44 self == other.as_bytes()
45 }
46}
47
48impl<'a> PartialEq<[u8]> for Bytes<'a> {
49 #[inline]
50 fn eq(&self, other: &[u8]) -> bool {
51 self.as_bytes() == other
52 }
53}
54
55impl<'a> PartialEq for Bytes<'a> {
56 #[inline]
57 fn eq(&self, other: &Self) -> bool {
58 let this = self.as_bytes();
59 let that = other.as_bytes();
60 this == that
61 }
62}
63
64impl<'a> Hash for Bytes<'a> {
65 #[inline]
66 fn hash<H: Hasher>(&self, state: &mut H) {
67 let this = self.as_bytes();
69 this.hash(state);
70 }
71}
72
73impl<'a> Clone for Bytes<'a> {
74 fn clone(&self) -> Self {
75 match &self.data {
81 BytesInner::Borrowed(data, len) => {
82 Bytes::from(unsafe { compact_bytes_to_slice(*data, *len) })
83 }
84 #[cfg(feature = "std")]
85 BytesInner::Owned(data, len) => {
86 let (ptr, len) = unsafe { clone_compact_bytes_parts(*data, *len) };
87 Bytes {
88 data: BytesInner::Owned(ptr, len),
89 _lt: PhantomData,
90 }
91 }
92 }
93 }
94}
95
96impl<'a> From<&'a str> for Bytes<'a> {
97 #[inline]
98 fn from(s: &'a str) -> Self {
99 <Self as From<&'a [u8]>>::from(s.as_bytes())
100 }
101}
102
103impl<'a> From<&'a [u8]> for Bytes<'a> {
104 #[inline]
105 fn from(s: &'a [u8]) -> Self {
106 Bytes {
107 data: BytesInner::Borrowed(s.as_ptr(), s.len() as u32),
108 _lt: PhantomData,
109 }
110 }
111}
112
113#[cfg(feature = "std")]
114impl TryFrom<String> for Bytes<'static> {
115 type Error = SetBytesError;
116
117 #[inline]
118 fn try_from(s: String) -> Result<Self, Self::Error> {
119 let mut bytes = Bytes::new();
120 bytes.set(s)?;
121 Ok(bytes)
122 }
123}
124
125#[inline]
127unsafe fn compact_bytes_to_slice<'a>(ptr: *const u8, l: u32) -> &'a [u8] {
128 unsafe { core::slice::from_raw_parts(ptr, l as usize) }
129}
130
131#[cfg(feature = "std")]
135unsafe fn boxed_slice_into_compact_parts(slice: Box<[u8]>) -> (*mut u8, u32) {
136 let mut slice = ManuallyDrop::new(slice);
138 let len = slice.len();
139 let ptr = slice.as_mut_ptr();
140
141 (ptr, len as u32)
142}
143
144#[inline]
146#[cfg(feature = "std")]
147unsafe fn clone_compact_bytes_parts(ptr: *mut u8, len: u32) -> (*mut u8, u32) {
148 let slice = unsafe { compact_bytes_to_slice(ptr, len) }
149 .to_vec()
150 .into_boxed_slice();
151 unsafe { boxed_slice_into_compact_parts(slice) }
152}
153
154impl<'a> Debug for Bytes<'a> {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 f.debug_tuple("Bytes")
159 .field(&self.try_as_utf8_str().unwrap_or("<non-utf8>"))
160 .finish()
161 }
162}
163
164impl<'a> Default for Bytes<'a> {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170impl<'a> Bytes<'a> {
171 #[inline]
173 pub fn new() -> Self {
174 Self {
175 data: BytesInner::Borrowed("".as_bytes().as_ptr(), 0),
176 _lt: PhantomData,
177 }
178 }
179
180 #[inline]
182 #[cfg(feature = "std")]
183 pub fn as_utf8_str(&self) -> Cow<'_, str> {
184 String::from_utf8_lossy(self.as_bytes())
185 }
186
187 #[inline]
190 pub fn try_as_utf8_str(&self) -> Option<&str> {
191 core::str::from_utf8(self.as_bytes()).ok()
192 }
193
194 #[inline]
196 pub fn as_bytes(&self) -> &[u8] {
197 match &self.data {
198 BytesInner::Borrowed(b, l) => unsafe { compact_bytes_to_slice(*b, *l) },
199 #[cfg(feature = "std")]
200 BytesInner::Owned(o, l) => unsafe { compact_bytes_to_slice(*o, *l) },
201 }
202 }
203
204 #[inline]
209 pub fn as_bytes_borrowed(&self) -> Option<&'a [u8]> {
210 match &self.data {
211 BytesInner::Borrowed(b, l) => Some(unsafe { compact_bytes_to_slice(*b, *l) }),
212 #[cfg(feature = "std")]
213 _ => None,
214 }
215 }
216
217 #[inline]
219 pub fn as_ptr(&self) -> *const u8 {
220 match &self.data {
221 BytesInner::Borrowed(b, _) => *b,
222 #[cfg(feature = "std")]
223 BytesInner::Owned(o, _) => *o,
224 }
225 }
226
227 #[cfg(feature = "std")]
229 pub fn set<B: IntoOwnedBytes>(&mut self, data: B) -> Result<Option<Box<[u8]>>, SetBytesError> {
230 const MAX: usize = u32::MAX as usize;
231
232 let data = <B as IntoOwnedBytes>::into_bytes(data);
233
234 if data.len() > MAX {
235 return Err(SetBytesError::LengthOverflow);
236 }
237
238 Ok(unsafe { self.set_unchecked(data) })
240 }
241
242 #[inline]
247 #[cfg(feature = "std")]
248 pub unsafe fn set_unchecked<B: IntoOwnedBytes>(&mut self, data: B) -> Option<Box<[u8]>> {
249 let data = <B as IntoOwnedBytes>::into_bytes(data);
250
251 let (ptr, len) = unsafe { boxed_slice_into_compact_parts(data) };
252
253 let bytes = BytesInner::Owned(ptr, len);
254 let old = core::mem::replace(&mut self.data, bytes);
255
256 let old = ManuallyDrop::new(old);
258
259 match &*old {
260 BytesInner::Borrowed(_, _) => None,
261 BytesInner::Owned(ptr, len) => {
262 let len = *len as usize;
263 Some(unsafe { Vec::from_raw_parts(*ptr, len, len) }.into_boxed_slice())
264 }
265 }
266 }
267}
268
269#[cfg(feature = "std")]
270mod private {
271 pub trait Sealed {}
272}
273
274#[cfg(feature = "std")]
278pub trait IntoOwnedBytes: private::Sealed {
279 fn into_bytes(self) -> Box<[u8]>;
280}
281
282#[cfg(feature = "std")]
283macro_rules! impl_into_owned_bytes_trivial {
284 ($($t:ty),*) => {
285 $(
286 impl private::Sealed for $t {}
287 impl IntoOwnedBytes for $t {
288 #[inline]
289 fn into_bytes(self) -> Box<[u8]> {
290 self.into()
291 }
292 }
293 )*
294 };
295}
296
297#[cfg(feature = "std")]
298impl_into_owned_bytes_trivial!(Box<[u8]>, &[u8], Vec<u8>);
299
300#[cfg(feature = "std")]
301impl private::Sealed for &str {}
302#[cfg(feature = "std")]
303impl IntoOwnedBytes for &str {
304 #[inline]
305 fn into_bytes(self) -> Box<[u8]> {
306 self.as_bytes().into()
307 }
308}
309
310#[cfg(feature = "std")]
311impl private::Sealed for String {}
312#[cfg(feature = "std")]
313impl IntoOwnedBytes for String {
314 #[inline]
315 fn into_bytes(self) -> Box<[u8]> {
316 self.into_bytes().into()
317 }
318}
319
320#[cfg(feature = "std")]
321impl Drop for BytesInner {
322 fn drop(&mut self) {
323 if let BytesInner::Owned(ptr, len) = self {
326 let ptr = *ptr;
327 let len = *len as usize;
328
329 unsafe { drop(Vec::from_raw_parts(ptr, len, len).into_boxed_slice()) };
332 }
333 }
334}