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