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 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 pub fn slice_ref(&self, subset: &str) -> Self {
400 Self {
401 bytes: self.bytes.slice_ref(subset.as_bytes()),
402 }
403 }
404
405 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
597impl 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 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 let bytes = Bytes::from("한국어".as_bytes());
689 let s = BytesStr::from_utf8(bytes).unwrap();
690 assert_eq!(s.as_str(), "한국어");
691
692 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 let vec = "한국어 🎉".as_bytes().to_vec();
705 let s = BytesStr::from_utf8_vec(vec).unwrap();
706 assert_eq!(s.as_str(), "한국어 🎉");
707
708 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 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 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 let s = BytesStr::from_utf8_slice("한국어".as_bytes()).unwrap();
744 assert_eq!(s.as_str(), "한국어");
745
746 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 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 let s = BytesStr::from_static_utf8_slice("한국어".as_bytes()).unwrap();
767 assert_eq!(s.as_str(), "한국어");
768
769 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 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 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 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 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 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 assert_eq!(s, "hello");
922 assert_ne!(s, "world");
923
924 assert_eq!("hello", s);
926 assert_ne!("world", s);
927
928 let hello_str = "hello";
930 let world_str = "world";
931 assert_eq!(s, hello_str);
932 assert_ne!(s, world_str);
933
934 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 assert_eq!(s, string);
947 assert_ne!(s, other_string);
948
949 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 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 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 }
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); let korean = BytesStr::from_static("한국어");
1058 assert_eq!(korean.len(), 9); assert_eq!(&korean[0..6], "한국"); }
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 assert_eq!(map.get("key"), Some(&"value"));
1094 }
1095
1096 #[test]
1097 fn test_memory_efficiency() {
1098 let original = BytesStr::from(String::from("hello world"));
1100 let clone1 = original.clone();
1101 let clone2 = original.clone();
1102
1103 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 assert_eq!(original, clone1);
1110 assert_eq!(clone1, clone2);
1111 }
1112
1113 #[test]
1114 fn test_static_vs_owned() {
1115 let static_str = BytesStr::from_static("hello");
1117 assert_eq!(static_str.as_str(), "hello");
1118
1119 let owned_str = BytesStr::from(String::from("hello"));
1121 assert_eq!(owned_str.as_str(), "hello");
1122
1123 assert_eq!(static_str, owned_str);
1125 }
1126
1127 #[test]
1128 fn test_error_cases() {
1129 let invalid_sequences = vec![
1131 vec![0xff], vec![0xfe, 0xff], vec![0xc0, 0x80], vec![0xe0, 0x80, 0x80], ];
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 let s = BytesStr::from_static("a");
1148 assert_eq!(s.len(), 1);
1149 assert_eq!(s.as_str(), "a");
1150
1151 let s = BytesStr::from_static("한");
1153 assert_eq!(s.len(), 3); assert_eq!(s.as_str(), "한");
1155
1156 let s = BytesStr::from_static("🌍");
1158 assert_eq!(s.len(), 4); assert_eq!(s.as_str(), "🌍");
1160 }
1161}