bytes_str/
byte_str.rs

1use std::{
2    borrow::{Borrow, Cow},
3    cmp::Ordering,
4    ffi::OsStr,
5    fmt::{self, Debug, Display},
6    hash::{Hash, Hasher},
7    ops::{Deref, Index},
8    path::Path,
9    slice::SliceIndex,
10    str::Utf8Error,
11};
12
13use bytes::Bytes;
14
15use crate::BytesString;
16
17/// A reference-counted `str` backed by [Bytes].
18///
19/// Clone is cheap thanks to [Bytes].
20///
21///
22/// # Features
23///
24/// ## `rkyv`
25///
26/// If the `rkyv` feature is enabled, the [BytesStr] type will be
27/// [rkyv::Archive], [rkyv::Serialize], and [rkyv::Deserialize].
28///
29///
30/// ## `serde`
31///
32/// If the `serde` feature is enabled, the [BytesStr] type will be
33/// [serde::Serialize] and [serde::Deserialize].
34///
35/// The [BytesStr] type will be serialized as a [str] type.
36#[derive(Clone, Default, PartialEq, Eq)]
37#[cfg_attr(
38    feature = "rkyv",
39    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
40)]
41pub struct BytesStr {
42    pub(crate) bytes: Bytes,
43}
44
45impl BytesStr {
46    /// Creates a new empty BytesStr.
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use bytes_str::BytesStr;
52    ///
53    /// let s = BytesStr::new();
54    ///
55    /// assert_eq!(s.as_str(), "");
56    /// ```
57    pub fn new() -> Self {
58        Self {
59            bytes: Bytes::new(),
60        }
61    }
62
63    /// Creates a new BytesStr from a static string.
64    ///
65    /// # Examples
66    ///
67    /// ```
68    /// use bytes_str::BytesStr;
69    pub fn from_static(bytes: &'static str) -> Self {
70        Self {
71            bytes: Bytes::from_static(bytes.as_bytes()),
72        }
73    }
74
75    /// Creates a new BytesStr from a [Bytes].
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use bytes_str::BytesStr;
81    /// use bytes::Bytes;
82    ///
83    /// let s = BytesStr::from_utf8(Bytes::from_static(b"hello")).unwrap();
84    ///
85    /// assert_eq!(s.as_str(), "hello");
86    /// ```
87    pub fn from_utf8(bytes: Bytes) -> Result<Self, Utf8Error> {
88        std::str::from_utf8(&bytes)?;
89
90        Ok(Self { bytes })
91    }
92
93    /// Creates a new BytesStr from a [Vec<u8>].
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use bytes_str::BytesStr;
99    /// use bytes::Bytes;
100    ///
101    /// let s = BytesStr::from_utf8_vec(b"hello".to_vec()).unwrap();
102    ///
103    /// assert_eq!(s.as_str(), "hello");
104    /// ```
105    pub fn from_utf8_vec(bytes: Vec<u8>) -> Result<Self, Utf8Error> {
106        std::str::from_utf8(&bytes)?;
107
108        Ok(Self {
109            bytes: Bytes::from(bytes),
110        })
111    }
112
113    /// Creates a new BytesStr from a [Bytes] without checking if the bytes
114    /// are valid UTF-8.
115    ///
116    /// # Safety
117    ///
118    /// This function is unsafe because it does not check if the bytes are valid
119    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
120    pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> Self {
121        Self { bytes }
122    }
123
124    /// Creates a new BytesStr from a [Vec<u8>] without checking if the bytes
125    /// are valid UTF-8.
126    ///
127    /// # Safety
128    ///
129    /// This function is unsafe because it does not check if the bytes are valid
130    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
131    /// be invalid.
132    pub unsafe fn from_utf8_vec_unchecked(bytes: Vec<u8>) -> Self {
133        Self::from_utf8_unchecked(Bytes::from(bytes))
134    }
135
136    /// Creates a new BytesStr from a [Bytes].
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use bytes_str::BytesStr;
142    /// use bytes::Bytes;
143    ///     
144    /// let s = BytesStr::from_utf8_slice(b"hello").unwrap();
145    ///
146    /// assert_eq!(s.as_str(), "hello");
147    /// ```
148    pub fn from_utf8_slice(bytes: &[u8]) -> Result<Self, Utf8Error> {
149        std::str::from_utf8(bytes)?;
150
151        Ok(Self {
152            bytes: Bytes::copy_from_slice(bytes),
153        })
154    }
155
156    /// Creates a new BytesStr from a [Bytes] without checking if the bytes
157    /// are valid UTF-8.
158    ///
159    /// # Safety
160    ///
161    /// This function is unsafe because it does not check if the bytes are valid
162    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
163    /// be invalid.
164    pub unsafe fn from_utf8_slice_unchecked(bytes: &[u8]) -> Self {
165        Self {
166            bytes: Bytes::copy_from_slice(bytes),
167        }
168    }
169
170    /// Creates a new BytesStr from a static UTF-8 slice.
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// use bytes_str::BytesStr;
176    ///     
177    /// let s = BytesStr::from_static_utf8_slice(b"hello").unwrap();
178    ///
179    /// assert_eq!(s.as_str(), "hello");
180    /// ```
181    pub fn from_static_utf8_slice(bytes: &'static [u8]) -> Result<Self, Utf8Error> {
182        std::str::from_utf8(bytes)?;
183
184        Ok(Self {
185            bytes: Bytes::from_static(bytes),
186        })
187    }
188
189    /// Creates a new BytesStr from a static UTF-8 slice without checking if the
190    /// bytes are valid UTF-8.
191    ///
192    /// # Safety
193    ///
194    /// This function is unsafe because it does not check if the bytes are valid
195    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
196    /// be invalid.
197    pub unsafe fn from_static_utf8_slice_unchecked(bytes: &'static [u8]) -> Self {
198        Self {
199            bytes: Bytes::from_static(bytes),
200        }
201    }
202
203    /// Returns a string slice containing the entire BytesStr.
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// use bytes_str::BytesStr;
209    ///
210    /// let s = BytesStr::from_static("hello");
211    ///
212    /// assert_eq!(s.as_str(), "hello");
213    /// ```
214    pub fn as_str(&self) -> &str {
215        unsafe { std::str::from_utf8_unchecked(&self.bytes) }
216    }
217}
218
219impl Deref for BytesStr {
220    type Target = str;
221
222    fn deref(&self) -> &Self::Target {
223        self.as_ref()
224    }
225}
226
227impl AsRef<str> for BytesStr {
228    fn as_ref(&self) -> &str {
229        self.as_str()
230    }
231}
232
233impl From<String> for BytesStr {
234    fn from(s: String) -> Self {
235        Self {
236            bytes: Bytes::from(s),
237        }
238    }
239}
240
241impl From<&'static str> for BytesStr {
242    fn from(s: &'static str) -> Self {
243        Self {
244            bytes: Bytes::from_static(s.as_bytes()),
245        }
246    }
247}
248
249impl From<BytesStr> for BytesString {
250    fn from(s: BytesStr) -> Self {
251        Self {
252            bytes: s.bytes.into(),
253        }
254    }
255}
256
257impl From<BytesString> for BytesStr {
258    fn from(s: BytesString) -> Self {
259        Self {
260            bytes: s.bytes.into(),
261        }
262    }
263}
264
265impl AsRef<[u8]> for BytesStr {
266    fn as_ref(&self) -> &[u8] {
267        self.bytes.as_ref()
268    }
269}
270
271impl AsRef<Bytes> for BytesStr {
272    fn as_ref(&self) -> &Bytes {
273        &self.bytes
274    }
275}
276
277impl AsRef<OsStr> for BytesStr {
278    fn as_ref(&self) -> &OsStr {
279        OsStr::new(self.as_str())
280    }
281}
282
283impl AsRef<Path> for BytesStr {
284    fn as_ref(&self) -> &Path {
285        Path::new(self.as_str())
286    }
287}
288
289impl Borrow<str> for BytesStr {
290    fn borrow(&self) -> &str {
291        self.as_str()
292    }
293}
294
295impl Debug for BytesStr {
296    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297        Debug::fmt(self.as_str(), f)
298    }
299}
300
301impl Display for BytesStr {
302    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303        Display::fmt(self.as_str(), f)
304    }
305}
306
307impl Extend<BytesStr> for BytesString {
308    fn extend<T: IntoIterator<Item = BytesStr>>(&mut self, iter: T) {
309        self.bytes.extend(iter.into_iter().map(|s| s.bytes));
310    }
311}
312
313impl<I> Index<I> for BytesStr
314where
315    I: SliceIndex<str>,
316{
317    type Output = I::Output;
318
319    fn index(&self, index: I) -> &Self::Output {
320        self.as_str().index(index)
321    }
322}
323
324impl PartialEq<str> for BytesStr {
325    fn eq(&self, other: &str) -> bool {
326        self.as_str() == other
327    }
328}
329
330impl PartialEq<&'_ str> for BytesStr {
331    fn eq(&self, other: &&str) -> bool {
332        self.as_str() == *other
333    }
334}
335
336impl PartialEq<Cow<'_, str>> for BytesStr {
337    fn eq(&self, other: &Cow<'_, str>) -> bool {
338        self.as_str() == *other
339    }
340}
341
342impl PartialEq<BytesStr> for str {
343    fn eq(&self, other: &BytesStr) -> bool {
344        self == other.as_str()
345    }
346}
347
348impl PartialEq<BytesStr> for &'_ str {
349    fn eq(&self, other: &BytesStr) -> bool {
350        *self == other.as_str()
351    }
352}
353
354impl PartialEq<BytesStr> for Bytes {
355    fn eq(&self, other: &BytesStr) -> bool {
356        self == other.as_bytes()
357    }
358}
359
360impl PartialEq<String> for BytesStr {
361    fn eq(&self, other: &String) -> bool {
362        self.as_str() == other
363    }
364}
365
366impl PartialEq<BytesStr> for String {
367    fn eq(&self, other: &BytesStr) -> bool {
368        self == other.as_str()
369    }
370}
371
372impl Ord for BytesStr {
373    fn cmp(&self, other: &Self) -> Ordering {
374        self.as_str().cmp(other.as_str())
375    }
376}
377
378impl PartialOrd for BytesStr {
379    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
380        Some(self.cmp(other))
381    }
382}
383
384/// This produces the same hash as [str]
385impl Hash for BytesStr {
386    fn hash<H: Hasher>(&self, state: &mut H) {
387        self.as_str().hash(state);
388    }
389}
390
391impl TryFrom<&'static [u8]> for BytesStr {
392    type Error = Utf8Error;
393
394    fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> {
395        Self::from_static_utf8_slice(value)
396    }
397}
398
399#[cfg(feature = "serde")]
400mod serde_impl {
401    use serde::{Deserialize, Deserializer, Serialize, Serializer};
402
403    use super::*;
404
405    impl<'de> Deserialize<'de> for BytesStr {
406        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
407        where
408            D: Deserializer<'de>,
409        {
410            let s = String::deserialize(deserializer)?;
411            Ok(Self::from(s))
412        }
413    }
414
415    impl Serialize for BytesStr {
416        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417        where
418            S: Serializer,
419        {
420            serializer.serialize_str(self.as_str())
421        }
422    }
423}