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