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#[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 pub fn new() -> Self {
58 Self {
59 bytes: Bytes::new(),
60 }
61 }
62
63 pub fn from_static(bytes: &'static str) -> Self {
74 Self {
75 bytes: Bytes::from_static(bytes.as_bytes()),
76 }
77 }
78
79 pub fn from_utf8(bytes: Bytes) -> Result<Self, Utf8Error> {
92 std::str::from_utf8(&bytes)?;
93
94 Ok(Self { bytes })
95 }
96
97 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 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 pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> Self {
139 Self { bytes }
140 }
141
142 pub unsafe fn from_utf8_vec_unchecked(bytes: Vec<u8>) -> Self {
151 Self::from_utf8_unchecked(Bytes::from(bytes))
152 }
153
154 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 pub unsafe fn from_utf8_slice_unchecked(bytes: &[u8]) -> Self {
183 Self {
184 bytes: Bytes::copy_from_slice(bytes),
185 }
186 }
187
188 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 pub unsafe fn from_static_utf8_slice_unchecked(bytes: &'static [u8]) -> Self {
216 Self {
217 bytes: Bytes::from_static(bytes),
218 }
219 }
220
221 pub fn as_str(&self) -> &str {
233 unsafe { std::str::from_utf8_unchecked(&self.bytes) }
234 }
235
236 pub fn into_bytes(self) -> Bytes {
250 self.bytes
251 }
252
253 pub const fn len(&self) -> usize {
265 self.bytes.len()
266 }
267
268 pub const fn is_empty(&self) -> bool {
280 self.bytes.is_empty()
281 }
282
283 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 pub fn slice_ref(&self, subset: &str) -> Self {
317 Self {
318 bytes: self.bytes.slice_ref(subset.as_bytes()),
319 }
320 }
321
322 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
514impl 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 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 let bytes = Bytes::from("한국어".as_bytes());
606 let s = BytesStr::from_utf8(bytes).unwrap();
607 assert_eq!(s.as_str(), "한국어");
608
609 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 let vec = "한국어 🎉".as_bytes().to_vec();
622 let s = BytesStr::from_utf8_vec(vec).unwrap();
623 assert_eq!(s.as_str(), "한국어 🎉");
624
625 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 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 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 let s = BytesStr::from_utf8_slice("한국어".as_bytes()).unwrap();
661 assert_eq!(s.as_str(), "한국어");
662
663 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 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 let s = BytesStr::from_static_utf8_slice("한국어".as_bytes()).unwrap();
684 assert_eq!(s.as_str(), "한국어");
685
686 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 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 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 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 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 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 assert_eq!(s, "hello");
839 assert_ne!(s, "world");
840
841 assert_eq!("hello", s);
843 assert_ne!("world", s);
844
845 let hello_str = "hello";
847 let world_str = "world";
848 assert_eq!(s, hello_str);
849 assert_ne!(s, world_str);
850
851 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 assert_eq!(s, string);
864 assert_ne!(s, other_string);
865
866 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 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 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 }
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); let korean = BytesStr::from_static("한국어");
975 assert_eq!(korean.len(), 9); assert_eq!(&korean[0..6], "한국"); }
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 assert_eq!(map.get("key"), Some(&"value"));
1011 }
1012
1013 #[test]
1014 fn test_memory_efficiency() {
1015 let original = BytesStr::from(String::from("hello world"));
1017 let clone1 = original.clone();
1018 let clone2 = original.clone();
1019
1020 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 assert_eq!(original, clone1);
1027 assert_eq!(clone1, clone2);
1028 }
1029
1030 #[test]
1031 fn test_static_vs_owned() {
1032 let static_str = BytesStr::from_static("hello");
1034 assert_eq!(static_str.as_str(), "hello");
1035
1036 let owned_str = BytesStr::from(String::from("hello"));
1038 assert_eq!(owned_str.as_str(), "hello");
1039
1040 assert_eq!(static_str, owned_str);
1042 }
1043
1044 #[test]
1045 fn test_error_cases() {
1046 let invalid_sequences = vec![
1048 vec![0xff], vec![0xfe, 0xff], vec![0xc0, 0x80], vec![0xe0, 0x80, 0x80], ];
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 let s = BytesStr::from_static("a");
1065 assert_eq!(s.len(), 1);
1066 assert_eq!(s.as_str(), "a");
1067
1068 let s = BytesStr::from_static("한");
1070 assert_eq!(s.len(), 3); assert_eq!(s.as_str(), "한");
1072
1073 let s = BytesStr::from_static("🌍");
1075 assert_eq!(s.len(), 4); assert_eq!(s.as_str(), "🌍");
1077 }
1078}