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, RangeBounds},
8    path::Path,
9    slice::SliceIndex,
10    str::Utf8Error,
11};
12
13use bytes::{Buf, 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    ///
70    /// let s = BytesStr::from_static("hello");
71    /// assert_eq!(s.as_str(), "hello");
72    /// ```
73    pub fn from_static(bytes: &'static str) -> Self {
74        Self {
75            bytes: Bytes::from_static(bytes.as_bytes()),
76        }
77    }
78
79    /// Creates a new BytesStr from a [Bytes].
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use bytes_str::BytesStr;
85    /// use bytes::Bytes;
86    ///
87    /// let s = BytesStr::from_utf8(Bytes::from_static(b"hello")).unwrap();
88    ///
89    /// assert_eq!(s.as_str(), "hello");
90    /// ```
91    pub fn from_utf8(bytes: Bytes) -> Result<Self, Utf8Error> {
92        std::str::from_utf8(&bytes)?;
93
94        Ok(Self { bytes })
95    }
96
97    /// Creates a new BytesStr from a [Vec<u8>].
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use bytes_str::BytesStr;
103    /// use bytes::Bytes;
104    ///
105    /// let s = BytesStr::from_utf8_vec(b"hello".to_vec()).unwrap();
106    ///
107    /// assert_eq!(s.as_str(), "hello");
108    /// ```
109    pub fn from_utf8_vec(bytes: Vec<u8>) -> Result<Self, Utf8Error> {
110        std::str::from_utf8(&bytes)?;
111
112        Ok(Self {
113            bytes: Bytes::from(bytes),
114        })
115    }
116
117    /// Creates a new BytesStr from an owner.
118    ///
119    /// See [Bytes::from_owner] for more information.
120    pub fn from_owned_utf8<T>(owner: T) -> Result<Self, Utf8Error>
121    where
122        T: AsRef<[u8]> + Send + 'static,
123    {
124        std::str::from_utf8(owner.as_ref())?;
125
126        Ok(Self {
127            bytes: Bytes::from_owner(owner),
128        })
129    }
130
131    /// Creates a new BytesStr from a [Bytes] without checking if the bytes
132    /// are valid UTF-8.
133    ///
134    /// # Safety
135    ///
136    /// This function is unsafe because it does not check if the bytes are valid
137    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
138    pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> Self {
139        Self { bytes }
140    }
141
142    /// Creates a new BytesStr from a [Vec<u8>] without checking if the bytes
143    /// are valid UTF-8.
144    ///
145    /// # Safety
146    ///
147    /// This function is unsafe because it does not check if the bytes are valid
148    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
149    /// be invalid.
150    pub unsafe fn from_utf8_vec_unchecked(bytes: Vec<u8>) -> Self {
151        Self::from_utf8_unchecked(Bytes::from(bytes))
152    }
153
154    /// Creates a new BytesStr from a [Bytes].
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use bytes_str::BytesStr;
160    /// use bytes::Bytes;
161    ///     
162    /// let s = BytesStr::from_utf8_slice(b"hello").unwrap();
163    ///
164    /// assert_eq!(s.as_str(), "hello");
165    /// ```
166    pub fn from_utf8_slice(bytes: &[u8]) -> Result<Self, Utf8Error> {
167        std::str::from_utf8(bytes)?;
168
169        Ok(Self {
170            bytes: Bytes::copy_from_slice(bytes),
171        })
172    }
173
174    /// Creates a new BytesStr from a [Bytes] without checking if the bytes
175    /// are valid UTF-8.
176    ///
177    /// # Safety
178    ///
179    /// This function is unsafe because it does not check if the bytes are valid
180    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
181    /// be invalid.
182    pub unsafe fn from_utf8_slice_unchecked(bytes: &[u8]) -> Self {
183        Self {
184            bytes: Bytes::copy_from_slice(bytes),
185        }
186    }
187
188    /// Creates a new BytesStr from a [str].
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use bytes_str::BytesStr;
194    ///     
195    /// let s = BytesStr::from_str_slice("hello");
196    ///
197    /// assert_eq!(s.as_str(), "hello");
198    /// ```
199    pub fn from_str_slice(bytes: &str) -> Self {
200        Self {
201            bytes: Bytes::copy_from_slice(bytes.as_bytes()),
202        }
203    }
204
205    /// Creates a new BytesStr from a [String].
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use bytes_str::BytesStr;
211    ///         
212    /// let s = BytesStr::from_string("hello".to_string());
213    ///
214    /// assert_eq!(s.as_str(), "hello");
215    /// ```
216    pub fn from_string(bytes: String) -> Self {
217        Self {
218            bytes: Bytes::from(bytes),
219        }
220    }
221
222    /// Creates a new BytesStr from a static UTF-8 slice.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// use bytes_str::BytesStr;
228    ///     
229    /// let s = BytesStr::from_static_utf8_slice(b"hello").unwrap();
230    ///
231    /// assert_eq!(s.as_str(), "hello");
232    /// ```
233    pub fn from_static_utf8_slice(bytes: &'static [u8]) -> Result<Self, Utf8Error> {
234        std::str::from_utf8(bytes)?;
235
236        Ok(Self {
237            bytes: Bytes::from_static(bytes),
238        })
239    }
240
241    /// Creates a new BytesStr from a static UTF-8 slice without checking if the
242    /// bytes are valid UTF-8.
243    ///
244    /// # Safety
245    ///
246    /// This function is unsafe because it does not check if the bytes are valid
247    /// UTF-8. If the bytes are not valid UTF-8, the resulting BytesStr will
248    /// be invalid.
249    pub unsafe fn from_static_utf8_slice_unchecked(bytes: &'static [u8]) -> Self {
250        Self {
251            bytes: Bytes::from_static(bytes),
252        }
253    }
254
255    /// Returns a string slice containing the entire BytesStr.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// use bytes_str::BytesStr;
261    ///
262    /// let s = BytesStr::from_static("hello");
263    ///
264    /// assert_eq!(s.as_str(), "hello");
265    /// ```
266    pub fn as_str(&self) -> &str {
267        unsafe { std::str::from_utf8_unchecked(&self.bytes) }
268    }
269
270    /// Converts the [BytesStr] into a [Bytes].
271    ///
272    /// # Examples
273    ///
274    /// ```
275    /// use bytes_str::BytesStr;
276    /// use bytes::Bytes;
277    ///     
278    /// let s = BytesStr::from_static("hello");
279    /// let bytes = s.into_bytes();
280    ///
281    /// assert_eq!(bytes, Bytes::from_static(b"hello"));
282    /// ```
283    pub fn into_bytes(self) -> Bytes {
284        self.bytes
285    }
286
287    /// Converts the [BytesStr] into a [Vec<u8>].
288    ///
289    /// # Examples
290    ///
291    /// ```
292    /// use bytes_str::BytesStr;
293    ///     
294    /// let s = BytesStr::from_static("hello");
295    /// let vec = s.into_vec();
296    ///
297    /// assert_eq!(vec, b"hello");
298    /// ```
299    pub fn into_vec(self) -> Vec<u8> {
300        self.into_bytes().to_vec()
301    }
302
303    /// Converts the [BytesStr] into a [String].
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// use bytes_str::BytesStr;
309    ///     
310    /// let s = BytesStr::from_static("hello");
311    /// let string = s.into_string();
312    ///
313    /// assert_eq!(string, "hello");
314    /// ```
315    pub fn into_string(self) -> String {
316        unsafe {
317            // Safety: BytesStr is backed by a valid UTF-8 string.
318            String::from_utf8_unchecked(self.into_vec())
319        }
320    }
321
322    /// Returns the length of the [BytesStr].
323    ///
324    /// # Examples
325    ///
326    /// ```
327    /// use bytes_str::BytesStr;
328    ///
329    /// let s = BytesStr::from_static("hello");
330    ///
331    /// assert_eq!(s.len(), 5);
332    /// ```
333    pub const fn len(&self) -> usize {
334        self.bytes.len()
335    }
336
337    /// Returns true if the [BytesStr] is empty.
338    ///
339    /// # Examples
340    ///
341    /// ```
342    /// use bytes_str::BytesStr;
343    ///     
344    /// let s = BytesStr::new();
345    ///
346    /// assert!(s.is_empty());
347    /// ```
348    pub const fn is_empty(&self) -> bool {
349        self.bytes.is_empty()
350    }
351
352    /// Returns a slice of the [BytesStr].
353    ///
354    /// # Panics
355    ///
356    /// Panics if the bounds are not character boundaries.
357    ///
358    /// # Examples
359    ///
360    /// ```
361    /// use bytes_str::BytesStr;
362    ///     
363    /// let s = BytesStr::from_static("hello");
364    /// let slice = s.slice(1..3);
365    ///
366    /// assert_eq!(slice.as_str(), "el");
367    /// ```
368    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
369        let s = Self {
370            bytes: self.bytes.slice(range),
371        };
372
373        if !s.is_char_boundary(0) {
374            panic!("range start is not a character boundary");
375        }
376
377        if !s.is_char_boundary(s.len()) {
378            panic!("range end is not a character boundary");
379        }
380
381        s
382    }
383
384    /// See [Bytes::slice_ref]
385    pub fn slice_ref(&self, subset: &str) -> Self {
386        Self {
387            bytes: self.bytes.slice_ref(subset.as_bytes()),
388        }
389    }
390
391    /// Advances the [BytesStr] by `n` bytes.
392    ///
393    /// # Panics
394    ///
395    /// Panics if `n` is greater than the length of the [BytesStr].
396    ///
397    /// Panics if `n` is not a character boundary.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use bytes_str::BytesStr;
403    ///     
404    /// let mut s = BytesStr::from_static("hello");
405    /// s.advance(3);
406    ///
407    /// assert_eq!(s.as_str(), "lo");
408    /// ```
409    pub fn advance(&mut self, n: usize) {
410        if !self.is_char_boundary(n) {
411            panic!("n is not a character boundary");
412        }
413
414        self.bytes.advance(n);
415    }
416}
417
418impl Deref for BytesStr {
419    type Target = str;
420
421    fn deref(&self) -> &Self::Target {
422        self.as_ref()
423    }
424}
425
426impl AsRef<str> for BytesStr {
427    fn as_ref(&self) -> &str {
428        self.as_str()
429    }
430}
431
432impl From<String> for BytesStr {
433    fn from(s: String) -> Self {
434        Self {
435            bytes: Bytes::from(s),
436        }
437    }
438}
439
440impl From<&'static str> for BytesStr {
441    fn from(s: &'static str) -> Self {
442        Self {
443            bytes: Bytes::from_static(s.as_bytes()),
444        }
445    }
446}
447
448impl From<BytesStr> for BytesString {
449    fn from(s: BytesStr) -> Self {
450        Self {
451            bytes: s.bytes.into(),
452        }
453    }
454}
455
456impl From<BytesString> for BytesStr {
457    fn from(s: BytesString) -> Self {
458        Self {
459            bytes: s.bytes.into(),
460        }
461    }
462}
463
464impl AsRef<[u8]> for BytesStr {
465    fn as_ref(&self) -> &[u8] {
466        self.bytes.as_ref()
467    }
468}
469
470impl AsRef<Bytes> for BytesStr {
471    fn as_ref(&self) -> &Bytes {
472        &self.bytes
473    }
474}
475
476impl AsRef<OsStr> for BytesStr {
477    fn as_ref(&self) -> &OsStr {
478        OsStr::new(self.as_str())
479    }
480}
481
482impl AsRef<Path> for BytesStr {
483    fn as_ref(&self) -> &Path {
484        Path::new(self.as_str())
485    }
486}
487
488impl Borrow<str> for BytesStr {
489    fn borrow(&self) -> &str {
490        self.as_str()
491    }
492}
493
494impl Debug for BytesStr {
495    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496        Debug::fmt(self.as_str(), f)
497    }
498}
499
500impl Display for BytesStr {
501    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502        Display::fmt(self.as_str(), f)
503    }
504}
505
506impl Extend<BytesStr> for BytesString {
507    fn extend<T: IntoIterator<Item = BytesStr>>(&mut self, iter: T) {
508        self.bytes.extend(iter.into_iter().map(|s| s.bytes));
509    }
510}
511
512impl<I> Index<I> for BytesStr
513where
514    I: SliceIndex<str>,
515{
516    type Output = I::Output;
517
518    fn index(&self, index: I) -> &Self::Output {
519        self.as_str().index(index)
520    }
521}
522
523impl PartialEq<str> for BytesStr {
524    fn eq(&self, other: &str) -> bool {
525        self.as_str() == other
526    }
527}
528
529impl PartialEq<&'_ str> for BytesStr {
530    fn eq(&self, other: &&str) -> bool {
531        self.as_str() == *other
532    }
533}
534
535impl PartialEq<Cow<'_, str>> for BytesStr {
536    fn eq(&self, other: &Cow<'_, str>) -> bool {
537        self.as_str() == *other
538    }
539}
540
541impl PartialEq<BytesStr> for str {
542    fn eq(&self, other: &BytesStr) -> bool {
543        self == other.as_str()
544    }
545}
546
547impl PartialEq<BytesStr> for &'_ str {
548    fn eq(&self, other: &BytesStr) -> bool {
549        *self == other.as_str()
550    }
551}
552
553impl PartialEq<BytesStr> for Bytes {
554    fn eq(&self, other: &BytesStr) -> bool {
555        *self == other.bytes
556    }
557}
558
559impl PartialEq<String> for BytesStr {
560    fn eq(&self, other: &String) -> bool {
561        self.as_str() == other
562    }
563}
564
565impl PartialEq<BytesStr> for String {
566    fn eq(&self, other: &BytesStr) -> bool {
567        self == other.as_str()
568    }
569}
570
571impl Ord for BytesStr {
572    fn cmp(&self, other: &Self) -> Ordering {
573        self.as_str().cmp(other.as_str())
574    }
575}
576
577impl PartialOrd for BytesStr {
578    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
579        Some(self.cmp(other))
580    }
581}
582
583/// This produces the same hash as [str]
584impl Hash for BytesStr {
585    fn hash<H: Hasher>(&self, state: &mut H) {
586        self.as_str().hash(state);
587    }
588}
589
590impl TryFrom<&'static [u8]> for BytesStr {
591    type Error = Utf8Error;
592
593    fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> {
594        Self::from_static_utf8_slice(value)
595    }
596}
597
598#[cfg(feature = "serde")]
599mod serde_impl {
600    use serde::{Deserialize, Deserializer, Serialize, Serializer};
601
602    use super::*;
603
604    impl<'de> Deserialize<'de> for BytesStr {
605        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
606        where
607            D: Deserializer<'de>,
608        {
609            let s = String::deserialize(deserializer)?;
610            Ok(Self::from(s))
611        }
612    }
613
614    impl Serialize for BytesStr {
615        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
616        where
617            S: Serializer,
618        {
619            serializer.serialize_str(self.as_str())
620        }
621    }
622}
623
624#[cfg(test)]
625mod tests {
626    use std::{
627        borrow::{Borrow, Cow},
628        collections::{hash_map::DefaultHasher, HashMap},
629        ffi::OsStr,
630        hash::{Hash, Hasher},
631        path::Path,
632    };
633
634    use bytes::Bytes;
635
636    use super::*;
637    use crate::BytesString;
638
639    #[test]
640    fn test_new() {
641        let s = BytesStr::new();
642        assert_eq!(s.as_str(), "");
643        assert_eq!(s.len(), 0);
644        assert!(s.is_empty());
645    }
646
647    #[test]
648    fn test_default() {
649        let s: BytesStr = Default::default();
650        assert_eq!(s.as_str(), "");
651        assert_eq!(s.len(), 0);
652        assert!(s.is_empty());
653    }
654
655    #[test]
656    fn test_from_static() {
657        let s = BytesStr::from_static("hello world");
658        assert_eq!(s.as_str(), "hello world");
659        assert_eq!(s.len(), 11);
660        assert!(!s.is_empty());
661
662        // Test with unicode
663        let s = BytesStr::from_static("한국어 🌍");
664        assert_eq!(s.as_str(), "한국어 🌍");
665    }
666
667    #[test]
668    fn test_from_utf8() {
669        let bytes = Bytes::from_static(b"hello");
670        let s = BytesStr::from_utf8(bytes).unwrap();
671        assert_eq!(s.as_str(), "hello");
672
673        // Test with unicode
674        let bytes = Bytes::from("한국어".as_bytes());
675        let s = BytesStr::from_utf8(bytes).unwrap();
676        assert_eq!(s.as_str(), "한국어");
677
678        // Test with invalid UTF-8
679        let invalid_bytes = Bytes::from_static(&[0xff, 0xfe]);
680        assert!(BytesStr::from_utf8(invalid_bytes).is_err());
681    }
682
683    #[test]
684    fn test_from_utf8_vec() {
685        let vec = b"hello world".to_vec();
686        let s = BytesStr::from_utf8_vec(vec).unwrap();
687        assert_eq!(s.as_str(), "hello world");
688
689        // Test with unicode
690        let vec = "한국어 🎉".as_bytes().to_vec();
691        let s = BytesStr::from_utf8_vec(vec).unwrap();
692        assert_eq!(s.as_str(), "한국어 🎉");
693
694        // Test with invalid UTF-8
695        let invalid_vec = vec![0xff, 0xfe];
696        assert!(BytesStr::from_utf8_vec(invalid_vec).is_err());
697    }
698
699    #[test]
700    fn test_from_utf8_unchecked() {
701        let bytes = Bytes::from_static(b"hello");
702        let s = unsafe { BytesStr::from_utf8_unchecked(bytes) };
703        assert_eq!(s.as_str(), "hello");
704
705        // Test with unicode
706        let bytes = Bytes::from("한국어".as_bytes());
707        let s = unsafe { BytesStr::from_utf8_unchecked(bytes) };
708        assert_eq!(s.as_str(), "한국어");
709    }
710
711    #[test]
712    fn test_from_utf8_vec_unchecked() {
713        let vec = b"hello world".to_vec();
714        let s = unsafe { BytesStr::from_utf8_vec_unchecked(vec) };
715        assert_eq!(s.as_str(), "hello world");
716
717        // Test with unicode
718        let vec = "한국어 🎉".as_bytes().to_vec();
719        let s = unsafe { BytesStr::from_utf8_vec_unchecked(vec) };
720        assert_eq!(s.as_str(), "한국어 🎉");
721    }
722
723    #[test]
724    fn test_from_utf8_slice() {
725        let s = BytesStr::from_utf8_slice(b"hello").unwrap();
726        assert_eq!(s.as_str(), "hello");
727
728        // Test with unicode
729        let s = BytesStr::from_utf8_slice("한국어".as_bytes()).unwrap();
730        assert_eq!(s.as_str(), "한국어");
731
732        // Test with invalid UTF-8
733        assert!(BytesStr::from_utf8_slice(&[0xff, 0xfe]).is_err());
734    }
735
736    #[test]
737    fn test_from_utf8_slice_unchecked() {
738        let s = unsafe { BytesStr::from_utf8_slice_unchecked(b"hello") };
739        assert_eq!(s.as_str(), "hello");
740
741        // Test with unicode
742        let s = unsafe { BytesStr::from_utf8_slice_unchecked("한국어".as_bytes()) };
743        assert_eq!(s.as_str(), "한국어");
744    }
745
746    #[test]
747    fn test_from_static_utf8_slice() {
748        let s = BytesStr::from_static_utf8_slice(b"hello").unwrap();
749        assert_eq!(s.as_str(), "hello");
750
751        // Test with unicode
752        let s = BytesStr::from_static_utf8_slice("한국어".as_bytes()).unwrap();
753        assert_eq!(s.as_str(), "한국어");
754
755        // Test with invalid UTF-8
756        assert!(BytesStr::from_static_utf8_slice(&[0xff, 0xfe]).is_err());
757    }
758
759    #[test]
760    fn test_from_static_utf8_slice_unchecked() {
761        let s = unsafe { BytesStr::from_static_utf8_slice_unchecked(b"hello") };
762        assert_eq!(s.as_str(), "hello");
763
764        // Test with unicode
765        let s = unsafe { BytesStr::from_static_utf8_slice_unchecked("한국어".as_bytes()) };
766        assert_eq!(s.as_str(), "한국어");
767    }
768
769    #[test]
770    fn test_as_str() {
771        let s = BytesStr::from_static("hello world");
772        assert_eq!(s.as_str(), "hello world");
773
774        // Test with unicode
775        let s = BytesStr::from_static("한국어 🌍");
776        assert_eq!(s.as_str(), "한국어 🌍");
777    }
778
779    #[test]
780    fn test_deref() {
781        let s = BytesStr::from_static("hello world");
782
783        // Test that we can call str methods directly
784        assert_eq!(s.len(), 11);
785        assert!(s.contains("world"));
786        assert!(s.starts_with("hello"));
787        assert!(s.ends_with("world"));
788        assert_eq!(&s[0..5], "hello");
789    }
790
791    #[test]
792    fn test_as_ref_str() {
793        let s = BytesStr::from_static("hello");
794        let str_ref: &str = s.as_ref();
795        assert_eq!(str_ref, "hello");
796    }
797
798    #[test]
799    fn test_as_ref_bytes() {
800        let s = BytesStr::from_static("hello");
801        let bytes_ref: &[u8] = s.as_ref();
802        assert_eq!(bytes_ref, b"hello");
803    }
804
805    #[test]
806    fn test_as_ref_bytes_type() {
807        let s = BytesStr::from_static("hello");
808        let bytes_ref: &Bytes = s.as_ref();
809        assert_eq!(bytes_ref.as_ref(), b"hello");
810    }
811
812    #[test]
813    fn test_as_ref_os_str() {
814        let s = BytesStr::from_static("hello/world");
815        let os_str_ref: &OsStr = s.as_ref();
816        assert_eq!(os_str_ref, OsStr::new("hello/world"));
817    }
818
819    #[test]
820    fn test_as_ref_path() {
821        let s = BytesStr::from_static("hello/world");
822        let path_ref: &Path = s.as_ref();
823        assert_eq!(path_ref, Path::new("hello/world"));
824    }
825
826    #[test]
827    fn test_borrow() {
828        let s = BytesStr::from_static("hello");
829        let borrowed: &str = s.borrow();
830        assert_eq!(borrowed, "hello");
831    }
832
833    #[test]
834    fn test_from_string() {
835        let original = String::from("hello world");
836        let s = BytesStr::from(original);
837        assert_eq!(s.as_str(), "hello world");
838    }
839
840    #[test]
841    fn test_from_static_str() {
842        let s = BytesStr::from("hello world");
843        assert_eq!(s.as_str(), "hello world");
844    }
845
846    #[test]
847    fn test_conversion_to_bytes_string() {
848        let s = BytesStr::from_static("hello");
849        let bytes_string: BytesString = s.into();
850        assert_eq!(bytes_string.as_str(), "hello");
851    }
852
853    #[test]
854    fn test_conversion_from_bytes_string() {
855        let mut bytes_string = BytesString::from("hello");
856        bytes_string.push_str(" world");
857        let s: BytesStr = bytes_string.into();
858        assert_eq!(s.as_str(), "hello world");
859    }
860
861    #[test]
862    fn test_try_from_static_slice() {
863        let s = BytesStr::try_from(b"hello" as &'static [u8]).unwrap();
864        assert_eq!(s.as_str(), "hello");
865
866        // Test with invalid UTF-8
867        let invalid_slice: &'static [u8] = &[0xff, 0xfe];
868        assert!(BytesStr::try_from(invalid_slice).is_err());
869    }
870
871    #[test]
872    fn test_debug() {
873        let s = BytesStr::from_static("hello");
874        assert_eq!(format!("{:?}", s), "\"hello\"");
875
876        let s = BytesStr::from_static("hello\nworld");
877        assert_eq!(format!("{:?}", s), "\"hello\\nworld\"");
878    }
879
880    #[test]
881    fn test_display() {
882        let s = BytesStr::from_static("hello world");
883        assert_eq!(format!("{}", s), "hello world");
884
885        let s = BytesStr::from_static("한국어 🌍");
886        assert_eq!(format!("{}", s), "한국어 🌍");
887    }
888
889    #[test]
890    fn test_index() {
891        let s = BytesStr::from_static("hello world");
892        assert_eq!(&s[0..5], "hello");
893        assert_eq!(&s[6..], "world");
894        assert_eq!(&s[..5], "hello");
895        assert_eq!(&s[6..11], "world");
896
897        // Test with unicode
898        let s = BytesStr::from_static("한국어");
899        assert_eq!(&s[0..6], "한국");
900    }
901
902    #[test]
903    fn test_partial_eq_str() {
904        let s = BytesStr::from_static("hello");
905
906        // Test BytesStr == str
907        assert_eq!(s, "hello");
908        assert_ne!(s, "world");
909
910        // Test str == BytesStr
911        assert_eq!("hello", s);
912        assert_ne!("world", s);
913
914        // Test BytesStr == &str
915        let hello_str = "hello";
916        let world_str = "world";
917        assert_eq!(s, hello_str);
918        assert_ne!(s, world_str);
919
920        // Test &str == BytesStr
921        assert_eq!(hello_str, s);
922        assert_ne!(world_str, s);
923    }
924
925    #[test]
926    fn test_partial_eq_string() {
927        let s = BytesStr::from_static("hello");
928        let string = String::from("hello");
929        let other_string = String::from("world");
930
931        // Test BytesStr == String
932        assert_eq!(s, string);
933        assert_ne!(s, other_string);
934
935        // Test String == BytesStr
936        assert_eq!(string, s);
937        assert_ne!(other_string, s);
938    }
939
940    #[test]
941    fn test_partial_eq_cow() {
942        let s = BytesStr::from_static("hello");
943
944        assert_eq!(s, Cow::Borrowed("hello"));
945        assert_eq!(s, Cow::Owned(String::from("hello")));
946        assert_ne!(s, Cow::Borrowed("world"));
947        assert_ne!(s, Cow::Owned(String::from("world")));
948    }
949
950    #[test]
951    fn test_partial_eq_bytes() {
952        let s = BytesStr::from_static("hello");
953        let bytes = Bytes::from_static(b"hello");
954        let other_bytes = Bytes::from_static(b"world");
955
956        assert_eq!(bytes, s);
957        assert_ne!(other_bytes, s);
958    }
959
960    #[test]
961    fn test_partial_eq_bytes_str() {
962        let s1 = BytesStr::from_static("hello");
963        let s2 = BytesStr::from_static("hello");
964        let s3 = BytesStr::from_static("world");
965
966        assert_eq!(s1, s2);
967        assert_ne!(s1, s3);
968    }
969
970    #[test]
971    fn test_ordering() {
972        let s1 = BytesStr::from_static("apple");
973        let s2 = BytesStr::from_static("banana");
974        let s3 = BytesStr::from_static("apple");
975
976        assert!(s1 < s2);
977        assert!(s2 > s1);
978        assert_eq!(s1, s3);
979        assert!(s1 <= s3);
980        assert!(s1 >= s3);
981
982        // Test partial_cmp
983        assert_eq!(s1.partial_cmp(&s2), Some(std::cmp::Ordering::Less));
984        assert_eq!(s2.partial_cmp(&s1), Some(std::cmp::Ordering::Greater));
985        assert_eq!(s1.partial_cmp(&s3), Some(std::cmp::Ordering::Equal));
986    }
987
988    #[test]
989    fn test_hash() {
990        let s1 = BytesStr::from_static("hello");
991        let s2 = BytesStr::from_static("hello");
992        let s3 = BytesStr::from_static("world");
993
994        let mut hasher1 = DefaultHasher::new();
995        let mut hasher2 = DefaultHasher::new();
996        let mut hasher3 = DefaultHasher::new();
997
998        s1.hash(&mut hasher1);
999        s2.hash(&mut hasher2);
1000        s3.hash(&mut hasher3);
1001
1002        assert_eq!(hasher1.finish(), hasher2.finish());
1003        assert_ne!(hasher1.finish(), hasher3.finish());
1004
1005        // Test hash consistency with str
1006        let mut str_hasher = DefaultHasher::new();
1007        "hello".hash(&mut str_hasher);
1008        assert_eq!(hasher1.finish(), str_hasher.finish());
1009    }
1010
1011    #[test]
1012    fn test_clone() {
1013        let s1 = BytesStr::from_static("hello world");
1014        let s2 = s1.clone();
1015
1016        assert_eq!(s1, s2);
1017        assert_eq!(s1.as_str(), s2.as_str());
1018
1019        // Clone should be cheap (reference counting)
1020        // Both should point to the same underlying data
1021    }
1022
1023    #[test]
1024    fn test_extend_bytes_string() {
1025        let mut bytes_string = BytesString::from("hello");
1026        let parts = vec![
1027            BytesStr::from_static(" "),
1028            BytesStr::from_static("world"),
1029            BytesStr::from_static("!"),
1030        ];
1031
1032        bytes_string.extend(parts);
1033        assert_eq!(bytes_string.as_str(), "hello world!");
1034    }
1035
1036    #[test]
1037    fn test_unicode_handling() {
1038        let s = BytesStr::from_static("Hello 🌍 한국어 🎉");
1039        assert_eq!(s.as_str(), "Hello 🌍 한국어 🎉");
1040        assert!(s.len() > 13); // More than ASCII length due to UTF-8 encoding
1041
1042        // Test indexing with unicode (be careful with boundaries)
1043        let korean = BytesStr::from_static("한국어");
1044        assert_eq!(korean.len(), 9); // 3 characters * 3 bytes each
1045        assert_eq!(&korean[0..6], "한국"); // First two characters
1046    }
1047
1048    #[test]
1049    fn test_empty_strings() {
1050        let s = BytesStr::new();
1051        assert!(s.is_empty());
1052        assert_eq!(s.len(), 0);
1053        assert_eq!(s.as_str(), "");
1054
1055        let s = BytesStr::from_static("");
1056        assert!(s.is_empty());
1057        assert_eq!(s.len(), 0);
1058        assert_eq!(s.as_str(), "");
1059    }
1060
1061    #[test]
1062    fn test_large_strings() {
1063        let large_str = "a".repeat(10000);
1064        let s = BytesStr::from(large_str.clone());
1065        assert_eq!(s.len(), 10000);
1066        assert_eq!(s.as_str(), large_str);
1067    }
1068
1069    #[test]
1070    fn test_hash_map_usage() {
1071        let mut map = HashMap::new();
1072        let key = BytesStr::from_static("key");
1073        map.insert(key, "value");
1074
1075        let lookup_key = BytesStr::from_static("key");
1076        assert_eq!(map.get(&lookup_key), Some(&"value"));
1077
1078        // Test that string can be used to lookup BytesStr key
1079        assert_eq!(map.get("key"), Some(&"value"));
1080    }
1081
1082    #[test]
1083    fn test_memory_efficiency() {
1084        // Test that cloning is cheap (reference counting)
1085        let original = BytesStr::from(String::from("hello world"));
1086        let clone1 = original.clone();
1087        let clone2 = original.clone();
1088
1089        // All should have the same content
1090        assert_eq!(original.as_str(), "hello world");
1091        assert_eq!(clone1.as_str(), "hello world");
1092        assert_eq!(clone2.as_str(), "hello world");
1093
1094        // They should be equal
1095        assert_eq!(original, clone1);
1096        assert_eq!(clone1, clone2);
1097    }
1098
1099    #[test]
1100    fn test_static_vs_owned() {
1101        // Test static string
1102        let static_str = BytesStr::from_static("hello");
1103        assert_eq!(static_str.as_str(), "hello");
1104
1105        // Test owned string
1106        let owned_str = BytesStr::from(String::from("hello"));
1107        assert_eq!(owned_str.as_str(), "hello");
1108
1109        // They should be equal even if one is static and one is owned
1110        assert_eq!(static_str, owned_str);
1111    }
1112
1113    #[test]
1114    fn test_error_cases() {
1115        // Test various invalid UTF-8 sequences
1116        let invalid_sequences = vec![
1117            vec![0xff],             // Invalid start byte
1118            vec![0xfe, 0xff],       // Invalid sequence
1119            vec![0xc0, 0x80],       // Overlong encoding
1120            vec![0xe0, 0x80, 0x80], // Overlong encoding
1121        ];
1122
1123        for invalid in invalid_sequences {
1124            assert!(BytesStr::from_utf8(Bytes::from(invalid.clone())).is_err());
1125            assert!(BytesStr::from_utf8_vec(invalid.clone()).is_err());
1126            assert!(BytesStr::from_utf8_slice(&invalid).is_err());
1127        }
1128    }
1129
1130    #[test]
1131    fn test_boundary_conditions() {
1132        // Test with single character
1133        let s = BytesStr::from_static("a");
1134        assert_eq!(s.len(), 1);
1135        assert_eq!(s.as_str(), "a");
1136
1137        // Test with single unicode character
1138        let s = BytesStr::from_static("한");
1139        assert_eq!(s.len(), 3); // UTF-8 encoding
1140        assert_eq!(s.as_str(), "한");
1141
1142        // Test with emoji
1143        let s = BytesStr::from_static("🌍");
1144        assert_eq!(s.len(), 4); // UTF-8 encoding
1145        assert_eq!(s.as_str(), "🌍");
1146    }
1147}