1use core::{
2 borrow::{Borrow, BorrowMut},
3 cmp::Ordering,
4 convert::Infallible,
5 fmt,
6 hash::{Hash, Hasher},
7 iter::{FromIterator, FusedIterator},
8 ops, ptr, slice,
9 str::{self, Chars, Utf8Error},
10};
11
12use alloc::{borrow::Cow, boxed::Box, str::FromStr, string::String};
13
14#[cfg(feature = "ffi")]
15use std::ffi::{OsStr, OsString};
16
17#[cfg(feature = "serde")]
18use core::marker::PhantomData;
19#[cfg(feature = "serde")]
20use serde::{
21 de::{Deserialize, Deserializer, Error, Visitor},
22 ser::{Serialize, Serializer},
23};
24
25use smallvec::{Array, SmallVec};
26
27#[derive(Clone, Default)]
31pub struct SmallString<A: Array<Item = u8>> {
32 data: SmallVec<A>,
33}
34
35impl<A: Array<Item = u8>> SmallString<A> {
36 #[inline]
38 pub fn new() -> SmallString<A> {
39 SmallString {
40 data: SmallVec::new(),
41 }
42 }
43
44 #[inline]
49 pub fn with_capacity(n: usize) -> SmallString<A> {
50 SmallString {
51 data: SmallVec::with_capacity(n),
52 }
53 }
54
55 #[allow(clippy::should_implement_trait)]
57 #[inline]
58 pub fn from_str(s: &str) -> SmallString<A> {
59 SmallString {
60 data: SmallVec::from_slice(s.as_bytes()),
61 }
62 }
63
64 #[inline]
66 pub fn from_string(s: String) -> SmallString<A> {
67 SmallString {
68 data: SmallVec::from_vec(s.into_bytes()),
69 }
70 }
71
72 #[inline]
76 pub fn from_buf(buf: A) -> Result<SmallString<A>, FromUtf8Error<A>> {
77 let data = SmallVec::from_buf(buf);
78
79 match str::from_utf8(&data) {
80 Ok(_) => Ok(SmallString { data }),
81 Err(error) => {
82 let buf = data.into_inner().ok().unwrap();
83
84 Err(FromUtf8Error { buf, error })
85 }
86 }
87 }
88
89 #[inline]
99 pub unsafe fn from_buf_unchecked(buf: A) -> SmallString<A> {
100 SmallString {
101 data: SmallVec::from_buf(buf),
102 }
103 }
104
105 #[inline]
107 pub fn inline_size(&self) -> usize {
108 A::size()
109 }
110
111 #[inline]
113 pub fn len(&self) -> usize {
114 self.data.len()
115 }
116
117 #[inline]
119 pub fn is_empty(&self) -> bool {
120 self.data.is_empty()
121 }
122
123 #[inline]
125 pub fn capacity(&self) -> usize {
126 self.data.capacity()
127 }
128
129 #[inline]
131 pub fn spilled(&self) -> bool {
132 self.data.spilled()
133 }
134
135 pub fn drain(&mut self) -> Drain<'_> {
137 unsafe {
138 let len = self.len();
139
140 self.data.set_len(0);
141
142 let ptr = self.as_ptr();
143
144 let slice = slice::from_raw_parts(ptr, len);
145 let s = str::from_utf8_unchecked(slice);
146
147 Drain { iter: s.chars() }
148 }
149 }
150
151 #[doc(alias = "drain")]
165 pub fn drain_range<R>(&mut self, range: R) -> DrainRange<'_, A>
166 where
167 R: ops::RangeBounds<usize>,
168 {
169 DrainRange {
170 drain: self.data.drain(range),
171 }
172 }
173
174 #[inline]
188 pub fn push(&mut self, ch: char) {
189 match ch.len_utf8() {
190 1 => self.data.push(ch as u8),
191 _ => self.push_str(ch.encode_utf8(&mut [0; 4])),
192 }
193 }
194
195 #[inline]
209 pub fn push_str(&mut self, s: &str) {
210 self.data.extend_from_slice(s.as_bytes());
211 }
212
213 #[inline]
217 pub fn pop(&mut self) -> Option<char> {
218 match self.chars().next_back() {
219 Some(ch) => unsafe {
220 let new_len = self.len() - ch.len_utf8();
221 self.data.set_len(new_len);
222 Some(ch)
223 },
224 None => None,
225 }
226 }
227
228 #[inline]
234 pub fn grow(&mut self, new_cap: usize) {
235 self.data.grow(new_cap);
236 }
237
238 #[inline]
244 pub fn reserve(&mut self, additional: usize) {
245 self.data.reserve(additional);
246 }
247
248 #[inline]
251 pub fn reserve_exact(&mut self, additional: usize) {
252 self.data.reserve(additional);
253 }
254
255 #[inline]
260 pub fn shrink_to_fit(&mut self) {
261 self.data.shrink_to_fit();
262 }
263
264 #[inline]
273 pub fn truncate(&mut self, len: usize) {
274 assert!(self.is_char_boundary(len));
275 self.data.truncate(len);
276 }
277
278 #[inline]
280 pub fn as_str(&self) -> &str {
281 self
282 }
283
284 #[inline]
286 pub fn as_mut_str(&mut self) -> &mut str {
287 self
288 }
289
290 #[inline]
292 pub fn clear(&mut self) {
293 self.data.clear();
294 }
295
296 #[inline]
302 pub fn remove(&mut self, idx: usize) -> char {
303 let ch = match self[idx..].chars().next() {
304 Some(ch) => ch,
305 None => panic!("cannot remove a char from the end of a string"),
306 };
307
308 let ch_len = ch.len_utf8();
309 let next = idx + ch_len;
310 let len = self.len();
311
312 unsafe {
313 let ptr = self.as_mut_ptr();
314
315 ptr::copy(ptr.add(next), ptr.add(idx), len - next);
316 self.data.set_len(len - ch_len);
317 }
318
319 ch
320 }
321
322 #[inline]
328 pub fn insert(&mut self, idx: usize, ch: char) {
329 assert!(self.is_char_boundary(idx));
330
331 match ch.len_utf8() {
332 1 => self.data.insert(idx, ch as u8),
333 _ => self.insert_str(idx, ch.encode_utf8(&mut [0; 4])),
334 }
335 }
336
337 #[inline]
343 pub fn insert_str(&mut self, idx: usize, s: &str) {
344 assert!(self.is_char_boundary(idx));
345
346 let len = self.len();
347 let amt = s.len();
348
349 self.data.reserve(amt);
350
351 let ptr = self.as_mut_ptr();
352
353 unsafe {
354 ptr::copy(ptr.add(idx), ptr.add(idx + amt), len - idx);
355 ptr::copy_nonoverlapping(s.as_ptr(), ptr.add(idx), amt);
356 self.data.set_len(len + amt);
357 }
358 }
359
360 #[inline]
369 pub unsafe fn as_mut_vec(&mut self) -> &mut SmallVec<A> {
370 &mut self.data
371 }
372
373 #[inline]
376 pub fn into_string(self) -> String {
377 unsafe { String::from_utf8_unchecked(self.data.into_vec()) }
378 }
379
380 #[inline]
385 pub fn into_boxed_str(self) -> Box<str> {
386 self.into_string().into_boxed_str()
387 }
388
389 #[inline]
395 pub fn into_inner(self) -> Result<A, Self> {
396 self.data.into_inner().map_err(|data| SmallString { data })
397 }
398
399 #[inline]
417 pub fn retain<F: FnMut(char) -> bool>(&mut self, mut f: F) {
418 struct SetLenOnDrop<'a, A: Array<Item = u8>> {
419 s: &'a mut SmallString<A>,
420 idx: usize,
421 del_bytes: usize,
422 }
423
424 impl<'a, A: Array<Item = u8>> Drop for SetLenOnDrop<'a, A> {
425 fn drop(&mut self) {
426 let new_len = self.idx - self.del_bytes;
427 debug_assert!(new_len <= self.s.len());
428 unsafe { self.s.data.set_len(new_len) };
429 }
430 }
431
432 let len = self.len();
433 let mut guard = SetLenOnDrop {
434 s: self,
435 idx: 0,
436 del_bytes: 0,
437 };
438
439 while guard.idx < len {
440 let ch = unsafe {
441 guard
442 .s
443 .get_unchecked(guard.idx..len)
444 .chars()
445 .next()
446 .unwrap()
447 };
448 let ch_len = ch.len_utf8();
449
450 if !f(ch) {
451 guard.del_bytes += ch_len;
452 } else if guard.del_bytes > 0 {
453 let ptr = guard.s.as_mut_ptr();
454
455 unsafe {
456 ptr::copy(
457 ptr.add(guard.idx),
458 ptr.add(guard.idx - guard.del_bytes),
459 ch_len,
460 );
461 }
462 }
463
464 guard.idx += ch_len;
466 }
467
468 drop(guard);
469 }
470
471 fn as_ptr(&mut self) -> *const u8 {
472 self.data.as_ptr()
473 }
474
475 fn as_mut_ptr(&mut self) -> *mut u8 {
476 self.data.as_mut_ptr()
477 }
478}
479
480impl<A: Array<Item = u8>> ops::Deref for SmallString<A> {
481 type Target = str;
482
483 #[inline]
484 fn deref(&self) -> &str {
485 let bytes: &[u8] = &self.data;
486 unsafe { str::from_utf8_unchecked(bytes) }
487 }
488}
489
490impl<A: Array<Item = u8>> ops::DerefMut for SmallString<A> {
491 #[inline]
492 fn deref_mut(&mut self) -> &mut str {
493 let bytes: &mut [u8] = &mut self.data;
494 unsafe { str::from_utf8_unchecked_mut(bytes) }
495 }
496}
497
498impl<A: Array<Item = u8>> AsRef<str> for SmallString<A> {
499 #[inline]
500 fn as_ref(&self) -> &str {
501 self
502 }
503}
504
505impl<A: Array<Item = u8>> AsMut<str> for SmallString<A> {
506 #[inline]
507 fn as_mut(&mut self) -> &mut str {
508 self
509 }
510}
511
512impl<A: Array<Item = u8>> Borrow<str> for SmallString<A> {
513 #[inline]
514 fn borrow(&self) -> &str {
515 self
516 }
517}
518
519impl<A: Array<Item = u8>> BorrowMut<str> for SmallString<A> {
520 #[inline]
521 fn borrow_mut(&mut self) -> &mut str {
522 self
523 }
524}
525
526impl<A: Array<Item = u8>> AsRef<[u8]> for SmallString<A> {
527 #[inline]
528 fn as_ref(&self) -> &[u8] {
529 self.data.as_ref()
530 }
531}
532
533impl<A: Array<Item = u8>> fmt::Write for SmallString<A> {
534 #[inline]
535 fn write_str(&mut self, s: &str) -> fmt::Result {
536 self.push_str(s);
537 Ok(())
538 }
539
540 #[inline]
541 fn write_char(&mut self, ch: char) -> fmt::Result {
542 self.push(ch);
543 Ok(())
544 }
545}
546
547impl<A: Array<Item = u8>> FromStr for SmallString<A> {
548 type Err = Infallible;
549
550 fn from_str(s: &str) -> Result<Self, Self::Err> {
551 Ok(SmallString::from(s))
552 }
553}
554
555#[cfg(feature = "serde")]
556impl<A: Array<Item = u8>> Serialize for SmallString<A> {
557 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
558 serializer.serialize_str(self)
559 }
560}
561
562#[cfg(feature = "serde")]
563impl<'de, A: Array<Item = u8>> Deserialize<'de> for SmallString<A> {
564 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
565 deserializer.deserialize_str(SmallStringVisitor {
566 phantom: PhantomData,
567 })
568 }
569}
570
571#[cfg(feature = "serde")]
572struct SmallStringVisitor<A> {
573 phantom: PhantomData<A>,
574}
575
576#[cfg(feature = "serde")]
577impl<'de, A: Array<Item = u8>> Visitor<'de> for SmallStringVisitor<A> {
578 type Value = SmallString<A>;
579
580 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
581 f.write_str("a string")
582 }
583
584 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
585 Ok(v.into())
586 }
587
588 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
589 Ok(v.into())
590 }
591}
592
593impl<A: Array<Item = u8>> From<char> for SmallString<A> {
594 #[inline]
595 fn from(ch: char) -> SmallString<A> {
596 SmallString::from_str(ch.encode_utf8(&mut [0; 4]))
597 }
598}
599
600impl<A: Array<Item = u8>> From<&'_ str> for SmallString<A> {
601 #[inline]
602 fn from(s: &str) -> SmallString<A> {
603 SmallString::from_str(s)
604 }
605}
606
607impl<A: Array<Item = u8>> From<Box<str>> for SmallString<A> {
608 #[inline]
609 fn from(s: Box<str>) -> SmallString<A> {
610 SmallString::from_string(s.into())
611 }
612}
613
614impl<A: Array<Item = u8>> From<String> for SmallString<A> {
615 #[inline]
616 fn from(s: String) -> SmallString<A> {
617 SmallString::from_string(s)
618 }
619}
620
621impl<'a, A: Array<Item = u8>> From<Cow<'a, str>> for SmallString<A> {
622 fn from(value: Cow<'a, str>) -> Self {
623 match value {
624 Cow::Borrowed(s) => Self::from_str(s),
625 Cow::Owned(s) => Self::from_string(s),
626 }
627 }
628}
629
630macro_rules! impl_index_str {
631 ($index_type: ty) => {
632 impl<A: Array<Item = u8>> ops::Index<$index_type> for SmallString<A> {
633 type Output = str;
634
635 #[inline]
636 fn index(&self, index: $index_type) -> &str {
637 &self.as_str()[index]
638 }
639 }
640
641 impl<A: Array<Item = u8>> ops::IndexMut<$index_type> for SmallString<A> {
642 #[inline]
643 fn index_mut(&mut self, index: $index_type) -> &mut str {
644 &mut self.as_mut_str()[index]
645 }
646 }
647 };
648}
649
650impl_index_str!(ops::Range<usize>);
651impl_index_str!(ops::RangeFrom<usize>);
652impl_index_str!(ops::RangeTo<usize>);
653impl_index_str!(ops::RangeFull);
654
655impl<A: Array<Item = u8>> FromIterator<char> for SmallString<A> {
656 fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> SmallString<A> {
657 let mut s = SmallString::new();
658 s.extend(iter);
659 s
660 }
661}
662
663impl<'a, A: Array<Item = u8>> FromIterator<&'a char> for SmallString<A> {
664 fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> SmallString<A> {
665 let mut s = SmallString::new();
666 s.extend(iter.into_iter().cloned());
667 s
668 }
669}
670
671impl<'a, A: Array<Item = u8>> FromIterator<Cow<'a, str>> for SmallString<A> {
672 fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> SmallString<A> {
673 let mut s = SmallString::new();
674 s.extend(iter);
675 s
676 }
677}
678
679impl<'a, A: Array<Item = u8>> FromIterator<&'a str> for SmallString<A> {
680 fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> SmallString<A> {
681 let mut s = SmallString::new();
682 s.extend(iter);
683 s
684 }
685}
686
687impl<A: Array<Item = u8>> FromIterator<String> for SmallString<A> {
688 fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> SmallString<A> {
689 let mut s = SmallString::new();
690 s.extend(iter);
691 s
692 }
693}
694
695impl<A: Array<Item = u8>> Extend<char> for SmallString<A> {
696 fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
697 let iter = iter.into_iter();
698 let (lo, _) = iter.size_hint();
699
700 self.reserve(lo);
701
702 for ch in iter {
703 self.push(ch);
704 }
705 }
706}
707
708impl<'a, A: Array<Item = u8>> Extend<&'a char> for SmallString<A> {
709 fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
710 self.extend(iter.into_iter().cloned());
711 }
712}
713
714impl<'a, A: Array<Item = u8>> Extend<Cow<'a, str>> for SmallString<A> {
715 fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
716 for s in iter {
717 self.push_str(&s);
718 }
719 }
720}
721
722impl<'a, A: Array<Item = u8>> Extend<&'a str> for SmallString<A> {
723 fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
724 for s in iter {
725 self.push_str(s);
726 }
727 }
728}
729
730impl<A: Array<Item = u8>> Extend<String> for SmallString<A> {
731 fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
732 for s in iter {
733 self.push_str(&s);
734 }
735 }
736}
737
738impl<A: Array<Item = u8>> fmt::Debug for SmallString<A> {
739 #[inline]
740 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
741 fmt::Debug::fmt(&**self, f)
742 }
743}
744
745impl<A: Array<Item = u8>> fmt::Display for SmallString<A> {
746 #[inline]
747 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
748 fmt::Display::fmt(&**self, f)
749 }
750}
751
752macro_rules! eq_str {
753 ( $rhs:ty ) => {
754 impl<'a, A: Array<Item = u8>> PartialEq<$rhs> for SmallString<A> {
755 #[inline]
756 fn eq(&self, rhs: &$rhs) -> bool {
757 self[..] == rhs[..]
758 }
759 }
760 };
761}
762
763eq_str!(str);
764eq_str!(&'a str);
765eq_str!(String);
766eq_str!(Cow<'a, str>);
767
768#[cfg(feature = "ffi")]
769impl<A: Array<Item = u8>> PartialEq<OsStr> for SmallString<A> {
770 #[inline]
771 fn eq(&self, rhs: &OsStr) -> bool {
772 &self[..] == rhs
773 }
774}
775
776#[cfg(feature = "ffi")]
777impl<'a, A: Array<Item = u8>> PartialEq<&'a OsStr> for SmallString<A> {
778 #[inline]
779 fn eq(&self, rhs: &&OsStr) -> bool {
780 &self[..] == *rhs
781 }
782}
783
784#[cfg(feature = "ffi")]
785impl<A: Array<Item = u8>> PartialEq<OsString> for SmallString<A> {
786 #[inline]
787 fn eq(&self, rhs: &OsString) -> bool {
788 &self[..] == rhs
789 }
790}
791
792#[cfg(feature = "ffi")]
793impl<'a, A: Array<Item = u8>> PartialEq<Cow<'a, OsStr>> for SmallString<A> {
794 #[inline]
795 fn eq(&self, rhs: &Cow<OsStr>) -> bool {
796 self[..] == **rhs
797 }
798}
799
800impl<A, B> PartialEq<SmallString<B>> for SmallString<A>
801where
802 A: Array<Item = u8>,
803 B: Array<Item = u8>,
804{
805 #[inline]
806 fn eq(&self, rhs: &SmallString<B>) -> bool {
807 self[..] == rhs[..]
808 }
809}
810
811impl<A: Array<Item = u8>> Eq for SmallString<A> {}
812
813impl<A: Array<Item = u8>> PartialOrd for SmallString<A> {
814 #[inline]
815 fn partial_cmp(&self, rhs: &SmallString<A>) -> Option<Ordering> {
816 Some(self.cmp(rhs))
817 }
818}
819
820impl<A: Array<Item = u8>> Ord for SmallString<A> {
821 #[inline]
822 fn cmp(&self, rhs: &SmallString<A>) -> Ordering {
823 self[..].cmp(&rhs[..])
824 }
825}
826
827impl<A: Array<Item = u8>> Hash for SmallString<A> {
828 #[inline]
829 fn hash<H: Hasher>(&self, state: &mut H) {
830 self[..].hash(state)
831 }
832}
833
834pub struct Drain<'a> {
841 iter: Chars<'a>,
842}
843
844impl<'a> Iterator for Drain<'a> {
845 type Item = char;
846
847 #[inline]
848 fn next(&mut self) -> Option<char> {
849 self.iter.next()
850 }
851
852 #[inline]
853 fn size_hint(&self) -> (usize, Option<usize>) {
854 self.iter.size_hint()
855 }
856}
857
858impl<'a> DoubleEndedIterator for Drain<'a> {
859 #[inline]
860 fn next_back(&mut self) -> Option<char> {
861 self.iter.next_back()
862 }
863}
864
865pub struct DrainRange<'a, A: Array<Item = u8>> {
872 drain: smallvec::Drain<'a, A>,
873}
874
875impl<A: Array<Item = u8>> fmt::Debug for DrainRange<'_, A> {
876 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
877 self.drain.fmt(f)
878 }
879}
880
881impl<A: Array<Item = u8>> Iterator for DrainRange<'_, A> {
882 type Item = char;
883
884 fn next(&mut self) -> Option<Self::Item> {
885 let mut buf = [0; 4];
886
887 buf[0] = self.drain.next()?;
888 let utf8_len = 1.max(buf[0].leading_ones() as usize);
889
890 for b in &mut buf[1..utf8_len] {
891 *b = self.drain.next().unwrap();
892 }
893
894 unsafe { str::from_utf8_unchecked(&buf[..utf8_len]) }
895 .chars()
896 .next()
897 }
898
899 fn size_hint(&self) -> (usize, Option<usize>) {
900 let len = self.drain.len();
901 (len.div_ceil(4), Some(len))
902 }
903}
904
905impl<A: Array<Item = u8>> DoubleEndedIterator for DrainRange<'_, A> {
906 fn next_back(&mut self) -> Option<Self::Item> {
907 let mut buf = [0; 4];
908 let mut i = 3;
909
910 buf[i] = self.drain.next_back()?;
911
912 while buf[i].leading_ones() == 1 {
913 i -= 1;
914 buf[i] = self.drain.next_back().unwrap();
915 }
916
917 unsafe { str::from_utf8_unchecked(&buf[i..]) }
918 .chars()
919 .next()
920 }
921}
922impl<A: Array<Item = u8>> FusedIterator for DrainRange<'_, A> {}
923
924#[derive(Debug)]
931pub struct FromUtf8Error<A: Array<Item = u8>> {
932 buf: A,
933 error: Utf8Error,
934}
935
936impl<A: Array<Item = u8>> FromUtf8Error<A> {
937 #[inline]
939 pub fn as_bytes(&self) -> &[u8] {
940 let ptr = &self.buf as *const _ as *const u8;
941 unsafe { slice::from_raw_parts(ptr, A::size()) }
942 }
943
944 #[inline]
946 pub fn into_buf(self) -> A {
947 self.buf
948 }
949
950 #[inline]
952 pub fn utf8_error(&self) -> Utf8Error {
953 self.error
954 }
955}
956
957impl<A: Array<Item = u8>> fmt::Display for FromUtf8Error<A> {
958 #[inline]
959 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
960 fmt::Display::fmt(&self.error, f)
961 }
962}
963
964#[cfg(test)]
965mod test {
966 use alloc::{
967 borrow::{Cow, ToOwned},
968 str::FromStr,
969 string::{String, ToString},
970 };
971
972 use super::SmallString;
973
974 #[test]
975 fn test_drain() {
976 let mut s: SmallString<[u8; 2]> = SmallString::new();
977
978 s.push('a');
979 assert_eq!(s.drain().collect::<String>(), "a");
980 assert!(s.is_empty());
981
982 s.push('x');
984 s.push('y');
985 s.push('z');
986
987 assert_eq!(s.drain().collect::<String>(), "xyz");
988 assert!(s.is_empty());
989 }
990
991 #[test]
992 fn test_drain_range() {
993 let mut s: SmallString<[u8; 2]> = SmallString::new();
994
995 s.push('a');
996 assert_eq!(s.drain_range(..).collect::<String>(), "a");
997 assert!(s.is_empty());
998
999 s.push_str("xyz");
1000
1001 assert_eq!(s.drain_range(1..).collect::<String>(), "yz");
1002 assert_eq!(s, "x");
1003
1004 s.push_str("yz");
1005
1006 assert_eq!(s.drain_range(..2).collect::<String>(), "xy");
1007 assert_eq!(s, "z");
1008
1009 s.clear();
1010 s.push_str("测试文本");
1011
1012 assert_eq!(s.drain_range(3..9).collect::<String>(), "试文");
1013 assert_eq!(s, "测本");
1014 }
1015
1016 #[test]
1017 fn test_drain_rev() {
1018 let mut s: SmallString<[u8; 2]> = SmallString::new();
1019
1020 s.push('a');
1021 assert_eq!(s.drain().rev().collect::<String>(), "a");
1022 assert!(s.is_empty());
1023
1024 s.push('x');
1026 s.push('y');
1027 s.push('z');
1028
1029 assert_eq!(s.drain().rev().collect::<String>(), "zyx");
1030 assert!(s.is_empty());
1031 }
1032
1033 #[test]
1034 fn test_drain_range_rev() {
1035 let mut s: SmallString<[u8; 2]> = SmallString::new();
1036
1037 s.push('a');
1038 assert_eq!(s.drain_range(..).rev().collect::<String>(), "a");
1039 assert!(s.is_empty());
1040
1041 s.push_str("xyz");
1043
1044 assert_eq!(s.drain_range(..).rev().collect::<String>(), "zyx");
1045 assert!(s.is_empty());
1046
1047 s.push_str("xyz");
1048
1049 assert_eq!(s.drain_range(1..).rev().collect::<String>(), "zy");
1050 assert_eq!(s, "x");
1051
1052 s.push_str("yz");
1053
1054 assert_eq!(s.drain_range(..2).rev().collect::<String>(), "yx");
1055 assert_eq!(s, "z");
1056
1057 s.clear();
1058 s.push_str("测试文本");
1059
1060 assert_eq!(s.drain_range(3..9).rev().collect::<String>(), "文试");
1061 assert_eq!(s, "测本");
1062 }
1063
1064 #[test]
1065 fn test_eq() {
1066 let s: SmallString<[u8; 4]> = SmallString::from("foo");
1067
1068 assert_eq!(s, *"foo");
1069 assert_eq!(s, "foo");
1070 assert_eq!(s, "foo".to_owned());
1071 assert_eq!(s, Cow::Borrowed("foo"));
1072 }
1073
1074 #[cfg(feature = "ffi")]
1075 #[test]
1076 fn test_eq_os_str() {
1077 use std::ffi::OsStr;
1078
1079 let s: SmallString<[u8; 4]> = SmallString::from("foo");
1080 let os_s: &OsStr = "foo".as_ref();
1081
1082 assert_eq!(s, os_s);
1083 assert_eq!(s, *os_s);
1084 assert_eq!(s, os_s.to_owned());
1085 assert_eq!(s, Cow::Borrowed(os_s));
1086 }
1087
1088 #[test]
1089 fn test_from_buf() {
1090 let s: SmallString<[u8; 2]> = SmallString::from_buf([206, 177]).unwrap();
1091 assert_eq!(s, "α");
1092
1093 assert!(SmallString::<[u8; 2]>::from_buf([206, 0]).is_err());
1094 }
1095
1096 #[test]
1097 fn test_insert() {
1098 let mut s: SmallString<[u8; 8]> = SmallString::from("abc");
1099
1100 s.insert(1, 'x');
1101 assert_eq!(s, "axbc");
1102
1103 s.insert(3, 'α');
1104 assert_eq!(s, "axbαc");
1105
1106 s.insert_str(0, "foo");
1107 assert_eq!(s, "fooaxbαc");
1108 }
1109
1110 #[test]
1111 #[should_panic]
1112 fn test_insert_panic() {
1113 let mut s: SmallString<[u8; 8]> = SmallString::from("αβγ");
1114
1115 s.insert(1, 'x');
1116 }
1117
1118 #[test]
1119 fn test_into_string() {
1120 let s: SmallString<[u8; 2]> = SmallString::from("foo");
1121 assert_eq!(s.into_string(), "foo");
1122
1123 let s: SmallString<[u8; 8]> = SmallString::from("foo");
1124 assert_eq!(s.into_string(), "foo");
1125 }
1126
1127 #[test]
1128 fn test_to_string() {
1129 let s: SmallString<[u8; 2]> = SmallString::from("foo");
1130 assert_eq!(s.to_string(), "foo");
1131
1132 let s: SmallString<[u8; 8]> = SmallString::from("foo");
1133 assert_eq!(s.to_string(), "foo");
1134 }
1135
1136 #[test]
1137 fn test_pop() {
1138 let mut s: SmallString<[u8; 8]> = SmallString::from("αβγ");
1139
1140 assert_eq!(s.pop(), Some('γ'));
1141 assert_eq!(s.pop(), Some('β'));
1142 assert_eq!(s.pop(), Some('α'));
1143 assert_eq!(s.pop(), None);
1144 }
1145
1146 #[test]
1147 fn test_remove() {
1148 let mut s: SmallString<[u8; 8]> = SmallString::from("αβγ");
1149
1150 assert_eq!(s.remove(2), 'β');
1151 assert_eq!(s, "αγ");
1152
1153 assert_eq!(s.remove(0), 'α');
1154 assert_eq!(s, "γ");
1155
1156 assert_eq!(s.remove(0), 'γ');
1157 assert_eq!(s, "");
1158 }
1159
1160 #[test]
1161 #[should_panic]
1162 fn test_remove_panic_0() {
1163 let mut s: SmallString<[u8; 8]> = SmallString::from("foo");
1164
1165 s.remove(3);
1167 }
1168
1169 #[test]
1170 #[should_panic]
1171 fn test_remove_panic_1() {
1172 let mut s: SmallString<[u8; 8]> = SmallString::from("αβγ");
1173
1174 s.remove(1);
1176 }
1177
1178 #[test]
1179 fn test_retain() {
1180 let mut s: SmallString<[u8; 8]> = SmallString::from("α_β_γ");
1181
1182 s.retain(|_| true);
1183 assert_eq!(s, "α_β_γ");
1184
1185 s.retain(|c| c != '_');
1186 assert_eq!(s, "αβγ");
1187
1188 s.retain(|c| c != 'β');
1189 assert_eq!(s, "αγ");
1190
1191 s.retain(|c| c == 'α');
1192 assert_eq!(s, "α");
1193
1194 s.retain(|_| false);
1195 assert_eq!(s, "");
1196 }
1197
1198 #[test]
1199 fn test_truncate() {
1200 let mut s: SmallString<[u8; 2]> = SmallString::from("foobar");
1201
1202 s.truncate(6);
1203 assert_eq!(s, "foobar");
1204
1205 s.truncate(3);
1206 assert_eq!(s, "foo");
1207 }
1208
1209 #[test]
1210 #[should_panic]
1211 fn test_truncate_panic() {
1212 let mut s: SmallString<[u8; 2]> = SmallString::from("α");
1213
1214 s.truncate(1);
1215 }
1216
1217 #[test]
1218 fn test_write() {
1219 use core::fmt::Write;
1220
1221 let mut s: SmallString<[u8; 8]> = SmallString::from("foo");
1222
1223 write!(s, "bar").unwrap();
1224
1225 assert_eq!(s, "foobar");
1226 }
1227
1228 #[test]
1229 fn test_from_str() {
1230 let s: SmallString<[u8; 8]> = FromStr::from_str("foo").unwrap();
1231
1232 assert_eq!(s, "foo");
1233 }
1234
1235 #[cfg(feature = "serde")]
1236 #[test]
1237 fn test_serde() {
1238 use bincode::{deserialize, serialize};
1239
1240 let mut small_str: SmallString<[u8; 4]> = SmallString::from("foo");
1241
1242 let encoded = serialize(&small_str).unwrap();
1243 let decoded: SmallString<[u8; 4]> = deserialize(&encoded).unwrap();
1244
1245 assert_eq!(small_str, decoded);
1246
1247 small_str.push_str("bar");
1249
1250 let encoded = serialize(&small_str).unwrap();
1252 let decoded: SmallString<[u8; 4]> = deserialize(&encoded).unwrap();
1253
1254 assert_eq!(small_str, decoded);
1255 }
1256}