Skip to main content

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