1use std::{
8 borrow::{Borrow, BorrowMut, Cow},
9 boxed::Box,
10 cmp::Ordering,
11 convert::Infallible,
12 fmt,
13 hash::{self, Hash, Hasher},
14 iter::FromIterator,
15 mem,
16 ops::{Add, Deref, DerefMut, Index},
17 ptr, str,
18 string::String,
19 sync::Arc,
20};
21
22use bytes::{Bytes, BytesMut};
23use bytes_utils::{Str as BytesStr, StrMut as BytesStrMut, string::StorageMut};
24
25#[derive(Default, Clone)]
36#[repr(transparent)]
37pub struct Str(Repr<BytesStr>);
38
39pub type Utf8Error = bytes_utils::string::Utf8Error<Bytes>;
41
42pub type Utf8ErrorMut = bytes_utils::string::Utf8Error<BytesMut>;
44
45impl Str {
46 #[inline]
54 pub unsafe fn from_utf8_unchecked_owned(u: impl Into<Bytes>) -> Self {
55 Self(Repr::Heap(unsafe { BytesStr::from_inner_unchecked(u.into()) }))
57 }
58
59 #[inline]
64 pub fn promote(&mut self) -> &mut BytesStr {
65 if let Repr::Inline(buf) = &mut self.0 {
66 self.0 = Repr::Heap(buf.as_str().into());
67 }
68 let Repr::Heap(data) = &mut self.0 else {
69 unreachable!();
70 };
71 data
72 }
73
74 #[inline]
82 pub unsafe fn from_utf8_unchecked(u: &[u8]) -> Self {
83 Self::new(unsafe { str::from_utf8_unchecked(u) })
85 }
86
87 #[inline]
92 pub fn from_utf8_owned(u: impl Into<Bytes>) -> Result<Self, Utf8Error> {
93 Ok(Self(Repr::Heap(BytesStr::from_inner(u.into())?)))
94 }
95
96 #[inline]
100 pub fn from_utf8(u: &[u8]) -> Result<Self, str::Utf8Error> {
101 Ok(Self::new(str::from_utf8(u)?))
102 }
103
104 #[inline]
110 pub fn from_utf8_lossy(u: &[u8]) -> Self {
111 match String::from_utf8_lossy(u) {
112 Cow::Borrowed(text) => Self::new(text),
113 Cow::Owned(text) => Self::from(text),
114 }
115 }
116
117 #[inline]
125 pub fn new_inline(text: &str) -> Self {
126 Self(Repr::new_inline(text).expect("len <= INLINE_CAP"))
127 }
128
129 #[inline(always)]
133 pub const fn new_static(text: &'static str) -> Self {
134 Self(Repr::Heap(BytesStr::from_static(text)))
138 }
139
140 #[inline(always)]
142 pub fn new(text: impl AsRef<str>) -> Self {
143 Self(Repr::copy_from_str(text.as_ref()))
144 }
145
146 #[inline(always)]
148 pub fn as_str(&self) -> &str {
149 self.0.as_str()
150 }
151
152 #[inline(always)]
154 pub fn len(&self) -> usize {
155 self.0.len()
156 }
157
158 #[inline(always)]
160 pub fn is_empty(&self) -> bool {
161 self.0.is_empty()
162 }
163
164 #[inline(always)]
166 pub const fn is_spilled(&self) -> bool {
167 matches!(self.0, Repr::Heap(..))
168 }
169
170 #[inline(always)]
172 pub fn is_unique(&self) -> bool {
173 match &self.0 {
174 Repr::Heap(data) => data.inner().is_unique(),
175 Repr::Inline(_) => true,
176 }
177 }
178
179 #[inline]
182 pub fn strip_prefix(&self, prefix: &str) -> Option<Self> {
183 let s = self.as_str();
184 s.strip_prefix(prefix).map(|r| self.slice_ref(r))
185 }
186
187 #[inline]
190 pub fn strip_suffix(&self, suffix: &str) -> Option<Self> {
191 let s = self.as_str();
192 s.strip_suffix(suffix).map(|r| self.slice_ref(r))
193 }
194
195 #[inline]
201 pub fn slice<R>(&self, range: R) -> Self
202 where
203 str: Index<R, Output = str>,
204 {
205 match &self.0 {
206 Repr::Heap(data) => Self(Repr::Heap(data.slice(range))),
207 _ => Self::new_inline(&self[range]),
208 }
209 }
210
211 #[inline]
214 pub fn slice_ref(&self, subset: &str) -> Self {
215 match &self.0 {
216 Repr::Heap(data) => Self(Repr::Heap(data.slice_ref(subset))),
217 _ => Self::new_inline(subset),
218 }
219 }
220
221 #[inline]
227 pub fn split_at(&self, at: usize) -> (Self, Self) {
228 match &self.0 {
229 Repr::Heap(data) => {
230 let (left, right) = data.clone().split_at_bytes(at);
231 (Self(Repr::Heap(left)), Self(Repr::Heap(right)))
232 },
233 Repr::Inline(buf) => {
234 let (left, right) = buf.split_at(at);
235 (Self::new_inline(left), Self::new_inline(right))
236 },
237 }
238 }
239
240 #[inline]
243 pub fn trim_start(&self) -> Self {
244 let trimmed = self.as_str().trim_start();
245 self.slice_ref(trimmed)
246 }
247
248 #[inline]
251 pub fn trim_end(&self) -> Self {
252 let trimmed = self.as_str().trim_end();
253 self.slice_ref(trimmed)
254 }
255
256 #[inline]
259 pub fn trim(&self) -> Self {
260 let trimmed = self.as_str().trim();
261 self.slice_ref(trimmed)
262 }
263
264 #[inline]
273 pub fn truncate(&mut self, len: usize) {
274 match &mut self.0 {
275 Repr::Inline(buf) => {
276 buf.truncate(len);
277 },
278 Repr::Heap(heap) => {
279 assert!(heap.is_char_boundary(len), "Index is not on a char boundary");
280 unsafe {
284 let mut bytes = mem::take(heap).into_inner();
285 bytes.truncate(len);
286 *heap = BytesStr::from_inner_unchecked(bytes);
287 }
288 },
289 }
290 }
291
292 pub fn split<'s>(
295 &'s self,
296 separator: &'s str,
297 ) -> impl Clone + std::iter::FusedIterator<Item = Self> + 's {
298 self
299 .as_str()
300 .split(separator)
301 .map(move |s| self.slice_ref(s))
302 }
303
304 pub fn into_ascii_lowercase(self) -> Self {
308 let mut buf = StrMut::from(self);
309 buf.make_ascii_lowercase();
310 buf.freeze()
311 }
312
313 pub fn into_ascii_uppercase(self) -> Self {
317 let mut buf = StrMut::from(self);
318 buf.make_ascii_uppercase();
319 buf.freeze()
320 }
321
322 #[inline(always)]
324 pub fn as_bytes(&self) -> &[u8] {
325 self.as_str().as_bytes()
326 }
327
328 #[inline]
330 pub fn try_into_mut(self) -> Result<StrMut, Self> {
331 match self.0 {
332 Repr::Heap(data) => match data.into_inner().try_into_mut() {
333 Ok(data) => Ok(StrMut(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(data) }))),
336 Err(e) => Err(Self(Repr::Heap(unsafe { BytesStr::from_inner_unchecked(e) }))),
339 },
340 Repr::Inline(buf) => Ok(StrMut(Repr::Inline(buf))),
341 }
342 }
343}
344
345pub trait StrExt {
348 fn to_ascii_lowercase_str(&self) -> Str;
363
364 fn to_ascii_uppercase_str(&self) -> Str;
379}
380
381impl StrExt for str {
382 fn to_ascii_lowercase_str(&self) -> Str {
383 let mut s = StrMut::new(self);
384 s.make_ascii_lowercase();
385 s.freeze()
386 }
387
388 fn to_ascii_uppercase_str(&self) -> Str {
389 let mut s = StrMut::new(self);
390 s.make_ascii_uppercase();
391 s.freeze()
392 }
393}
394
395impl Eq for Str {}
400impl PartialEq<Self> for Str {
401 fn eq(&self, other: &Self) -> bool {
402 self.0.ptr_eq(&other.0) || self.as_str() == other.as_str()
403 }
404}
405
406impl PartialEq<str> for Str {
407 #[inline(always)]
408 fn eq(&self, other: &str) -> bool {
409 self.as_str() == other
410 }
411}
412
413impl PartialEq<Str> for str {
414 #[inline(always)]
415 fn eq(&self, other: &Str) -> bool {
416 other == self
417 }
418}
419
420impl<'a> PartialEq<&'a str> for Str {
421 #[inline(always)]
422 fn eq(&self, other: &&'a str) -> bool {
423 self == *other
424 }
425}
426
427impl PartialEq<Str> for &str {
428 #[inline(always)]
429 fn eq(&self, other: &Str) -> bool {
430 *self == other
431 }
432}
433
434impl PartialEq<String> for Str {
435 #[inline(always)]
436 fn eq(&self, other: &String) -> bool {
437 self.as_str() == other
438 }
439}
440
441impl PartialEq<Str> for String {
442 #[inline(always)]
443 fn eq(&self, other: &Str) -> bool {
444 other == self
445 }
446}
447
448impl<'a> PartialEq<&'a String> for Str {
449 #[inline(always)]
450 fn eq(&self, other: &&'a String) -> bool {
451 self == *other
452 }
453}
454
455impl PartialEq<Str> for &String {
456 #[inline(always)]
457 fn eq(&self, other: &Str) -> bool {
458 *self == other
459 }
460}
461
462impl Ord for Str {
463 fn cmp(&self, other: &Self) -> Ordering {
464 self.as_str().cmp(other.as_str())
465 }
466}
467
468impl PartialOrd for Str {
469 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
470 Some(self.cmp(other))
471 }
472}
473
474impl PartialOrd<str> for Str {
475 #[inline(always)]
476 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
477 self.as_str().partial_cmp(other)
478 }
479}
480
481impl PartialOrd<Str> for str {
482 #[inline(always)]
483 fn partial_cmp(&self, other: &Str) -> Option<Ordering> {
484 self.partial_cmp(other.as_str())
485 }
486}
487
488impl<'a> PartialOrd<&'a str> for Str {
489 #[inline(always)]
490 fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
491 self.partial_cmp(*other)
492 }
493}
494
495impl PartialOrd<Str> for &str {
496 #[inline(always)]
497 fn partial_cmp(&self, other: &Str) -> Option<Ordering> {
498 (*self).partial_cmp(other)
499 }
500}
501
502impl hash::Hash for Str {
503 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
504 self.as_str().hash(hasher);
505 }
506}
507
508impl fmt::Debug for Str {
513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514 fmt::Debug::fmt(self.as_str(), f)
515 }
516}
517
518impl fmt::Display for Str {
519 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
520 fmt::Display::fmt(self.as_str(), f)
521 }
522}
523
524impl fmt::Debug for StrMut {
525 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526 fmt::Debug::fmt(self.as_str(), f)
527 }
528}
529
530impl fmt::Display for StrMut {
531 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
532 fmt::Display::fmt(self.as_str(), f)
533 }
534}
535
536impl Eq for StrMut {}
541impl PartialEq<Self> for StrMut {
542 fn eq(&self, other: &Self) -> bool {
543 self.0.ptr_eq(&other.0) || self.as_str() == other.as_str()
544 }
545}
546
547impl PartialEq<str> for StrMut {
548 #[inline(always)]
549 fn eq(&self, other: &str) -> bool {
550 self.as_str() == other
551 }
552}
553
554impl PartialEq<StrMut> for str {
555 #[inline(always)]
556 fn eq(&self, other: &StrMut) -> bool {
557 other == self
558 }
559}
560
561impl<'a> PartialEq<&'a str> for StrMut {
562 #[inline(always)]
563 fn eq(&self, other: &&'a str) -> bool {
564 self == *other
565 }
566}
567
568impl PartialEq<StrMut> for &str {
569 #[inline(always)]
570 fn eq(&self, other: &StrMut) -> bool {
571 *self == other
572 }
573}
574
575impl PartialEq<String> for StrMut {
576 #[inline(always)]
577 fn eq(&self, other: &String) -> bool {
578 self.as_str() == other
579 }
580}
581
582impl PartialEq<StrMut> for String {
583 #[inline(always)]
584 fn eq(&self, other: &StrMut) -> bool {
585 other == self
586 }
587}
588
589impl<'a> PartialEq<&'a String> for StrMut {
590 #[inline(always)]
591 fn eq(&self, other: &&'a String) -> bool {
592 self == *other
593 }
594}
595
596impl PartialEq<StrMut> for &String {
597 #[inline(always)]
598 fn eq(&self, other: &StrMut) -> bool {
599 *self == other
600 }
601}
602
603impl Ord for StrMut {
604 fn cmp(&self, other: &Self) -> Ordering {
605 self.as_str().cmp(other.as_str())
606 }
607}
608
609impl PartialOrd for StrMut {
610 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
611 Some(self.cmp(other))
612 }
613}
614
615impl PartialOrd<str> for StrMut {
616 #[inline(always)]
617 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
618 self.as_str().partial_cmp(other)
619 }
620}
621
622impl PartialOrd<StrMut> for str {
623 #[inline(always)]
624 fn partial_cmp(&self, other: &StrMut) -> Option<Ordering> {
625 self.partial_cmp(other.as_str())
626 }
627}
628
629impl<'a> PartialOrd<&'a str> for StrMut {
630 #[inline(always)]
631 fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
632 self.partial_cmp(*other)
633 }
634}
635
636impl PartialOrd<StrMut> for &str {
637 #[inline(always)]
638 fn partial_cmp(&self, other: &StrMut) -> Option<Ordering> {
639 (*self).partial_cmp(other)
640 }
641}
642
643impl hash::Hash for StrMut {
644 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
645 self.as_str().hash(hasher);
646 }
647}
648
649impl AsRef<str> for Str {
654 #[inline(always)]
655 fn as_ref(&self) -> &str {
656 self.as_str()
657 }
658}
659
660impl AsRef<[u8]> for Str {
661 #[inline(always)]
662 fn as_ref(&self) -> &[u8] {
663 self.as_str().as_bytes()
664 }
665}
666
667impl AsRef<std::ffi::OsStr> for Str {
668 #[inline(always)]
669 fn as_ref(&self) -> &std::ffi::OsStr {
670 AsRef::<std::ffi::OsStr>::as_ref(self.as_str())
671 }
672}
673
674impl AsRef<std::path::Path> for Str {
675 #[inline(always)]
676 fn as_ref(&self) -> &std::path::Path {
677 AsRef::<std::path::Path>::as_ref(self.as_str())
678 }
679}
680
681impl Borrow<str> for Str {
682 #[inline(always)]
683 fn borrow(&self) -> &str {
684 self.as_str()
685 }
686}
687
688impl Deref for Str {
689 type Target = str;
690
691 #[inline(always)]
692 fn deref(&self) -> &str {
693 self.as_str()
694 }
695}
696
697impl AsRef<str> for StrMut {
698 #[inline(always)]
699 fn as_ref(&self) -> &str {
700 self.as_str()
701 }
702}
703
704impl AsMut<str> for StrMut {
705 #[inline(always)]
706 fn as_mut(&mut self) -> &mut str {
707 self.as_str_mut()
708 }
709}
710
711impl AsRef<[u8]> for StrMut {
712 #[inline(always)]
713 fn as_ref(&self) -> &[u8] {
714 self.as_str().as_bytes()
715 }
716}
717
718impl AsRef<std::ffi::OsStr> for StrMut {
719 #[inline(always)]
720 fn as_ref(&self) -> &std::ffi::OsStr {
721 AsRef::<std::ffi::OsStr>::as_ref(self.as_str())
722 }
723}
724
725impl AsRef<std::path::Path> for StrMut {
726 #[inline(always)]
727 fn as_ref(&self) -> &std::path::Path {
728 AsRef::<std::path::Path>::as_ref(self.as_str())
729 }
730}
731
732impl Borrow<str> for StrMut {
733 #[inline(always)]
734 fn borrow(&self) -> &str {
735 self.as_str()
736 }
737}
738
739impl BorrowMut<str> for StrMut {
740 #[inline(always)]
741 fn borrow_mut(&mut self) -> &mut str {
742 self.as_str_mut()
743 }
744}
745
746impl Deref for StrMut {
747 type Target = str;
748
749 #[inline(always)]
750 fn deref(&self) -> &str {
751 self.as_str()
752 }
753}
754
755impl DerefMut for StrMut {
756 #[inline(always)]
757 fn deref_mut(&mut self) -> &mut str {
758 self.as_str_mut()
759 }
760}
761
762impl Add<&str> for Str {
767 type Output = Self;
768
769 #[inline]
770 fn add(self, rhs: &str) -> Self::Output {
771 match self.try_into_mut() {
772 Ok(mut lhs) => {
773 lhs.push_str(rhs);
774 lhs.freeze()
775 },
776 Err(this) => {
777 let mut lhs = StrMut::with_capacity(this.len() + rhs.len());
778 lhs.push_str(&this);
779 lhs.push_str(rhs);
780 lhs.freeze()
781 },
782 }
783 }
784}
785
786impl Add<Str> for &str {
787 type Output = Str;
788
789 #[inline]
790 fn add(self, rhs: Str) -> Self::Output {
791 match rhs.try_into_mut() {
792 Ok(mut rhs) => {
793 rhs.insert(0, self);
794 rhs.freeze()
795 },
796 Err(rhs) => {
797 let mut result = StrMut::with_capacity(self.len() + rhs.len());
798 result.push_str(self);
799 result.push_str(rhs.as_str());
800 result.freeze()
801 },
802 }
803 }
804}
805
806impl Add<&str> for &Str {
807 type Output = Str;
808
809 #[inline]
810 fn add(self, rhs: &str) -> Self::Output {
811 let mut result = StrMut::with_capacity(self.len() + rhs.len());
812 result.push_str(self);
813 result.push_str(rhs);
814 result.freeze()
815 }
816}
817
818impl Add<&Str> for &str {
819 type Output = Str;
820
821 #[inline]
822 fn add(self, rhs: &Str) -> Self::Output {
823 let mut result = StrMut::with_capacity(self.len() + rhs.len());
824 result.push_str(self);
825 result.push_str(rhs.as_str());
826 result.freeze()
827 }
828}
829
830impl Add<&str> for StrMut {
831 type Output = Self;
832
833 #[inline]
834 fn add(mut self, rhs: &str) -> Self::Output {
835 self.push_str(rhs);
836 self
837 }
838}
839
840impl Add<StrMut> for &str {
841 type Output = StrMut;
842
843 #[inline]
844 fn add(self, mut rhs: StrMut) -> Self::Output {
845 rhs.insert(0, self);
847 rhs
848 }
849}
850
851impl Add<&str> for &StrMut {
852 type Output = StrMut;
853
854 #[inline]
855 fn add(self, rhs: &str) -> Self::Output {
856 let mut result = StrMut::with_capacity(self.len() + rhs.len());
857 result.push_str(self.as_str());
858 result.push_str(rhs);
859 result
860 }
861}
862
863impl Add<&StrMut> for &str {
864 type Output = StrMut;
865
866 #[inline]
867 fn add(self, rhs: &StrMut) -> Self::Output {
868 let mut result = StrMut::with_capacity(self.len() + rhs.len());
869 result.push_str(self);
870 result.push_str(rhs.as_str());
871 result
872 }
873}
874
875impl Add<Self> for Str {
877 type Output = Self;
878
879 #[inline]
880 fn add(self, rhs: Self) -> Self::Output {
881 match self.try_into_mut() {
882 Ok(mut lhs) => {
883 lhs.push_str(&rhs);
884 lhs.freeze()
885 },
886 Err(lhs) => match rhs.try_into_mut() {
887 Ok(mut rhs) => {
888 rhs.insert(0, &lhs);
889 rhs.freeze()
890 },
891 Err(rhs) => {
892 let mut result = StrMut::with_capacity(lhs.len() + rhs.len());
893 result.push_str(&lhs);
894 result.push_str(&rhs);
895 result.freeze()
896 },
897 },
898 }
899 }
900}
901
902impl Add<&Self> for Str {
903 type Output = Self;
904
905 #[inline]
906 fn add(self, rhs: &Self) -> Self::Output {
907 match self.try_into_mut() {
908 Ok(mut lhs) => {
909 lhs.push_str(rhs);
910 lhs.freeze()
911 },
912 Err(lhs) => {
913 let mut result = StrMut::with_capacity(lhs.len() + rhs.len());
914 result.push_str(&lhs);
915 result.push_str(rhs);
916 result.freeze()
917 },
918 }
919 }
920}
921
922impl Add<Str> for &Str {
923 type Output = Str;
924
925 #[inline]
926 fn add(self, rhs: Str) -> Self::Output {
927 match rhs.try_into_mut() {
928 Ok(mut rhs) => {
929 rhs.insert(0, self);
930 rhs.freeze()
931 },
932 Err(rhs) => {
933 let mut result = StrMut::with_capacity(self.len() + rhs.len());
934 result.push_str(self);
935 result.push_str(&rhs);
936 result.freeze()
937 },
938 }
939 }
940}
941
942impl Add<&Str> for &Str {
943 type Output = Str;
944
945 #[inline]
946 fn add(self, rhs: &Str) -> Self::Output {
947 let mut result = StrMut::with_capacity(self.len() + rhs.len());
948 result.push_str(self);
949 result.push_str(rhs);
950 result.freeze()
951 }
952}
953
954impl Add<Self> for StrMut {
956 type Output = Self;
957
958 #[inline]
959 fn add(mut self, rhs: Self) -> Self::Output {
960 self.push_str(&rhs);
961 self
962 }
963}
964
965impl Add<&Self> for StrMut {
966 type Output = Self;
967
968 #[inline]
969 fn add(mut self, rhs: &Self) -> Self::Output {
970 self.push_str(rhs.as_str());
971 self
972 }
973}
974
975impl Add<StrMut> for &StrMut {
976 type Output = StrMut;
977
978 #[inline]
979 fn add(self, mut rhs: StrMut) -> Self::Output {
980 rhs.insert(0, self.as_str());
981 rhs
982 }
983}
984
985impl Add<&StrMut> for &StrMut {
986 type Output = StrMut;
987
988 #[inline]
989 fn add(self, rhs: &StrMut) -> Self::Output {
990 let mut result = StrMut::with_capacity(self.len() + rhs.len());
991 result.push_str(self.as_str());
992 result.push_str(rhs.as_str());
993 result
994 }
995}
996
997const INLINE_CAP: usize = 23;
1002
1003#[derive(Debug)]
1004enum Repr<H> {
1005 Inline(heapless::String<INLINE_CAP, u8>),
1006 Heap(H),
1007}
1008
1009impl<H: Clone> Clone for Repr<H> {
1010 #[inline]
1011 fn clone(&self) -> Self {
1012 match self {
1013 Self::Heap(data) => Self::Heap(data.clone()),
1014 _ => unsafe { ptr::read(self as *const Self) },
1018 }
1019 }
1020}
1021
1022impl<H> Default for Repr<H> {
1023 #[inline]
1024 fn default() -> Self {
1025 Self::new()
1026 }
1027}
1028
1029impl<H> Repr<H> {
1030 #[inline(always)]
1031 const fn new() -> Self {
1032 Self::Inline(heapless::String::new())
1033 }
1034}
1035
1036impl<H> Repr<H>
1037where
1038 H: Deref<Target = str> + for<'a> From<&'a str>,
1039{
1040 #[inline(always)]
1043 fn new_inline(text: &str) -> Option<Self> {
1044 heapless::String::try_from(text).ok().map(Self::Inline)
1045 }
1046
1047 #[inline(always)]
1048 fn copy_from_str(text: &str) -> Self {
1049 match heapless::String::try_from(text) {
1050 Ok(buf) => Self::Inline(buf),
1051 Err(_) => Self::Heap(text.into()),
1052 }
1053 }
1054
1055 #[inline(always)]
1056 fn len(&self) -> usize {
1057 match self {
1058 Self::Heap(data) => data.len(),
1059 Self::Inline(buf) => buf.len(),
1060 }
1061 }
1062
1063 #[inline(always)]
1064 fn is_empty(&self) -> bool {
1065 match self {
1066 Self::Heap(data) => data.is_empty(),
1067 Self::Inline(buf) => buf.is_empty(),
1068 }
1069 }
1070
1071 #[inline]
1072 fn as_str(&self) -> &str {
1073 match self {
1074 Self::Heap(data) => data,
1075 Self::Inline(buf) => buf.as_str(),
1076 }
1077 }
1078
1079 #[inline]
1080 fn ptr_eq(&self, other: &Self) -> bool {
1081 let (this, that) = (self.as_str(), other.as_str());
1082 ptr::eq(this.as_ptr(), that.as_ptr()) && this.len() == that.len()
1085 }
1086}
1087
1088#[macro_export]
1096macro_rules! fmts {
1097 ($($tt:tt)*) => {{
1098 let mut w = $crate::str::StrMut::default();
1099 ::std::fmt::Write::write_fmt(&mut w, format_args!($($tt)*))
1100 .expect("a formatting trait implementation returned an error");
1101 w.freeze()
1102 }};
1103}
1104
1105#[macro_export]
1109macro_rules! fmts_mut {
1110 ($($tt:tt)*) => {{
1111 let mut w = $crate::str::StrMut::default();
1112 ::std::fmt::Write::write_fmt(&mut w, format_args!($($tt)*))
1113 .expect("a formatting trait implementation returned an error");
1114 w
1115 }};
1116}
1117
1118macro_rules! impl_extend {
1119 (for<$lt:lifetime> $type:ty, ($this:ident, $item:ident) => $($body:tt)*) => {
1121 impl<$lt> Extend<$type> for StrMut {
1122 fn extend<T: IntoIterator<Item = $type>>(&mut self, iter: T) {
1123 let $this: &mut StrMut = self;
1124 for $item in iter {
1125 $($body)*
1126 }
1127 }
1128 }
1129 impl<$lt> FromIterator<$type> for StrMut {
1130 fn from_iter<T: IntoIterator<Item = $type>>(iter: T) -> Self {
1131 let mut $this = StrMut::default();
1132 $this.extend(iter);
1133 $this
1134 }
1135 }
1136 impl<$lt> FromIterator<$type> for Str {
1137 fn from_iter<T: IntoIterator<Item = $type>>(iter: T) -> Self {
1138 let mut $this = StrMut::default();
1139 $this.extend(iter);
1140 $this.freeze()
1141 }
1142 }
1143 };
1144 ($type:ty, ($this:ident, $item:ident) => $($body:tt)*) => {
1146 impl Extend<$type> for StrMut {
1147 fn extend<T: IntoIterator<Item = $type>>(&mut self, iter: T) {
1148 let $this: &mut StrMut = self;
1149 for $item in iter {
1150 $($body)*
1151 }
1152 }
1153 }
1154 impl FromIterator<$type> for StrMut {
1155 fn from_iter<T: IntoIterator<Item = $type>>(iter: T) -> Self {
1156 let mut $this = StrMut::default();
1157 $this.extend(iter);
1158 $this
1159 }
1160 }
1161 impl FromIterator<$type> for Str {
1162 fn from_iter<T: IntoIterator<Item = $type>>(iter: T) -> Self {
1163 let mut $this = StrMut::default();
1164 $this.extend(iter);
1165 $this.freeze()
1166 }
1167 }
1168 };
1169}
1170
1171impl_extend!(char, (s, rhs) => s.push(rhs));
1172impl_extend!(String, (s, rhs) => s.push_str(rhs.as_str()));
1173impl_extend!(for<'a> &'a String, (s, rhs) => s.push_str(rhs.as_str()));
1174impl_extend!(for<'a> &'a str, (s, rhs) => s.push_str(rhs));
1175
1176#[derive(Default, Clone)]
1187#[repr(transparent)]
1188pub struct StrMut(Repr<BytesStrMut>);
1189
1190impl StrMut {
1191 #[inline]
1199 pub unsafe fn from_utf8_unchecked_owned(u: impl Into<BytesMut>) -> Self {
1200 Self(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(u.into()) }))
1202 }
1203
1204 #[inline]
1212 pub unsafe fn from_utf8_unchecked(u: &[u8]) -> Self {
1213 Self::new(unsafe { str::from_utf8_unchecked(u) })
1215 }
1216
1217 #[inline]
1222 pub fn from_utf8_owned(u: impl Into<BytesMut>) -> Result<Self, Utf8ErrorMut> {
1223 let u: BytesMut = u.into();
1224 Ok(Self(Repr::Heap(BytesStrMut::from_inner(u)?)))
1225 }
1226
1227 #[inline]
1231 pub fn from_utf8(u: &[u8]) -> Result<Self, str::Utf8Error> {
1232 Ok(Self::new(str::from_utf8(u)?))
1233 }
1234
1235 #[inline]
1243 pub fn new_inline(text: &str) -> Self {
1244 Self(Repr::new_inline(text).expect("len <= INLINE_CAP"))
1245 }
1246
1247 #[inline(always)]
1249 pub fn new(text: impl AsRef<str>) -> Self {
1250 Self(Repr::copy_from_str(text.as_ref()))
1251 }
1252
1253 #[inline]
1255 pub fn with_capacity(capacity: usize) -> Self {
1256 if capacity > INLINE_CAP {
1257 Self(Repr::Heap(unsafe {
1260 BytesStrMut::from_inner_unchecked(BytesMut::with_capacity(capacity))
1261 }))
1262 } else {
1263 Self(Repr::new())
1264 }
1265 }
1266
1267 #[inline(always)]
1269 pub fn as_str(&self) -> &str {
1270 self.0.as_str()
1271 }
1272
1273 #[inline(always)]
1275 pub fn as_str_mut(&mut self) -> &mut str {
1276 match &mut self.0 {
1277 Repr::Heap(data) => unsafe { str::from_utf8_unchecked_mut(data.as_bytes_mut()) },
1279 Repr::Inline(buf) => buf.as_mut_str(),
1280 }
1281 }
1282
1283 #[inline(always)]
1285 pub fn len(&self) -> usize {
1286 self.0.len()
1287 }
1288
1289 #[inline(always)]
1291 pub fn is_empty(&self) -> bool {
1292 self.0.is_empty()
1293 }
1294
1295 #[inline]
1304 pub fn truncate(&mut self, len: usize) {
1305 match &mut self.0 {
1306 Repr::Inline(buf) => {
1307 buf.truncate(len);
1308 },
1309 Repr::Heap(heap) => {
1310 assert!(heap.is_char_boundary(len), "Index is not on a char boundary");
1311 unsafe {
1314 heap.inner_mut().truncate(len);
1315 }
1316 },
1317 }
1318 }
1319
1320 #[inline(always)]
1322 pub const fn is_spilled(&self) -> bool {
1323 matches!(self.0, Repr::Heap(..))
1324 }
1325
1326 #[inline]
1329 pub fn reserve(&mut self, additional: usize) {
1330 match &mut self.0 {
1331 Repr::Inline(buf) => {
1332 let cap = buf.len() + additional;
1333 if cap > INLINE_CAP {
1334 let cap = cap.next_power_of_two();
1335 let mut heap =
1338 unsafe { BytesStrMut::from_inner_unchecked(BytesMut::with_capacity(cap)) };
1339 heap.push_str(buf.as_str());
1340 *self = Self(Repr::Heap(heap));
1341 }
1342 },
1343 Repr::Heap(heap) => {
1344 unsafe {
1347 heap.inner_mut().reserve(additional);
1348 }
1349 },
1350 }
1351 }
1352
1353 #[must_use]
1355 #[inline]
1356 pub fn freeze(self) -> Str {
1357 Str(match self.0 {
1358 Repr::Inline(buf) => Repr::Inline(buf),
1359 Repr::Heap(heap) => Repr::Heap(heap.freeze()),
1360 })
1361 }
1362
1363 #[inline]
1365 pub fn push(&mut self, c: char) {
1366 let mut buf = [0; 4];
1367 self.push_str(c.encode_utf8(&mut buf));
1368 }
1369
1370 #[inline]
1372 pub fn push_str(&mut self, s: &str) {
1373 match &mut self.0 {
1374 Repr::Inline(buf) => {
1375 let len = buf.len();
1376 if buf.push_str(s).is_err() {
1377 let mut heap = BytesMut::with_capacity((len + s.len()).next_power_of_two());
1378 heap.extend_from_slice(buf.as_bytes());
1379 heap.extend_from_slice(s.as_bytes());
1380 *self = Self(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(heap) }));
1383 }
1384 },
1385 Repr::Heap(heap) => heap.push_str(s),
1386 }
1387 }
1388
1389 #[inline]
1396 pub unsafe fn extend_from_bytes_unchecked(&mut self, s: &[u8]) {
1397 match &mut self.0 {
1398 Repr::Inline(buf) => {
1399 let len = buf.len();
1400 if unsafe { buf.as_mut_vec().extend_from_slice(s).is_err() } {
1403 let mut heap = BytesMut::with_capacity((len + s.len()).next_power_of_two());
1404 heap.extend_from_slice(buf.as_bytes());
1405 heap.extend_from_slice(s);
1406 *self = Self(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(heap) }));
1409 }
1410 },
1411 Repr::Heap(heap) => unsafe { heap.inner_mut().push_slice(s) },
1413 }
1414 }
1415
1416 #[inline]
1424 pub fn insert(&mut self, index: usize, s: &str) {
1425 match &mut self.0 {
1426 Repr::Inline(buf) => {
1427 assert!(
1429 buf.is_char_boundary(index),
1430 "index is not on a valid UTF-8 character boundary"
1431 );
1432
1433 if buf.insert_str(index, s).is_err() {
1434 let old_len = buf.len();
1436 let new_len = old_len + s.len();
1437 let mut heap = BytesMut::with_capacity(new_len.next_power_of_two());
1438
1439 heap.extend_from_slice(&buf.as_bytes()[..index]);
1441 heap.extend_from_slice(s.as_bytes());
1443 heap.extend_from_slice(&buf.as_bytes()[index..]);
1445
1446 *self = Self(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(heap) }));
1450 }
1451 },
1452 Repr::Heap(heap) => {
1453 assert!(
1454 heap.is_char_boundary(index),
1455 "index is not on a valid UTF-8 character boundary"
1456 );
1457 let inner = unsafe { heap.inner_mut() };
1460
1461 let len = inner.len();
1462 let string_len = s.len();
1463 inner.reserve(string_len);
1464
1465 unsafe {
1469 let ptr = inner.as_mut_ptr();
1470 core::ptr::copy(ptr.add(index), ptr.add(index + string_len), len - index);
1471 }
1472
1473 unsafe {
1478 core::ptr::copy_nonoverlapping(
1479 s.as_ptr(),
1480 inner.as_mut_ptr().add(index),
1481 string_len,
1482 );
1483 }
1484
1485 unsafe {
1490 inner.set_len(len + string_len);
1491 }
1492 },
1493 }
1494 }
1495}
1496
1497impl fmt::Write for StrMut {
1498 #[inline]
1499 fn write_str(&mut self, s: &str) -> fmt::Result {
1500 self.push_str(s);
1501 Ok(())
1502 }
1503}
1504
1505pub trait IntoStr: fmt::Display {
1515 fn into_str(self) -> Str
1517 where
1518 Self: Sized,
1519 {
1520 self.to_str()
1521 }
1522
1523 fn into_str_mut(self) -> StrMut
1525 where
1526 Self: Sized,
1527 {
1528 self.into_str().into()
1529 }
1530
1531 fn to_str(&self) -> Str {
1533 fmts!("{self}")
1534 }
1535
1536 fn to_strmut(&self) -> StrMut {
1538 self.to_str().into()
1539 }
1540}
1541
1542impl IntoStr for &str {
1543 #[inline]
1544 fn into_str(self) -> Str {
1545 Str::new(self)
1546 }
1547
1548 #[inline]
1549 fn into_str_mut(self) -> StrMut {
1550 StrMut::new(self)
1551 }
1552
1553 #[inline]
1554 fn to_str(&self) -> Str {
1555 Str::new(self)
1556 }
1557
1558 #[inline]
1559 fn to_strmut(&self) -> StrMut {
1560 StrMut::new(self)
1561 }
1562}
1563
1564impl IntoStr for &mut str {
1565 #[inline]
1566 fn into_str(self) -> Str {
1567 Str::new(self)
1568 }
1569
1570 #[inline]
1571 fn into_str_mut(self) -> StrMut {
1572 StrMut::new(self)
1573 }
1574
1575 #[inline]
1576 fn to_str(&self) -> Str {
1577 Str::new(self)
1578 }
1579
1580 #[inline]
1581 fn to_strmut(&self) -> StrMut {
1582 StrMut::new(self)
1583 }
1584}
1585
1586impl IntoStr for Str {
1587 #[inline]
1588 fn into_str(self) -> Str {
1589 self
1590 }
1591
1592 #[inline]
1593 fn into_str_mut(self) -> StrMut {
1594 self.into()
1595 }
1596
1597 #[inline]
1598 fn to_str(&self) -> Str {
1599 self.clone()
1600 }
1601
1602 #[inline]
1603 fn to_strmut(&self) -> StrMut {
1604 StrMut::new(self.as_str())
1605 }
1606}
1607
1608impl IntoStr for StrMut {
1609 #[inline]
1610 fn into_str(self) -> Str {
1611 self.freeze()
1612 }
1613
1614 #[inline]
1615 fn into_str_mut(self) -> StrMut {
1616 self
1617 }
1618
1619 #[inline]
1620 fn to_str(&self) -> Str {
1621 Str::new(self.as_str())
1622 }
1623
1624 #[inline]
1625 fn to_strmut(&self) -> StrMut {
1626 self.clone()
1627 }
1628}
1629
1630impl IntoStr for CowStr<'_> {
1631 #[inline]
1632 fn into_str(self) -> Str {
1633 match self {
1634 CowStr::Borrowed(s) => Str::new(s),
1635 CowStr::Owned(s) => s.freeze(),
1636 }
1637 }
1638
1639 #[inline]
1640 fn into_str_mut(self) -> StrMut {
1641 match self {
1642 CowStr::Borrowed(s) => StrMut::new(s),
1643 CowStr::Owned(s) => s,
1644 }
1645 }
1646
1647 #[inline]
1648 fn to_str(&self) -> Str {
1649 Str::new(self.as_str())
1650 }
1651
1652 #[inline]
1653 fn to_strmut(&self) -> StrMut {
1654 StrMut::new(self.as_str())
1655 }
1656}
1657
1658impl IntoStr for String {
1659 #[inline]
1660 fn into_str(self) -> Str {
1661 Str(Repr::Heap(self.into()))
1662 }
1663
1664 #[inline]
1665 fn into_str_mut(self) -> StrMut {
1666 StrMut(Repr::Heap(unsafe {
1669 BytesStrMut::from_inner_unchecked(Bytes::from(self.into_bytes()).into())
1670 }))
1671 }
1672
1673 #[inline]
1674 fn to_str(&self) -> Str {
1675 self.as_str().into()
1676 }
1677
1678 #[inline]
1679 fn to_strmut(&self) -> StrMut {
1680 self.as_str().into()
1681 }
1682}
1683
1684impl IntoStr for BytesStr {
1685 #[inline]
1686 fn into_str(self) -> Str {
1687 Str(Repr::Heap(self))
1688 }
1689
1690 #[inline]
1691 fn into_str_mut(self) -> StrMut {
1692 StrMut(Repr::Heap(unsafe { BytesStrMut::from_inner_unchecked(self.into_inner().into()) }))
1695 }
1696
1697 #[inline]
1698 fn to_str(&self) -> Str {
1699 Str(Repr::Heap(self.clone()))
1700 }
1701
1702 #[inline]
1703 fn to_strmut(&self) -> StrMut {
1704 self.deref().into()
1705 }
1706}
1707
1708impl IntoStr for Cow<'_, str> {
1709 #[inline]
1710 fn into_str(self) -> Str {
1711 match self {
1712 Cow::Borrowed(s) => Str::new(s),
1713 Cow::Owned(s) => Str(Repr::Heap(s.into())),
1714 }
1715 }
1716
1717 #[inline]
1718 fn into_str_mut(self) -> StrMut {
1719 match self {
1720 Cow::Borrowed(s) => StrMut::new(s),
1721 Cow::Owned(s) => s.into_str_mut(),
1722 }
1723 }
1724
1725 #[inline]
1726 fn to_str(&self) -> Str {
1727 match self {
1728 Cow::Borrowed(s) => Str::new(s),
1729 Cow::Owned(s) => s.into_str(),
1730 }
1731 }
1732
1733 #[inline]
1734 fn to_strmut(&self) -> StrMut {
1735 match self {
1736 Cow::Borrowed(s) => StrMut::new(s),
1737 Cow::Owned(s) => s.into_str_mut(),
1738 }
1739 }
1740}
1741
1742impl IntoStr for Box<str> {
1743 #[inline]
1744 fn into_str(self) -> Str {
1745 Str(Repr::Heap(self.into()))
1746 }
1747
1748 #[inline]
1749 fn into_str_mut(self) -> StrMut {
1750 StrMut(Repr::Heap(unsafe {
1753 BytesStrMut::from_inner_unchecked(Bytes::from(self.into_boxed_bytes()).into())
1754 }))
1755 }
1756
1757 #[inline]
1758 fn to_str(&self) -> Str {
1759 Str::new(self.as_ref())
1760 }
1761
1762 #[inline]
1763 fn to_strmut(&self) -> StrMut {
1764 StrMut::new(self.as_ref())
1765 }
1766}
1767
1768impl IntoStr for Arc<str> {
1769 #[inline]
1770 fn into_str(self) -> Str {
1771 let bytes: Arc<[u8]> = self.into();
1772 Str(Repr::Heap(unsafe { BytesStr::from_inner_unchecked(Bytes::from_owner(bytes)) }))
1775 }
1776
1777 #[inline]
1778 fn into_str_mut(self) -> StrMut {
1779 StrMut::new(self.as_ref())
1780 }
1781
1782 #[inline]
1783 fn to_str(&self) -> Str {
1784 Str::new(self.as_ref())
1785 }
1786
1787 #[inline]
1788 fn to_strmut(&self) -> StrMut {
1789 StrMut::new(self.as_ref())
1790 }
1791}
1792
1793impl<T> IntoStr for &T
1794where
1795 T: fmt::Display + ?Sized,
1796{
1797 default fn into_str(self) -> Str {
1798 fmts!("{}", self)
1799 }
1800
1801 #[inline]
1802 default fn into_str_mut(self) -> StrMut {
1803 fmts_mut!("{}", self)
1804 }
1805
1806 #[inline]
1807 default fn to_str(&self) -> Str {
1808 fmts!("{}", *self)
1809 }
1810
1811 #[inline]
1812 default fn to_strmut(&self) -> StrMut {
1813 fmts_mut!("{}", *self)
1814 }
1815}
1816
1817impl str::FromStr for Str {
1822 type Err = Infallible;
1823
1824 #[inline]
1825 fn from_str(s: &str) -> Result<Self, Self::Err> {
1826 Ok(Self::from(s))
1827 }
1828}
1829
1830impl From<fmt::Arguments<'_>> for Str {
1831 #[inline]
1832 fn from(args: fmt::Arguments<'_>) -> Self {
1833 args.into_str()
1834 }
1835}
1836
1837impl From<&str> for Str {
1838 #[inline]
1839 fn from(s: &str) -> Self {
1840 Self::new(s)
1841 }
1842}
1843
1844impl From<&mut str> for Str {
1845 #[inline]
1846 fn from(s: &mut str) -> Self {
1847 Self::new(s)
1848 }
1849}
1850
1851impl From<&str> for StrMut {
1852 #[inline]
1853 fn from(s: &str) -> Self {
1854 Self::new(s)
1855 }
1856}
1857
1858impl From<&mut str> for StrMut {
1859 #[inline]
1860 fn from(s: &mut str) -> Self {
1861 Self::new(s)
1862 }
1863}
1864
1865impl From<&String> for Str {
1866 #[inline]
1867 fn from(s: &String) -> Self {
1868 Self::new(s)
1869 }
1870}
1871
1872impl From<&String> for StrMut {
1873 #[inline]
1874 fn from(s: &String) -> Self {
1875 Self::new(s)
1876 }
1877}
1878
1879impl From<String> for Str {
1880 #[inline(always)]
1881 fn from(text: String) -> Self {
1882 Self(Repr::Heap(text.into()))
1883 }
1884}
1885
1886impl From<String> for StrMut {
1887 #[inline(always)]
1888 fn from(text: String) -> Self {
1889 Self(Repr::Heap(unsafe {
1892 BytesStrMut::from_inner_unchecked(Bytes::from(text.into_bytes()).into())
1893 }))
1894 }
1895}
1896
1897impl From<&BytesStr> for Str {
1898 #[inline]
1899 fn from(s: &BytesStr) -> Self {
1900 Self(Repr::Heap(s.clone()))
1901 }
1902}
1903
1904impl From<&BytesStr> for StrMut {
1905 #[inline]
1906 fn from(s: &BytesStr) -> Self {
1907 Self::new(&**s)
1908 }
1909}
1910
1911impl From<BytesStr> for Str {
1912 #[inline(always)]
1913 fn from(text: BytesStr) -> Self {
1914 Self(Repr::Heap(text))
1915 }
1916}
1917
1918impl From<BytesStr> for StrMut {
1919 #[inline(always)]
1920 fn from(text: BytesStr) -> Self {
1921 Self(Repr::Heap(unsafe {
1924 BytesStrMut::from_inner_unchecked(BytesMut::from(text.into_inner()))
1925 }))
1926 }
1927}
1928
1929impl From<BytesStrMut> for Str {
1930 #[inline]
1931 fn from(value: BytesStrMut) -> Self {
1932 Self(Repr::Heap(value.freeze()))
1933 }
1934}
1935
1936impl From<BytesStrMut> for StrMut {
1937 #[inline]
1938 fn from(value: BytesStrMut) -> Self {
1939 Self(Repr::Heap(value))
1940 }
1941}
1942
1943impl<'a> From<Cow<'a, str>> for Str {
1944 #[inline]
1945 fn from(s: Cow<'a, str>) -> Self {
1946 match s {
1947 Cow::Borrowed(borrowed) => Self::new(borrowed),
1948 Cow::Owned(owned) => Self(Repr::Heap(owned.into())),
1949 }
1950 }
1951}
1952
1953impl<'a> From<Cow<'a, str>> for StrMut {
1954 #[inline]
1955 fn from(s: Cow<'a, str>) -> Self {
1956 match s {
1957 Cow::Borrowed(borrowed) => borrowed.into(),
1958 Cow::Owned(owned) => owned.into(),
1959 }
1960 }
1961}
1962
1963impl From<Str> for BytesStr {
1964 #[inline(always)]
1965 fn from(text: Str) -> Self {
1966 match text.0 {
1967 Repr::Heap(data) => data,
1968 _ => text.as_str().into(),
1969 }
1970 }
1971}
1972
1973impl From<StrMut> for BytesStr {
1974 #[inline(always)]
1975 fn from(text: StrMut) -> Self {
1976 match text.0 {
1977 Repr::Heap(data) => data.freeze(),
1978 _ => text.as_str().into(),
1979 }
1980 }
1981}
1982
1983impl From<Str> for String {
1984 #[inline(always)]
1985 fn from(text: Str) -> Self {
1986 text.as_str().into()
1987 }
1988}
1989
1990impl From<StrMut> for String {
1991 #[inline(always)]
1992 fn from(text: StrMut) -> Self {
1993 text.as_str().into()
1994 }
1995}
1996
1997impl From<Str> for Bytes {
1998 #[inline(always)]
1999 fn from(text: Str) -> Self {
2000 match text.0 {
2001 Repr::Heap(data) => data.into(),
2002 Repr::Inline(buf) => Self::copy_from_slice(buf.as_bytes()),
2003 }
2004 }
2005}
2006
2007impl From<StrMut> for Bytes {
2008 #[inline(always)]
2009 fn from(text: StrMut) -> Self {
2010 match text.0 {
2011 Repr::Heap(data) => data.into_inner().into(),
2012 Repr::Inline(buf) => Self::copy_from_slice(buf.as_bytes()),
2013 }
2014 }
2015}
2016
2017impl From<Str> for BytesMut {
2018 #[inline(always)]
2019 fn from(value: Str) -> Self {
2020 match value.0 {
2021 Repr::Heap(data) => data.into_inner().into(),
2022 Repr::Inline(buf) => Self::from(buf.as_bytes()),
2023 }
2024 }
2025}
2026
2027impl From<StrMut> for BytesMut {
2028 #[inline(always)]
2029 fn from(text: StrMut) -> Self {
2030 match text.0 {
2031 Repr::Heap(data) => data.into_inner(),
2032 Repr::Inline(buf) => Self::from(buf.as_bytes()),
2033 }
2034 }
2035}
2036
2037impl From<Str> for BytesStrMut {
2038 #[inline(always)]
2039 fn from(value: Str) -> Self {
2040 unsafe { Self::from_inner_unchecked(BytesMut::from(value)) }
2043 }
2044}
2045
2046impl From<StrMut> for BytesStrMut {
2047 #[inline(always)]
2048 fn from(value: StrMut) -> Self {
2049 match value.0 {
2050 Repr::Heap(data) => data,
2051 Repr::Inline(buf) => unsafe { Self::from_inner_unchecked(BytesMut::from(buf.as_bytes())) },
2054 }
2055 }
2056}
2057
2058impl From<StrMut> for Str {
2059 #[inline]
2060 fn from(value: StrMut) -> Self {
2061 value.freeze()
2062 }
2063}
2064
2065impl From<Str> for StrMut {
2066 #[inline]
2067 fn from(value: Str) -> Self {
2068 match value.0 {
2069 Repr::Inline(buf) => Self(Repr::Inline(buf)),
2070 Repr::Heap(heap) => unsafe { Self::from_utf8_unchecked_owned(heap.into_inner()) },
2072 }
2073 }
2074}
2075
2076impl From<Arc<str>> for Str {
2077 #[inline]
2078 fn from(value: Arc<str>) -> Self {
2079 let bytes: Arc<[u8]> = value.into();
2080 Self(Repr::Heap(unsafe { BytesStr::from_inner_unchecked(Bytes::from_owner(bytes)) }))
2083 }
2084}
2085
2086impl From<Box<str>> for Str {
2087 #[inline]
2088 fn from(value: Box<str>) -> Self {
2089 Self(Repr::Heap(value.into()))
2090 }
2091}
2092
2093impl From<Box<str>> for StrMut {
2094 #[inline]
2095 fn from(value: Box<str>) -> Self {
2096 Self(Repr::Heap(unsafe {
2099 BytesStrMut::from_inner_unchecked(Bytes::from(value.into_boxed_bytes()).into())
2100 }))
2101 }
2102}
2103
2104impl serde::Serialize for Str {
2109 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2110 where
2111 S: serde::Serializer,
2112 {
2113 self.as_str().serialize(serializer)
2114 }
2115}
2116
2117impl<'de> serde::Deserialize<'de> for Str {
2118 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2119 where
2120 D: serde::Deserializer<'de>,
2121 {
2122 use serde::de::{Error, Unexpected};
2123 struct StrVisitor;
2124
2125 impl serde::de::Visitor<'_> for StrVisitor {
2126 type Value = Str;
2127
2128 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2129 formatter.write_str("a string")
2130 }
2131
2132 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
2133 Ok(Str::from(v))
2134 }
2135
2136 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
2137 Ok(Str::from(v))
2138 }
2139
2140 fn visit_bytes<E: Error>(self, v: &[u8]) -> Result<Self::Value, E> {
2141 match str::from_utf8(v) {
2142 Ok(s) => Ok(Str::from(s)),
2143 Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
2144 }
2145 }
2146
2147 fn visit_byte_buf<E: Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
2148 match String::from_utf8(v) {
2149 Ok(s) => Ok(Str::from(s)),
2150 Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
2151 }
2152 }
2153 }
2154
2155 deserializer.deserialize_str(StrVisitor)
2156 }
2157}
2158
2159impl serde::Serialize for CowStr<'_> {
2160 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2161 where
2162 S: serde::Serializer,
2163 {
2164 self.as_str().serialize(serializer)
2165 }
2166}
2167
2168impl<'de: 'a, 'a> serde::Deserialize<'de> for CowStr<'a> {
2169 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2170 where
2171 D: serde::Deserializer<'de>,
2172 {
2173 use serde::de::{Error, Unexpected};
2174
2175 struct CowStrVisitor;
2176
2177 impl<'de> serde::de::Visitor<'de> for CowStrVisitor {
2178 type Value = CowStr<'de>;
2179
2180 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2181 formatter.write_str("a string")
2182 }
2183
2184 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
2185 Ok(CowStr::Owned(StrMut::from(v)))
2186 }
2187
2188 fn visit_borrowed_str<E: Error>(self, v: &'de str) -> Result<Self::Value, E> {
2189 Ok(CowStr::Borrowed(v))
2190 }
2191
2192 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
2193 Ok(CowStr::Owned(StrMut::from(v)))
2194 }
2195
2196 fn visit_bytes<E: Error>(self, v: &[u8]) -> Result<Self::Value, E> {
2197 match str::from_utf8(v) {
2198 Ok(s) => Ok(CowStr::Owned(StrMut::from(s))),
2199 Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
2200 }
2201 }
2202
2203 fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
2204 where
2205 E: serde::de::Error,
2206 {
2207 match str::from_utf8(v) {
2208 Ok(s) => Ok(CowStr::Borrowed(s)),
2209 Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
2210 }
2211 }
2212
2213 fn visit_byte_buf<E: Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
2214 match String::from_utf8(v) {
2215 Ok(s) => Ok(CowStr::Owned(StrMut::from(s))),
2216 Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
2217 }
2218 }
2219 }
2220
2221 deserializer.deserialize_str(CowStrVisitor)
2222 }
2223}
2224
2225#[derive(Clone)]
2234pub enum CowStr<'a> {
2235 Borrowed(&'a str),
2237 Owned(StrMut),
2239}
2240
2241impl<'a> CowStr<'a> {
2242 #[inline]
2244 pub const fn from_str(s: &'a str) -> Self {
2245 CowStr::Borrowed(s)
2246 }
2247
2248 #[inline]
2250 pub const fn from_owned(s: StrMut) -> Self {
2251 CowStr::Owned(s)
2252 }
2253
2254 #[inline]
2256 pub fn as_str(&self) -> &str {
2257 match self {
2258 CowStr::Borrowed(s) => s,
2259 CowStr::Owned(s) => s.as_str(),
2260 }
2261 }
2262
2263 #[inline]
2265 pub fn len(&self) -> usize {
2266 self.as_str().len()
2267 }
2268
2269 #[inline]
2271 pub fn is_empty(&self) -> bool {
2272 self.as_str().is_empty()
2273 }
2274
2275 #[inline]
2277 pub const fn is_borrowed(&self) -> bool {
2278 matches!(self, CowStr::Borrowed(_))
2279 }
2280
2281 #[inline]
2283 pub const fn is_owned(&self) -> bool {
2284 matches!(self, CowStr::Owned(_))
2285 }
2286
2287 #[inline]
2289 pub fn assign_slice_ref(&mut self, subset: &'a str) {
2290 match self {
2291 CowStr::Owned(owned) => {
2292 unsafe {
2297 std::ptr::copy(subset.as_ptr(), owned.as_mut_ptr(), subset.len());
2298 owned.truncate(subset.len());
2299 }
2300 },
2301 CowStr::Borrowed(_) => *self = CowStr::Borrowed(subset),
2302 }
2303 }
2304
2305 #[inline]
2307 pub fn assign_range(&mut self, range: impl Into<std::ops::Range<usize>>) {
2308 let range = range.into();
2309 match self {
2310 CowStr::Owned(owned) => {
2311 let len = range.end - range.start;
2312 unsafe {
2318 if range.start > 0 {
2319 let base = owned.as_str_mut().as_mut_ptr();
2320 std::ptr::copy(base.add(range.start).cast_const(), base, len);
2321 }
2322 owned.truncate(len);
2323 }
2324 },
2325 CowStr::Borrowed(s) => {
2326 *self = CowStr::Borrowed(&s[range]);
2327 },
2328 }
2329 }
2330
2331 #[inline]
2340 pub fn into_range(self, range: impl Into<std::ops::Range<usize>>) -> Self {
2341 let range = range.into();
2342 match self {
2343 CowStr::Borrowed(s) => CowStr::Borrowed(&s[range]),
2344 CowStr::Owned(mut owned) => {
2345 let len = range.end - range.start;
2346 unsafe {
2352 if range.start > 0 {
2353 let base = owned.as_str_mut().as_mut_ptr();
2354 std::ptr::copy(base.add(range.start).cast_const(), base, len);
2355 }
2356 owned.truncate(len);
2357 }
2358 CowStr::Owned(owned)
2359 },
2360 }
2361 }
2362
2363 #[inline]
2372 pub fn into_slice_ref(self, subset: &'a str) -> Self {
2373 match self {
2374 CowStr::Borrowed(_) => CowStr::Borrowed(subset),
2375 CowStr::Owned(mut owned) => {
2376 unsafe {
2381 std::ptr::copy(subset.as_ptr(), owned.as_mut_ptr(), subset.len());
2382 owned.truncate(subset.len());
2383 }
2384 CowStr::Owned(owned)
2385 },
2386 }
2387 }
2388
2389 #[inline]
2391 pub fn into_owned(self) -> CowStr<'static> {
2392 match self {
2393 CowStr::Borrowed(s) => CowStr::Owned(s.into()),
2394 CowStr::Owned(owned) => CowStr::Owned(owned),
2395 }
2396 }
2397
2398 #[inline]
2400 pub fn borrow(&self) -> CowStr<'_> {
2401 match self {
2402 CowStr::Borrowed(s) => CowStr::Borrowed(s),
2403 CowStr::Owned(o) => CowStr::Borrowed(o.as_str()),
2404 }
2405 }
2406
2407 #[inline]
2409 pub fn push_str(&mut self, s: &str) {
2410 self.as_mut().push_str(s);
2411 }
2412
2413 #[inline]
2415 pub fn push(&mut self, c: char) {
2416 self.as_mut().push(c);
2417 }
2418
2419 #[inline]
2421 pub fn truncate(&mut self, len: usize) {
2422 if self.len() > len {
2423 match self {
2424 CowStr::Borrowed(s) => {
2425 *self = CowStr::Borrowed(s.split_at(len).0);
2426 },
2427 CowStr::Owned(s) => {
2428 s.truncate(len);
2429 },
2430 }
2431 }
2432 }
2433
2434 #[inline]
2438 pub fn trim(&mut self) {
2439 match self {
2440 CowStr::Borrowed(s) => {
2441 *self = CowStr::Borrowed(s.trim());
2442 },
2443 CowStr::Owned(s) => {
2444 let range = s
2445 .substr_range(s.trim())
2446 .expect("substr_range should not fail");
2447 self.assign_range(range);
2448 },
2449 }
2450 }
2451
2452 #[inline]
2456 pub fn trim_end(&mut self) {
2457 match self {
2458 CowStr::Borrowed(s) => {
2459 *self = CowStr::Borrowed(s.trim_end());
2460 },
2461 CowStr::Owned(s) => {
2462 let range = s
2463 .substr_range(s.trim_end())
2464 .expect("substr_range should not fail");
2465 self.assign_range(range);
2466 },
2467 }
2468 }
2469
2470 #[inline]
2474 pub fn trim_start(&mut self) {
2475 match self {
2476 CowStr::Borrowed(s) => {
2477 *self = CowStr::Borrowed(s.trim_start());
2478 },
2479 CowStr::Owned(s) => {
2480 let range = s
2481 .substr_range(s.trim_start())
2482 .expect("substr_range should not fail");
2483 self.assign_range(range);
2484 },
2485 }
2486 }
2487
2488 #[inline]
2490 pub fn make_ascii_lowercase(&mut self) {
2491 if self.as_str().bytes().any(|b| b.is_ascii_uppercase()) {
2493 self.as_mut().make_ascii_lowercase();
2494 }
2495 }
2496
2497 #[inline]
2499 pub fn make_ascii_uppercase(&mut self) {
2500 if self.as_str().bytes().any(|b| b.is_ascii_lowercase()) {
2502 self.as_mut().make_ascii_uppercase();
2503 }
2504 }
2505}
2506
2507impl AsMut<StrMut> for CowStr<'_> {
2508 fn as_mut(&mut self) -> &mut StrMut {
2509 match self {
2510 CowStr::Borrowed(s) => {
2511 *self = CowStr::Owned(StrMut::new(s));
2512 match self {
2513 CowStr::Owned(owned) => owned,
2514 _ => unreachable!(),
2515 }
2516 },
2517 CowStr::Owned(owned) => owned,
2518 }
2519 }
2520}
2521
2522impl<'a> From<&'a str> for CowStr<'a> {
2527 #[inline]
2528 fn from(s: &'a str) -> Self {
2529 CowStr::Borrowed(s)
2530 }
2531}
2532
2533impl From<StrMut> for CowStr<'_> {
2534 #[inline]
2535 fn from(s: StrMut) -> Self {
2536 CowStr::Owned(s)
2537 }
2538}
2539
2540impl From<Str> for CowStr<'_> {
2541 #[inline]
2542 fn from(s: Str) -> Self {
2543 CowStr::Owned(StrMut::from(s))
2544 }
2545}
2546
2547impl From<String> for CowStr<'_> {
2548 #[inline]
2549 fn from(s: String) -> Self {
2550 CowStr::Owned(StrMut::from(s))
2551 }
2552}
2553
2554impl<'a> From<Cow<'a, str>> for CowStr<'a> {
2555 #[inline]
2556 fn from(cow: Cow<'a, str>) -> Self {
2557 match cow {
2558 Cow::Borrowed(s) => CowStr::Borrowed(s),
2559 Cow::Owned(s) => CowStr::Owned(StrMut::from(s)),
2560 }
2561 }
2562}
2563
2564impl<'a> From<CowStr<'a>> for Cow<'a, str> {
2565 #[inline]
2566 fn from(cow: CowStr<'a>) -> Self {
2567 match cow {
2568 CowStr::Borrowed(s) => Cow::Borrowed(s),
2569 CowStr::Owned(s) => Cow::Owned(s.as_str().to_string()),
2570 }
2571 }
2572}
2573
2574impl<'a> From<CowStr<'a>> for Str {
2575 #[inline]
2576 fn from(cow: CowStr<'a>) -> Self {
2577 match cow {
2578 CowStr::Borrowed(s) => Self::from(s),
2579 CowStr::Owned(s) => Self::from(s),
2580 }
2581 }
2582}
2583
2584impl<'a> From<CowStr<'a>> for StrMut {
2585 #[inline]
2586 fn from(cow: CowStr<'a>) -> Self {
2587 match cow {
2588 CowStr::Borrowed(s) => Self::from(s),
2589 CowStr::Owned(s) => s,
2590 }
2591 }
2592}
2593
2594impl Deref for CowStr<'_> {
2599 type Target = str;
2600
2601 #[inline]
2602 fn deref(&self) -> &str {
2603 self.as_str()
2604 }
2605}
2606
2607impl AsRef<str> for CowStr<'_> {
2608 #[inline]
2609 fn as_ref(&self) -> &str {
2610 self.as_str()
2611 }
2612}
2613
2614impl AsRef<[u8]> for CowStr<'_> {
2615 #[inline]
2616 fn as_ref(&self) -> &[u8] {
2617 self.as_str().as_bytes()
2618 }
2619}
2620
2621impl Borrow<str> for CowStr<'_> {
2622 #[inline]
2623 fn borrow(&self) -> &str {
2624 self.as_str()
2625 }
2626}
2627
2628impl fmt::Display for CowStr<'_> {
2633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2634 fmt::Display::fmt(self.as_str(), f)
2635 }
2636}
2637
2638impl fmt::Debug for CowStr<'_> {
2639 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2640 fmt::Debug::fmt(self.as_str(), f)
2641 }
2642}
2643
2644impl PartialEq for CowStr<'_> {
2649 #[inline]
2650 fn eq(&self, other: &Self) -> bool {
2651 self.as_str() == other.as_str()
2652 }
2653}
2654
2655impl Eq for CowStr<'_> {}
2656
2657impl PartialEq<str> for CowStr<'_> {
2658 #[inline]
2659 fn eq(&self, other: &str) -> bool {
2660 self.as_str() == other
2661 }
2662}
2663
2664impl PartialEq<CowStr<'_>> for str {
2665 #[inline]
2666 fn eq(&self, other: &CowStr<'_>) -> bool {
2667 self == other.as_str()
2668 }
2669}
2670
2671impl PartialEq<&str> for CowStr<'_> {
2672 #[inline]
2673 fn eq(&self, other: &&str) -> bool {
2674 self.as_str() == *other
2675 }
2676}
2677
2678impl PartialEq<CowStr<'_>> for &str {
2679 #[inline]
2680 fn eq(&self, other: &CowStr<'_>) -> bool {
2681 *self == other.as_str()
2682 }
2683}
2684
2685impl PartialEq<String> for CowStr<'_> {
2686 #[inline]
2687 fn eq(&self, other: &String) -> bool {
2688 self.as_str() == other.as_str()
2689 }
2690}
2691
2692impl PartialEq<CowStr<'_>> for String {
2693 #[inline]
2694 fn eq(&self, other: &CowStr<'_>) -> bool {
2695 self.as_str() == other.as_str()
2696 }
2697}
2698
2699impl PartialEq<Str> for CowStr<'_> {
2700 #[inline]
2701 fn eq(&self, other: &Str) -> bool {
2702 self.as_str() == other.as_str()
2703 }
2704}
2705
2706impl PartialEq<CowStr<'_>> for Str {
2707 #[inline]
2708 fn eq(&self, other: &CowStr<'_>) -> bool {
2709 self.as_str() == other.as_str()
2710 }
2711}
2712
2713impl PartialEq<StrMut> for CowStr<'_> {
2714 #[inline]
2715 fn eq(&self, other: &StrMut) -> bool {
2716 self.as_str() == other.as_str()
2717 }
2718}
2719
2720impl PartialEq<CowStr<'_>> for StrMut {
2721 #[inline]
2722 fn eq(&self, other: &CowStr<'_>) -> bool {
2723 self.as_str() == other.as_str()
2724 }
2725}
2726
2727impl PartialOrd for CowStr<'_> {
2732 #[inline]
2733 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2734 Some(self.cmp(other))
2735 }
2736}
2737
2738impl Ord for CowStr<'_> {
2739 #[inline]
2740 fn cmp(&self, other: &Self) -> Ordering {
2741 self.as_str().cmp(other.as_str())
2742 }
2743}
2744
2745impl PartialOrd<str> for CowStr<'_> {
2746 #[inline(always)]
2747 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
2748 self.as_str().partial_cmp(other)
2749 }
2750}
2751
2752impl PartialOrd<CowStr<'_>> for str {
2753 #[inline(always)]
2754 fn partial_cmp(&self, other: &CowStr<'_>) -> Option<Ordering> {
2755 self.partial_cmp(other.as_str())
2756 }
2757}
2758
2759impl PartialOrd<&str> for CowStr<'_> {
2760 #[inline(always)]
2761 fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
2762 self.partial_cmp(*other)
2763 }
2764}
2765
2766impl PartialOrd<CowStr<'_>> for &str {
2767 #[inline(always)]
2768 fn partial_cmp(&self, other: &CowStr<'_>) -> Option<Ordering> {
2769 (*self).partial_cmp(other)
2770 }
2771}
2772
2773impl Hash for CowStr<'_> {
2778 #[inline]
2779 fn hash<H: Hasher>(&self, state: &mut H) {
2780 self.as_str().hash(state);
2781 }
2782}
2783
2784impl Default for CowStr<'_> {
2789 #[inline]
2790 fn default() -> Self {
2791 CowStr::Owned(StrMut::default())
2792 }
2793}
2794
2795#[cfg(test)]
2800mod tests {
2801 use serde_json as json;
2802
2803 use super::*;
2804
2805 const PREFIX: &str = "prefix__";
2806 const REMAINDER: &str = "abcdefghijklmnopjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2807 const LONG_TEXT: &str = "prefix__abcdefghijklmnopjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2808 const SPACED: &str = " prefix__abcdefghijklmnopjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2809
2810 fn heap_ptr(s: &Str) -> (*const u8, usize) {
2811 match &s.0 {
2812 Repr::Heap(data) => (data.inner().as_ptr(), data.len()),
2813 _ => panic!("expected heap representation"),
2814 }
2815 }
2816
2817 #[test]
2818 fn shared_buffer_prefix_slice_is_not_equal_to_parent() {
2819 let parent = Str::new(LONG_TEXT);
2820 let prefix = parent.slice(..PREFIX.len());
2821 assert_eq!(heap_ptr(&prefix).0, heap_ptr(&parent).0);
2824 assert_ne!(prefix, parent);
2825 assert_ne!(parent, prefix);
2826 assert_eq!(prefix, Str::new(PREFIX));
2827 assert_eq!(parent, parent.slice(..));
2828 }
2829
2830 #[test]
2831 fn strip_prefix_reuses_heap_storage() {
2832 let value = Str::new(LONG_TEXT);
2833 assert!(value.is_spilled());
2834
2835 let (orig_ptr, orig_len) = heap_ptr(&value);
2836 assert_eq!(orig_len, LONG_TEXT.len());
2837
2838 let remainder = value.strip_prefix(PREFIX).expect("prefix matches");
2839 assert_eq!(remainder.as_str(), REMAINDER);
2840
2841 let (rem_ptr, rem_len) = heap_ptr(&remainder);
2842 assert_eq!(rem_len, REMAINDER.len());
2843
2844 unsafe {
2847 assert_eq!(rem_ptr.offset_from(orig_ptr) as usize, PREFIX.len());
2848 }
2849 }
2850
2851 #[test]
2852 fn split_at_reuses_heap_storage() {
2853 let value = Str::new(LONG_TEXT);
2854 assert!(value.is_spilled());
2855
2856 let split_at = PREFIX.len();
2857 let (left, right) = value.split_at(split_at);
2858
2859 assert_eq!(left.as_str(), &LONG_TEXT[..split_at]);
2860 assert_eq!(right.as_str(), &LONG_TEXT[split_at..]);
2861
2862 let (orig_ptr, _) = heap_ptr(&value);
2863 let (left_ptr, left_len) = heap_ptr(&left);
2864 let (right_ptr, right_len) = heap_ptr(&right);
2865
2866 assert_eq!(left_len, split_at);
2867 assert_eq!(right_len, LONG_TEXT.len() - split_at);
2868
2869 unsafe {
2872 assert_eq!(left_ptr.offset_from(orig_ptr) as usize, 0);
2873 assert_eq!(right_ptr.offset_from(orig_ptr) as usize, split_at);
2874 }
2875 }
2876
2877 #[test]
2878 fn trim_start_reuses_heap_storage() {
2879 let value = Str::new(SPACED);
2880 assert!(value.is_spilled());
2881
2882 let trimmed = value.trim_start();
2883 assert_eq!(trimmed.as_str(), LONG_TEXT);
2884
2885 let (orig_ptr, _) = heap_ptr(&value);
2886 let (trim_ptr, _) = heap_ptr(&trimmed);
2887
2888 unsafe {
2891 assert_eq!(trim_ptr.offset_from(orig_ptr) as usize, 3);
2892 }
2893 }
2894
2895 #[test]
2896 fn test_add_operations() {
2897 let s1 = Str::new("hello");
2899 let result = s1 + " world";
2900 assert_eq!(result.as_str(), "hello world");
2901
2902 let s2 = Str::new("world");
2904 let result = "hello " + s2;
2905 assert_eq!(result.as_str(), "hello world");
2906
2907 let s3 = Str::new("hello");
2909 let result = &s3 + " world";
2910 assert_eq!(result.as_str(), "hello world");
2911
2912 let s4 = Str::new("world");
2914 let result = "hello " + &s4;
2915 assert_eq!(result.as_str(), "hello world");
2916
2917 let m1 = StrMut::new("hello");
2919 let result = m1 + " world";
2920 assert_eq!(result.as_str(), "hello world");
2921
2922 let m2 = StrMut::new("world");
2924 let result = "hello " + m2;
2925 assert_eq!(result.as_str(), "hello world");
2926
2927 let m3 = StrMut::new("hello");
2929 let result = &m3 + " world";
2930 assert_eq!(result.as_str(), "hello world");
2931
2932 let m4 = StrMut::new("world");
2934 let result = "hello " + &m4;
2935 assert_eq!(result.as_str(), "hello world");
2936
2937 let long = Str::new("this is a very long string that will be heap allocated");
2939 let result = &long + " and more";
2940 assert_eq!(
2941 result.as_str(),
2942 "this is a very long string that will be heap allocated and more"
2943 );
2944 }
2945
2946 #[test]
2947 fn test_insert_inline_to_heap_promotion() {
2948 let mut s = StrMut::new("hello world");
2950 assert!(!s.is_spilled()); s.insert(6, "beautiful and wonderful ");
2954 assert_eq!(s.as_str(), "hello beautiful and wonderful world");
2955 assert!(s.is_spilled()); let mut s = StrMut::new("world");
2959 s.insert(0, "hello ");
2960 assert_eq!(s.as_str(), "hello world");
2961
2962 let mut s = StrMut::new("hello");
2964 s.insert(5, " world");
2965 assert_eq!(s.as_str(), "hello world");
2966
2967 let mut s = StrMut::new("12345678901234567890"); s.insert(10, "ABCDE"); assert_eq!(s.as_str(), "1234567890ABCDE1234567890");
2971 assert!(s.is_spilled());
2972 }
2973
2974 #[test]
2975 fn test_cow_basic_operations() {
2976 let s = "hello world";
2978 let cow = CowStr::from(s);
2979 assert!(cow.is_borrowed());
2980 assert!(!cow.is_owned());
2981 assert_eq!(cow.as_str(), "hello world");
2982 assert_eq!(cow.len(), 11);
2983 assert!(!cow.is_empty());
2984
2985 let mut_str = StrMut::new("hello");
2987 let cow = CowStr::from(mut_str);
2988 assert!(!cow.is_borrowed());
2989 assert!(cow.is_owned());
2990 assert_eq!(cow.as_str(), "hello");
2991 }
2992
2993 #[test]
2994 fn test_cow_to_mut() {
2995 let s = "hello";
2997 let mut cow = CowStr::from(s);
2998 assert!(cow.is_borrowed());
2999
3000 let mutable = cow.as_mut();
3002 mutable.push_str(" world");
3003 assert!(cow.is_owned());
3004 assert_eq!(cow.as_str(), "hello world");
3005
3006 let mutable2 = cow.as_mut();
3008 mutable2.push_str("!");
3009 assert_eq!(cow.as_str(), "hello world!");
3010 }
3011
3012 #[test]
3013 fn test_cow_assign_slice_ref() {
3014 let original = "hello world";
3015
3016 let mut cow = CowStr::from(original);
3018 cow.assign_slice_ref("goodbye");
3019 assert!(cow.is_borrowed());
3020 assert_eq!(cow.as_str(), "goodbye");
3021
3022 let mut cow = CowStr::from(StrMut::new("hello world"));
3024 cow.assign_slice_ref("bye");
3025 assert!(cow.is_owned());
3026 assert_eq!(cow.as_str(), "bye");
3027 }
3028
3029 #[test]
3030 fn test_cow_assign_range() {
3031 let mut cow = CowStr::from("hello world");
3033 cow.assign_range(0..5);
3034 assert!(cow.is_borrowed());
3035 assert_eq!(cow.as_str(), "hello");
3036
3037 let mut cow = CowStr::from(StrMut::new("hello world"));
3039 cow.assign_range(6..11);
3040 assert!(cow.is_owned());
3041 assert_eq!(cow.as_str(), "world");
3042
3043 let mut cow = CowStr::from(StrMut::new("hello world"));
3045 cow.assign_range(3..8);
3046 assert_eq!(cow.as_str(), "lo wo");
3047 }
3048
3049 #[test]
3050 fn test_cow_into_range() {
3051 let cow = CowStr::from("hello world");
3053 let new_cow = cow.into_range(0..5);
3054 assert!(new_cow.is_borrowed());
3055 assert_eq!(new_cow.as_str(), "hello");
3056
3057 let cow = CowStr::from(StrMut::new("hello world"));
3059 let new_cow = cow.into_range(6..11);
3060 assert!(new_cow.is_owned());
3061 assert_eq!(new_cow.as_str(), "world");
3062 }
3063
3064 #[test]
3065 fn test_cow_into_slice_ref() {
3066 let original = "hello world";
3067
3068 let cow = CowStr::from(original);
3070 let subset = &original[6..11];
3071 let new_cow = cow.into_slice_ref(subset);
3072 assert!(new_cow.is_borrowed());
3073 assert_eq!(new_cow.as_str(), "world");
3074
3075 let cow = CowStr::from(StrMut::new("hello world"));
3077 let new_cow = cow.into_slice_ref("new");
3078 assert!(new_cow.is_owned());
3079 assert_eq!(new_cow.as_str(), "new");
3080 }
3081
3082 #[test]
3083 fn test_cow_mutating_operations() {
3084 let mut cow = CowStr::from("hello");
3086 cow.push_str(" world");
3087 assert!(cow.is_owned());
3088 assert_eq!(cow.as_str(), "hello world");
3089
3090 let mut cow = CowStr::from("hello");
3092 cow.push('!');
3093 assert_eq!(cow.as_str(), "hello!");
3094
3095 let mut cow = CowStr::from("hello world");
3097 cow.truncate(5);
3098 assert!(cow.is_borrowed());
3099 assert_eq!(cow.as_str(), "hello");
3100
3101 let mut cow = CowStr::from(StrMut::new("hello world"));
3103 cow.truncate(5);
3104 assert!(cow.is_owned());
3105 assert_eq!(cow.as_str(), "hello");
3106 }
3107
3108 #[test]
3109 fn test_cow_trim_operations() {
3110 let mut cow = CowStr::from(" hello world ");
3112 cow.trim();
3113 assert!(cow.is_borrowed());
3114 assert_eq!(cow.as_str(), "hello world");
3115
3116 let mut cow = CowStr::from(StrMut::new(" hello world "));
3118 cow.trim();
3119 assert!(cow.is_owned());
3120 assert_eq!(cow.as_str(), "hello world");
3121
3122 let mut cow = CowStr::from(" hello");
3124 cow.trim_start();
3125 assert!(cow.is_borrowed());
3126 assert_eq!(cow.as_str(), "hello");
3127
3128 let mut cow = CowStr::from(StrMut::new(" hello"));
3130 cow.trim_start();
3131 assert!(cow.is_owned());
3132 assert_eq!(cow.as_str(), "hello");
3133
3134 let mut cow = CowStr::from("hello ");
3136 cow.trim_end();
3137 assert!(cow.is_borrowed());
3138 assert_eq!(cow.as_str(), "hello");
3139
3140 let mut cow = CowStr::from(StrMut::new("hello "));
3142 cow.trim_end();
3143 assert!(cow.is_owned());
3144 assert_eq!(cow.as_str(), "hello");
3145 }
3146
3147 #[test]
3148 fn test_cow_ascii_case_conversion() {
3149 let mut cow = CowStr::from("hello");
3151 cow.make_ascii_lowercase();
3152 assert!(cow.is_borrowed()); let mut cow = CowStr::from("HELLO");
3155 cow.make_ascii_lowercase();
3156 assert!(cow.is_owned());
3157 assert_eq!(cow.as_str(), "hello");
3158
3159 let mut cow = CowStr::from("HELLO");
3161 cow.make_ascii_uppercase();
3162 assert!(cow.is_borrowed()); let mut cow = CowStr::from("hello");
3165 cow.make_ascii_uppercase();
3166 assert!(cow.is_owned());
3167 assert_eq!(cow.as_str(), "HELLO");
3168 }
3169
3170 #[test]
3171 fn test_cow_equality() {
3172 let cow1 = CowStr::from("hello");
3173 let cow2 = CowStr::from(StrMut::new("hello"));
3174
3175 assert_eq!(cow1, cow2);
3176 assert_eq!(cow1, "hello");
3177 assert_eq!("hello", cow1);
3178 assert_eq!(cow1, String::from("hello"));
3179 assert_eq!(cow1, Str::new("hello"));
3180 assert_eq!(cow1, StrMut::new("hello"));
3181 }
3182
3183 #[test]
3184 fn test_cow_ordering() {
3185 let cow1 = CowStr::from("apple");
3186 let cow2 = CowStr::from("banana");
3187 let cow3 = CowStr::from(StrMut::new("apple"));
3188
3189 assert!(cow1 < cow2);
3190 assert!(cow2 > cow1);
3191 assert_eq!(cow1.cmp(&cow3), std::cmp::Ordering::Equal);
3192 }
3193
3194 #[test]
3195 fn test_cow_hash() {
3196 use std::{
3197 collections::hash_map::DefaultHasher,
3198 hash::{Hash, Hasher},
3199 };
3200
3201 let cow1 = CowStr::from("hello");
3202 let cow2 = CowStr::from(StrMut::new("hello"));
3203
3204 let mut hasher1 = DefaultHasher::new();
3205 cow1.hash(&mut hasher1);
3206 let hash1 = hasher1.finish();
3207
3208 let mut hasher2 = DefaultHasher::new();
3209 cow2.hash(&mut hasher2);
3210 let hash2 = hasher2.finish();
3211
3212 assert_eq!(hash1, hash2);
3213 }
3214
3215 #[test]
3216 fn test_cow_into_owned() {
3217 let cow = CowStr::from("hello");
3219 let owned = cow.into_str_mut();
3220 assert_eq!(owned.as_str(), "hello");
3221
3222 let cow = CowStr::from(StrMut::new("world"));
3224 let owned = cow.into_str_mut();
3225 assert_eq!(owned.as_str(), "world");
3226 }
3227
3228 #[test]
3229 fn test_cow_into_str() {
3230 let cow = CowStr::from("hello");
3231 let string = cow.into_str();
3232 assert_eq!(string.as_str(), "hello");
3233 }
3234
3235 #[test]
3236 fn test_cow_cow_conversion() {
3237 let std_cow = Cow::Borrowed("hello");
3239 let cow: CowStr = std_cow.into();
3240 assert!(cow.is_borrowed());
3241
3242 let std_cow = Cow::<str>::Owned(String::from("world"));
3243 let cow: CowStr = std_cow.into();
3244 assert!(cow.is_owned());
3245
3246 let cow = CowStr::from("hello");
3248 let std_cow: Cow<str> = cow.into();
3249 assert!(matches!(std_cow, Cow::Borrowed(_)));
3250 }
3251
3252 #[test]
3253 fn test_cow_from_conversions() {
3254 let string = Str::new("hello");
3256 let cow: CowStr = string.into();
3257 assert!(cow.is_owned());
3258 assert_eq!(cow.as_str(), "hello");
3259
3260 let string = String::from("world");
3262 let cow: CowStr = string.into();
3263 assert!(cow.is_owned());
3264 assert_eq!(cow.as_str(), "world");
3265
3266 let cow = CowStr::from("test");
3268 let string: Str = cow.into();
3269 assert_eq!(string.as_str(), "test");
3270
3271 let cow = CowStr::from("test");
3273 let string_mut: StrMut = cow.into();
3274 assert_eq!(string_mut.as_str(), "test");
3275 }
3276
3277 #[test]
3278 fn test_cow_default() {
3279 let cow: CowStr = Default::default();
3280 assert!(cow.is_owned());
3281 assert_eq!(cow.as_str(), "");
3282 assert!(cow.is_empty());
3283 }
3284
3285 #[test]
3286 fn test_cow_deref_and_borrow() {
3287 let cow = CowStr::from("hello world");
3288
3289 assert_eq!(&*cow, "hello world");
3291
3292 let s: &str = cow.as_ref();
3294 assert_eq!(s, "hello world");
3295
3296 let bytes: &[u8] = cow.as_ref();
3298 assert_eq!(bytes, b"hello world");
3299 }
3300
3301 #[test]
3302 fn test_cow_serde() {
3303 let cow = CowStr::from("hello world");
3305 let json = json::to_string(&cow).unwrap();
3306 assert_eq!(json, r#""hello world""#);
3307
3308 let deserialized: CowStr = json::from_str(&json).unwrap();
3310 assert!(!deserialized.is_owned());
3311 assert_eq!(deserialized.as_str(), "hello world");
3312
3313 let cow = CowStr::from(StrMut::new("test"));
3315 let json = json::to_string(&cow).unwrap();
3316 assert_eq!(json, r#""test""#);
3317 }
3318
3319 #[test]
3324 fn test_empty_strings() {
3325 let s = Str::new("");
3327 assert!(s.is_empty());
3328 assert_eq!(s.len(), 0);
3329 assert!(!s.is_spilled());
3330 assert_eq!(s.as_str(), "");
3331
3332 let mut m = StrMut::new("");
3334 assert!(m.is_empty());
3335 assert_eq!(m.len(), 0);
3336 assert!(!m.is_spilled());
3337 m.push_str("");
3338 assert!(m.is_empty());
3339
3340 assert_eq!(s.trim(), "");
3342 assert_eq!(s.trim_start(), "");
3343 assert_eq!(s.trim_end(), "");
3344 assert_eq!(s.strip_prefix("x"), None);
3345 assert_eq!(s.strip_suffix("x"), None);
3346
3347 let (l, r) = s.split_at(0);
3348 assert!(l.is_empty());
3349 assert!(r.is_empty());
3350
3351 let parts: Vec<_> = s.split("x").collect();
3353 assert_eq!(parts.len(), 1);
3354 assert_eq!(parts[0], "");
3355 }
3356
3357 #[test]
3358 fn test_exact_inline_capacity() {
3359 let text = "12345678901234567890123"; assert_eq!(text.len(), 23);
3362
3363 let s = Str::new(text);
3364 assert!(!s.is_spilled());
3365 assert_eq!(s.len(), 23);
3366 assert_eq!(s.as_str(), text);
3367
3368 let m = StrMut::new(text);
3369 assert!(!m.is_spilled());
3370 assert_eq!(m.len(), 23);
3371 }
3372
3373 #[test]
3374 fn test_boundary_24_bytes() {
3375 let text = "123456789012345678901234"; assert_eq!(text.len(), 24);
3378
3379 let s = Str::new(text);
3380 assert!(s.is_spilled());
3381 assert_eq!(s.len(), 24);
3382 assert_eq!(s.as_str(), text);
3383
3384 let m = StrMut::new(text);
3385 assert!(m.is_spilled());
3386 assert_eq!(m.len(), 24);
3387 }
3388
3389 #[test]
3390 fn test_slice_boundaries() {
3391 let text = "0123456789";
3392 let s = Str::new(text);
3393
3394 assert_eq!(s.slice(..), text);
3396 assert_eq!(s.slice(0..10), text);
3397
3398 assert_eq!(s.slice(0..0), "");
3400 assert_eq!(s.slice(5..5), "");
3401 assert_eq!(s.slice(10..10), "");
3402
3403 assert_eq!(s.slice(0..1), "0");
3405 assert_eq!(s.slice(9..10), "9");
3406
3407 assert_eq!(s.slice(..5), "01234");
3409 assert_eq!(s.slice(5..), "56789");
3410 }
3411
3412 #[test]
3413 #[should_panic(expected = "self.is_char_boundary(new_len)")]
3414 fn test_truncate_non_char_boundary_inline() {
3415 let mut s = Str::new("hello world δΈη");
3416 s.truncate(13); }
3418
3419 #[test]
3420 #[should_panic(expected = "Index is not on a char boundary")]
3421 fn test_truncate_non_char_boundary_heap() {
3422 let mut s = Str::new("hello world hello world δΈη");
3423 s.truncate(26); }
3425
3426 #[test]
3431 fn test_from_utf8_valid() {
3432 let valid = b"hello world";
3433 let s = Str::from_utf8(valid).unwrap();
3434 assert_eq!(s.as_str(), "hello world");
3435
3436 let valid_utf8 = "hello δΈη π".as_bytes();
3437 let s = Str::from_utf8(valid_utf8).unwrap();
3438 assert_eq!(s.as_str(), "hello δΈη π");
3439 }
3440
3441 #[test]
3442 fn test_from_utf8_invalid() {
3443 let invalid = &[0xff, 0xfe, 0xfd];
3444 assert!(Str::from_utf8(invalid).is_err());
3445
3446 let invalid = &[0xc0, 0x80]; assert!(Str::from_utf8(invalid).is_err());
3448 }
3449
3450 #[test]
3451 fn test_from_utf8_lossy() {
3452 let valid = Str::from_utf8_lossy("hello δΈη".as_bytes());
3453 assert_eq!(valid.as_str(), "hello δΈη");
3454
3455 let invalid = Str::from_utf8_lossy(b"hello \xff world");
3456 assert_eq!(invalid.as_str(), "hello οΏ½ world");
3457 }
3458
3459 #[test]
3460 fn test_from_utf8_owned_valid() {
3461 let valid = bytes::Bytes::from("hello world");
3462 let s = Str::from_utf8_owned(valid).unwrap();
3463 assert_eq!(s.as_str(), "hello world");
3464 assert!(s.is_spilled());
3465 }
3466
3467 #[test]
3468 fn test_from_utf8_owned_invalid() {
3469 let invalid = bytes::Bytes::from_static(&[0xff, 0xfe, 0xfd]);
3470 assert!(Str::from_utf8_owned(invalid).is_err());
3471 }
3472
3473 #[test]
3474 fn test_from_utf8_mut_valid() {
3475 let valid = b"hello";
3476 let m = StrMut::from_utf8(valid).unwrap();
3477 assert_eq!(m.as_str(), "hello");
3478 }
3479
3480 #[test]
3481 fn test_from_utf8_mut_invalid() {
3482 let invalid = &[0xff, 0xfe];
3483 assert!(StrMut::from_utf8(invalid).is_err());
3484 }
3485
3486 #[test]
3487 fn test_multibyte_char_boundaries() {
3488 let text = "πδΈη";
3490 let s = Str::new(text);
3491 assert_eq!(s.len(), 10); let (l, r) = s.split_at(4);
3495 assert_eq!(l.as_str(), "π");
3496 assert_eq!(r.as_str(), "δΈη");
3497
3498 let mut s2 = Str::new(text);
3500 s2.truncate(4);
3501 assert_eq!(s2.as_str(), "π");
3502 }
3503
3504 #[test]
3505 #[should_panic(expected = "byte index 1 is not a char boundary")]
3506 fn test_split_at_invalid_boundary() {
3507 let s = Str::new("δΈη");
3508 let _ = s.split_at(1); }
3510
3511 #[test]
3516 #[should_panic(expected = "len <= INLINE_CAP")]
3517 fn test_new_inline_panic() {
3518 let too_long = "123456789012345678901234"; let _ = Str::new_inline(too_long);
3520 }
3521
3522 #[test]
3523 #[should_panic(expected = "len <= INLINE_CAP")]
3524 fn test_new_inline_mut_panic() {
3525 let too_long = "123456789012345678901234";
3526 let _ = StrMut::new_inline(too_long);
3527 }
3528
3529 #[test]
3530 #[should_panic(expected = "index is not on a valid UTF-8 character boundary")]
3531 fn test_insert_non_char_boundary_inline() {
3532 let mut m = StrMut::new("δΈη");
3533 m.insert(1, "x"); }
3535
3536 #[test]
3537 #[should_panic(expected = "index is not on a valid UTF-8 character boundary")]
3538 fn test_insert_non_char_boundary_heap() {
3539 let mut m = StrMut::new("hello world hello world δΈη");
3540 m.insert(25, "x"); }
3542
3543 #[test]
3544 fn test_try_into_mut_success_inline() {
3545 let s = Str::new("hello");
3546 let m = s.try_into_mut().unwrap();
3547 assert_eq!(m.as_str(), "hello");
3548 assert!(!m.is_spilled());
3549 }
3550
3551 #[test]
3552 fn test_try_into_mut_success_heap_unique() {
3553 let s = Str::new("hello world hello world!!");
3554 let m = s.try_into_mut().unwrap();
3555 assert_eq!(m.as_str(), "hello world hello world!!");
3556 assert!(m.is_spilled());
3557 }
3558
3559 #[test]
3560 fn test_try_into_mut_failure_shared() {
3561 let s = Str::new("hello world hello world!!");
3562 let s2 = s.clone();
3563
3564 let result = s.try_into_mut();
3566 assert!(result.is_err());
3567
3568 let original = result.unwrap_err();
3570 assert_eq!(original.as_str(), "hello world hello world!!");
3571 assert_eq!(s2.as_str(), "hello world hello world!!");
3572 }
3573
3574 #[test]
3579 fn test_push_str_inline_to_heap() {
3580 let mut m = StrMut::new("12345678901234567890"); assert!(!m.is_spilled());
3582
3583 m.push_str("1234"); assert!(m.is_spilled());
3585 assert_eq!(m.as_str(), "123456789012345678901234");
3586 }
3587
3588 #[test]
3589 fn test_push_char_inline_to_heap() {
3590 let mut m = StrMut::new("1234567890123456789012"); assert!(!m.is_spilled());
3592
3593 m.push('x');
3594 assert!(!m.is_spilled()); m.push('y');
3597 assert!(m.is_spilled()); assert_eq!(m.as_str(), "1234567890123456789012xy");
3599 }
3600
3601 #[test]
3602 fn test_push_multibyte_char_promotion() {
3603 let mut m = StrMut::new("12345678901234567890"); assert!(!m.is_spilled());
3605
3606 m.push('π'); assert!(m.is_spilled()); assert_eq!(m.as_str(), "12345678901234567890π");
3609 }
3610
3611 #[test]
3612 fn test_reserve_triggers_promotion() {
3613 let mut m = StrMut::new("hello"); assert!(!m.is_spilled());
3615
3616 m.reserve(20); assert!(m.is_spilled());
3618 assert_eq!(m.as_str(), "hello");
3619
3620 m.push_str("12345678901234567890"); assert_eq!(m.as_str(), "hello12345678901234567890");
3623 }
3624
3625 #[test]
3626 fn test_sequential_operations_promotion() {
3627 let mut m = StrMut::new("abc");
3628 assert!(!m.is_spilled());
3629
3630 for _ in 0..5 {
3631 m.push_str("1234"); }
3633 assert!(!m.is_spilled());
3635
3636 m.push('x');
3637 assert!(m.is_spilled()); }
3639
3640 #[test]
3645 fn test_strip_prefix_none() {
3646 let s = Str::new("hello world");
3647 assert_eq!(s.strip_prefix("goodbye"), None);
3648 assert_eq!(s.strip_prefix("hello world!"), None);
3649 }
3650
3651 #[test]
3652 fn test_strip_suffix_none() {
3653 let s = Str::new("hello world");
3654 assert_eq!(s.strip_suffix("goodbye"), None);
3655 assert_eq!(s.strip_suffix("!hello world"), None);
3656 }
3657
3658 #[test]
3659 fn test_slice_ref_inline() {
3660 let text = "hello world";
3661 let s = Str::new(text);
3662 assert!(!s.is_spilled());
3663
3664 let subset = &text[6..11]; let sliced = s.slice_ref(subset);
3666 assert_eq!(sliced.as_str(), "world");
3667 assert!(!sliced.is_spilled()); }
3669
3670 #[test]
3671 fn test_trim_end_zero_copy_heap() {
3672 let text = "hello world hello world hello ";
3673 let s = Str::new(text);
3674 assert!(s.is_spilled());
3675
3676 let trimmed = s.trim_end();
3677 assert_eq!(trimmed.as_str(), "hello world hello world hello");
3678 assert!(trimmed.is_spilled());
3679 }
3680
3681 #[test]
3682 fn test_split_iterator_complete() {
3683 let s = Str::new("a,b,c,d,e");
3684 let parts: Vec<_> = s.split(",").collect();
3685 assert_eq!(parts.len(), 5);
3686 assert_eq!(parts[0], "a");
3687 assert_eq!(parts[1], "b");
3688 assert_eq!(parts[4], "e");
3689
3690 let s2 = Str::new("a,,b");
3692 let parts2: Vec<_> = s2.split(",").collect();
3693 assert_eq!(parts2.len(), 3);
3694 assert_eq!(parts2[1], ""); }
3696
3697 #[test]
3698 fn test_split_no_separator() {
3699 let s = Str::new("hello");
3700 let parts: Vec<_> = s.split(",").collect();
3701 assert_eq!(parts.len(), 1);
3702 assert_eq!(parts[0], "hello");
3703 }
3704
3705 #[test]
3710 fn test_is_unique_inline() {
3711 let s = Str::new("hello");
3712 assert!(s.is_unique()); }
3714
3715 #[test]
3716 fn test_is_unique_heap_unshared() {
3717 let s = Str::new("hello world hello world!!");
3718 assert!(s.is_unique()); }
3720
3721 #[test]
3722 fn test_is_unique_heap_shared() {
3723 let s1 = Str::new("hello world hello world!!");
3724 let s2 = s1.clone();
3725
3726 assert!(!s1.is_unique()); assert!(!s2.is_unique());
3728 }
3729
3730 #[test]
3731 fn test_into_ascii_uppercase_leaves_shared_clone_untouched() {
3732 let s1 = Str::new("hello world hello world!!");
3733 let s2 = s1.clone();
3734
3735 let upper = s1.into_ascii_uppercase();
3737
3738 assert_eq!(upper.as_str(), "HELLO WORLD HELLO WORLD!!");
3739 assert_eq!(s2.as_str(), "hello world hello world!!"); }
3741
3742 #[test]
3743 fn test_promote_inline_to_heap() {
3744 let mut s = Str::new("hello");
3745 assert!(!s.is_spilled());
3746
3747 let heap_str = s.promote();
3748 assert_eq!(&**heap_str, "hello");
3749 assert!(s.is_spilled());
3750 }
3751
3752 #[test]
3757 fn test_from_arc_str() {
3758 let arc: std::sync::Arc<str> = "hello world hello world".into();
3759 let s = Str::from(arc);
3760 assert!(s.is_spilled());
3761 assert_eq!(s.as_str(), "hello world hello world");
3762 }
3763
3764 #[test]
3765 fn test_from_box_str() {
3766 let boxed: Box<str> = "hello world".into();
3767 let s = Str::from(boxed);
3768 assert_eq!(s.as_str(), "hello world");
3769 }
3770
3771 #[test]
3772 fn test_from_cow_borrowed() {
3773 let cow = std::borrow::Cow::Borrowed("hello");
3774 let s = Str::from(cow);
3775 assert_eq!(s.as_str(), "hello");
3776 }
3777
3778 #[test]
3779 fn test_from_cow_owned() {
3780 let cow = std::borrow::Cow::<str>::Owned(String::from("hello world hello world"));
3781 let s = Str::from(cow);
3782 assert_eq!(s.as_str(), "hello world hello world");
3783 }
3784
3785 #[test]
3786 fn test_into_string() {
3787 let s = Str::new("hello world");
3788 let string: String = s.into();
3789 assert_eq!(string, "hello world");
3790 }
3791
3792 #[test]
3793 fn test_into_bytes() {
3794 let s = Str::new("hello world hello world");
3795 let bytes: bytes::Bytes = s.into();
3796 assert_eq!(&bytes[..], b"hello world hello world");
3797 }
3798
3799 #[test]
3800 fn test_into_bytes_inline() {
3801 let s = Str::new("hello");
3802 let bytes: bytes::Bytes = s.into();
3803 assert_eq!(&bytes[..], b"hello");
3804 }
3805
3806 #[test]
3807 fn test_from_iterator_char() {
3808 let chars = vec!['h', 'e', 'l', 'l', 'o'];
3809 let s: Str = chars.into_iter().collect();
3810 assert_eq!(s.as_str(), "hello");
3811 }
3812
3813 #[test]
3814 fn test_from_iterator_str_ref() {
3815 let strs = vec!["hello", " ", "world"];
3816 let s: Str = strs.into_iter().collect();
3817 assert_eq!(s.as_str(), "hello world");
3818 }
3819
3820 #[test]
3821 fn test_from_iterator_string() {
3822 let strings = vec![String::from("hello"), String::from(" "), String::from("world")];
3823 let s: Str = strings.into_iter().collect();
3824 assert_eq!(s.as_str(), "hello world");
3825 }
3826
3827 #[test]
3828 fn test_from_iterator_triggers_heap() {
3829 let s: Str = "123456789012345678901234".chars().collect();
3830 assert!(s.is_spilled());
3831 assert_eq!(s.as_str(), "123456789012345678901234");
3832 }
3833
3834 #[test]
3839 fn test_to_ascii_lowercase_str() {
3840 let s = "HELLO WORLD";
3841 let lower = s.to_ascii_lowercase_str();
3842 assert_eq!(lower.as_str(), "hello world");
3843 assert!(!lower.is_spilled());
3844
3845 let long = "HELLO WORLD HELLO WORLD!!";
3846 let lower_long = long.to_ascii_lowercase_str();
3847 assert_eq!(lower_long.as_str(), "hello world hello world!!");
3848 assert!(lower_long.is_spilled());
3849 }
3850
3851 #[test]
3852 fn test_to_ascii_uppercase_str() {
3853 let s = "hello world";
3854 let upper = s.to_ascii_uppercase_str();
3855 assert_eq!(upper.as_str(), "HELLO WORLD");
3856
3857 let already_upper = "HELLO";
3858 let upper2 = already_upper.to_ascii_uppercase_str();
3859 assert_eq!(upper2.as_str(), "HELLO");
3860 }
3861
3862 #[test]
3863 fn test_into_ascii_lowercase() {
3864 let s = Str::new("HELLO");
3865 let lower = s.into_ascii_lowercase();
3866 assert_eq!(lower.as_str(), "hello");
3867 }
3868
3869 #[test]
3870 fn test_into_ascii_uppercase() {
3871 let s = Str::new("hello");
3872 let upper = s.into_ascii_uppercase();
3873 assert_eq!(upper.as_str(), "HELLO");
3874 }
3875
3876 #[test]
3881 fn test_fmts_basic() {
3882 let s = fmts!("hello {}", "world");
3883 assert_eq!(s.as_str(), "hello world");
3884 }
3885
3886 #[test]
3887 fn test_fmts_numbers() {
3888 let s = fmts!("count: {}, pi: {:.2}", 42, std::f64::consts::PI);
3889 assert_eq!(s.as_str(), "count: 42, pi: 3.14");
3890 }
3891
3892 #[test]
3893 fn test_fmts_no_args() {
3894 let s = fmts!("static text");
3895 assert_eq!(s.as_str(), "static text");
3896 }
3897
3898 #[test]
3899 fn test_fmts_mut_basic() {
3900 let mut s = fmts_mut!("hello {}", "world");
3901 assert_eq!(s.as_str(), "hello world");
3902 s.push('!');
3903 assert_eq!(s.as_str(), "hello world!");
3904 }
3905
3906 #[test]
3907 fn test_fmts_heap_allocation() {
3908 let s = fmts!("{}", "123456789012345678901234");
3909 assert!(s.is_spilled());
3910 assert_eq!(s.as_str(), "123456789012345678901234");
3911 }
3912
3913 #[test]
3918 fn test_new_static() {
3919 const STATIC: &str = "hello world hello world";
3920 let s = Str::new_static(STATIC);
3921
3922 assert!(s.is_spilled());
3924 assert_eq!(s.as_str(), STATIC);
3925
3926 const SHORT: &str = "hi";
3928 let s2 = Str::new_static(SHORT);
3929 assert!(s2.is_spilled()); }
3931
3932 #[test]
3937 fn test_str_serde_roundtrip() {
3938 let s = Str::new("hello world");
3939 let json = json::to_string(&s).unwrap();
3940 assert_eq!(json, r#""hello world""#);
3941
3942 let deserialized: Str = json::from_str(&json).unwrap();
3943 assert_eq!(deserialized.as_str(), "hello world");
3944 }
3945
3946 #[test]
3947 fn test_str_serde_empty() {
3948 let s = Str::new("");
3949 let json = json::to_string(&s).unwrap();
3950 assert_eq!(json, r#""""#);
3951
3952 let deserialized: Str = json::from_str(&json).unwrap();
3953 assert!(deserialized.is_empty());
3954 }
3955
3956 #[test]
3957 fn test_str_serde_multibyte() {
3958 let s = Str::new("δΈη π");
3959 let json = json::to_string(&s).unwrap();
3960
3961 let deserialized: Str = json::from_str(&json).unwrap();
3962 assert_eq!(deserialized.as_str(), "δΈη π");
3963 }
3964
3965 #[test]
3970 fn test_clone_inline() {
3971 let s1 = Str::new("hello");
3972 let s2 = s1.clone();
3973 assert_eq!(s1, s2);
3974 assert!(!s1.is_spilled());
3975 assert!(!s2.is_spilled());
3976 }
3977
3978 #[test]
3979 fn test_clone_heap() {
3980 let s1 = Str::new("hello world hello world!!");
3981 let s2 = s1.clone();
3982 assert_eq!(s1, s2);
3983
3984 assert!(!s1.is_unique());
3986 assert!(!s2.is_unique());
3987 }
3988
3989 #[test]
3990 fn test_default_str() {
3991 let s = Str::default();
3992 assert!(s.is_empty());
3993 assert!(!s.is_spilled());
3994 }
3995
3996 #[test]
3997 fn test_default_strmut() {
3998 let m = StrMut::default();
3999 assert!(m.is_empty());
4000 assert!(!m.is_spilled());
4001 }
4002
4003 #[test]
4004 fn test_with_capacity_inline() {
4005 let m = StrMut::with_capacity(10);
4006 assert!(!m.is_spilled());
4007 assert!(m.is_empty());
4008 }
4009
4010 #[test]
4011 fn test_with_capacity_heap() {
4012 let m = StrMut::with_capacity(100);
4013 assert!(m.is_spilled());
4014 assert!(m.is_empty());
4015 }
4016
4017 #[test]
4018 fn test_freeze_inline() {
4019 let m = StrMut::new("hello");
4020 let s = m.freeze();
4021 assert_eq!(s.as_str(), "hello");
4022 assert!(!s.is_spilled());
4023 }
4024
4025 #[test]
4026 fn test_freeze_heap() {
4027 let m = StrMut::new("hello world hello world!!");
4028 let s = m.freeze();
4029 assert_eq!(s.as_str(), "hello world hello world!!");
4030 assert!(s.is_spilled());
4031 }
4032
4033 #[test]
4034 fn test_extend_empty_iterator() {
4035 let mut m = StrMut::new("hello");
4036 let empty: Vec<&str> = vec![];
4037 m.extend(empty);
4038 assert_eq!(m.as_str(), "hello");
4039 }
4040
4041 #[test]
4042 fn test_equality_different_repr() {
4043 let inline = Str::new("hello");
4045 let heap = Str::new("hello world hello world!!").slice(0..5);
4046
4047 assert_eq!(inline, heap);
4048 assert!(!inline.is_spilled());
4049 assert!(heap.is_spilled());
4050 }
4051
4052 #[test]
4053 fn test_ordering() {
4054 let a = Str::new("apple");
4055 let b = Str::new("banana");
4056 let c = Str::new("cherry");
4057
4058 assert!(a < b);
4059 assert!(b < c);
4060 assert!(a < c);
4061 assert!((b >= a));
4062 }
4063
4064 #[test]
4065 fn test_hash_consistency() {
4066 use std::{
4067 collections::hash_map::DefaultHasher,
4068 hash::{Hash, Hasher},
4069 };
4070
4071 let s1 = Str::new("hello world");
4072 let s2 = Str::new("hello world hello world").slice(0..11);
4073
4074 let mut h1 = DefaultHasher::new();
4075 s1.hash(&mut h1);
4076
4077 let mut h2 = DefaultHasher::new();
4078 s2.hash(&mut h2);
4079
4080 assert_eq!(h1.finish(), h2.finish());
4081 }
4082
4083 #[test]
4084 fn test_as_bytes() {
4085 let s = Str::new("hello π");
4086 let bytes = s.as_bytes();
4087 assert_eq!(bytes, "hello π".as_bytes());
4088 }
4089
4090 #[test]
4091 fn test_insert_at_end() {
4092 let mut m = StrMut::new("hello");
4093 m.insert(5, " world");
4094 assert_eq!(m.as_str(), "hello world");
4095 }
4096
4097 #[test]
4098 fn test_insert_at_start() {
4099 let mut m = StrMut::new("world");
4100 m.insert(0, "hello ");
4101 assert_eq!(m.as_str(), "hello world");
4102 }
4103
4104 #[test]
4105 fn test_truncate_noop() {
4106 let mut s = Str::new("hello");
4107 s.truncate(100); assert_eq!(s.as_str(), "hello");
4109
4110 s.truncate(5); assert_eq!(s.as_str(), "hello");
4112 }
4113
4114 #[test]
4115 fn test_truncate_mut_noop() {
4116 let mut m = StrMut::new("hello");
4117 m.truncate(100);
4118 assert_eq!(m.as_str(), "hello");
4119 }
4120
4121 #[test]
4122 fn test_deref_coercion() {
4123 let s = Str::new("hello");
4124 let len = s.len(); assert_eq!(len, 5);
4126
4127 fn takes_str(s: &str) -> usize {
4129 s.len()
4130 }
4131 assert_eq!(takes_str(&s), 5);
4132 }
4133
4134 #[test]
4135 fn test_borrow_trait() {
4136 use std::borrow::Borrow;
4137
4138 let s = Str::new("hello");
4139 let borrowed: &str = s.borrow();
4140 assert_eq!(borrowed, "hello");
4141 }
4142
4143 #[test]
4144 fn test_as_ref_os_str() {
4145 let s = Str::new("hello");
4146 let os_str: &std::ffi::OsStr = s.as_ref();
4147 assert_eq!(os_str, "hello");
4148 }
4149
4150 #[test]
4151 fn test_as_ref_path() {
4152 let s = Str::new("/tmp/file.txt");
4153 let path: &std::path::Path = s.as_ref();
4154 assert_eq!(path.to_str().unwrap(), "/tmp/file.txt");
4155 }
4156
4157 #[test]
4158 fn test_partial_eq_str() {
4159 let s = Str::new("hello");
4160 assert_eq!(s, "hello");
4161 assert_eq!("hello", s);
4162 assert_ne!(s, "world");
4163 }
4164
4165 #[test]
4166 fn test_partial_eq_string() {
4167 let s = Str::new("hello");
4168 let string = String::from("hello");
4169 assert_eq!(s, string);
4170 assert_eq!(string, s);
4171 }
4172
4173 #[test]
4174 fn test_strmut_deref_mut() {
4175 let mut m = StrMut::new("hello");
4176 let str_mut: &mut str = &mut m;
4177 str_mut.make_ascii_uppercase();
4178 assert_eq!(m.as_str(), "HELLO");
4179 }
4180
4181 #[test]
4182 fn test_from_str_parse() {
4183 let s: Str = "hello world".parse().unwrap();
4184 assert_eq!(s.as_str(), "hello world");
4185 }
4186
4187 #[test]
4188 fn test_into_str_trait() {
4189 use super::IntoStr;
4190
4191 let s: Str = "hello".into_str();
4192 assert_eq!(s.as_str(), "hello");
4193
4194 let num: i32 = 42;
4195 let s2 = (&num).to_str();
4196 assert_eq!(s2.as_str(), "42");
4197 }
4198
4199 #[test]
4200 fn test_write_trait() {
4201 use std::fmt::Write;
4202
4203 let mut m = StrMut::new("hello");
4204 write!(&mut m, " {}", 42).unwrap();
4205 assert_eq!(m.as_str(), "hello 42");
4206 }
4207
4208 #[test]
4209 fn test_display_format() {
4210 let s = Str::new("hello");
4211 let formatted = format!("{s}");
4212 assert_eq!(formatted, "hello");
4213 }
4214
4215 #[test]
4216 fn test_debug_format() {
4217 let s = Str::new("hello");
4218 let formatted = format!("{s:?}");
4219 assert_eq!(formatted, "\"hello\"");
4220 }
4221
4222 #[test]
4223 fn test_slice_heap_zero_copy() {
4224 let s = Str::new("hello world hello world!!");
4225 let sliced = s.slice(6..11);
4226 assert_eq!(sliced.as_str(), "world");
4227 assert!(sliced.is_spilled());
4228 }
4229
4230 #[test]
4231 fn test_slice_inline_creates_inline() {
4232 let s = Str::new("hello world");
4233 let sliced = s.slice(0..5);
4234 assert_eq!(sliced.as_str(), "hello");
4235 assert!(!sliced.is_spilled());
4236 }
4237
4238 #[test]
4239 fn test_reserve_heap_noop() {
4240 let mut m = StrMut::new("hello world hello world!!");
4241 assert!(m.is_spilled());
4242
4243 let initial_len = m.len();
4244 m.reserve(10);
4245
4246 assert_eq!(m.len(), initial_len);
4247 assert_eq!(m.as_str(), "hello world hello world!!");
4248 }
4249
4250 #[test]
4251 fn test_push_empty_string() {
4252 let mut m = StrMut::new("hello");
4253 m.push_str("");
4254 assert_eq!(m.as_str(), "hello");
4255 }
4256
4257 #[test]
4258 fn test_split_empty_separator() {
4259 let s = Str::new("hello");
4260 let parts = s.split("").filter(|s| !s.is_empty()).count();
4261 assert_eq!(parts, 5);
4262 }
4263
4264 #[test]
4265 fn test_from_bytes_mut() {
4266 let bytes_mut = bytes::BytesMut::from("hello world hello world");
4267 let result = StrMut::from_utf8_owned(bytes_mut);
4268 assert!(result.is_ok());
4269 let m = result.unwrap();
4270 assert_eq!(m.as_str(), "hello world hello world");
4271 assert!(m.is_spilled());
4272 }
4273
4274 #[test]
4275 fn test_into_bytes_mut() {
4276 let m = StrMut::new("hello world hello world");
4277 let bytes_mut: bytes::BytesMut = m.into();
4278 assert_eq!(&bytes_mut[..], b"hello world hello world");
4279 }
4280
4281 #[test]
4282 fn test_str_to_str() {
4283 let s = Str::new("hello");
4284 let str_ref: bytes_utils::Str = s.into();
4285 assert_eq!(&*str_ref, "hello");
4286 }
4287
4288 #[test]
4289 fn test_strmut_to_strmut() {
4290 let m = StrMut::new("hello world hello world");
4291 let str_mut: bytes_utils::StrMut = m.into();
4292 assert_eq!(&*str_mut, "hello world hello world");
4293 }
4294}