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