1use core::{
4 borrow,
5 char::DecodeUtf16Error,
6 cmp::Ordering,
7 fmt,
8 fmt::{Arguments, Write},
9 hash, iter,
10 ops::{self, Range, RangeBounds},
11 str::{self, Utf8Error},
12};
13
14#[cfg(feature = "zeroize")]
15use zeroize::Zeroize;
16
17use crate::{
18 len_type::LenType,
19 vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage},
20 CapacityError,
21};
22
23mod drain;
24pub use drain::Drain;
25
26#[derive(Debug)]
32pub enum FromUtf16Error {
33 Capacity(CapacityError),
35 DecodeUtf16(DecodeUtf16Error),
37}
38
39impl fmt::Display for FromUtf16Error {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 Self::Capacity(err) => write!(f, "{err}"),
43 Self::DecodeUtf16(err) => write!(f, "invalid UTF-16: {err}"),
44 }
45 }
46}
47
48impl core::error::Error for FromUtf16Error {}
49
50impl From<CapacityError> for FromUtf16Error {
51 fn from(e: CapacityError) -> Self {
52 Self::Capacity(e)
53 }
54}
55
56mod storage {
57 use super::{StringInner, StringView};
58 use crate::{
59 vec::{OwnedVecStorage, VecStorage, ViewVecStorage},
60 LenType,
61 };
62
63 pub trait StringStorage: StringStorageSealed {}
90 pub trait StringStorageSealed: VecStorage<u8> {
91 fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
92 where
93 Self: StringStorage;
94 fn as_string_mut_view<LenT: LenType>(
95 this: &mut StringInner<LenT, Self>,
96 ) -> &mut StringView<LenT>
97 where
98 Self: StringStorage;
99 }
100
101 impl<const N: usize> StringStorage for OwnedVecStorage<u8, N> {}
102 impl<const N: usize> StringStorageSealed for OwnedVecStorage<u8, N> {
103 fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
104 where
105 Self: StringStorage,
106 {
107 this
108 }
109 fn as_string_mut_view<LenT: LenType>(
110 this: &mut StringInner<LenT, Self>,
111 ) -> &mut StringView<LenT>
112 where
113 Self: StringStorage,
114 {
115 this
116 }
117 }
118
119 impl StringStorage for ViewVecStorage<u8> {}
120
121 impl StringStorageSealed for ViewVecStorage<u8> {
122 fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
123 where
124 Self: StringStorage,
125 {
126 this
127 }
128 fn as_string_mut_view<LenT: LenType>(
129 this: &mut StringInner<LenT, Self>,
130 ) -> &mut StringView<LenT>
131 where
132 Self: StringStorage,
133 {
134 this
135 }
136 }
137}
138
139pub use storage::StringStorage;
140
141pub type OwnedStorage<const N: usize> = OwnedVecStorage<u8, N>;
144pub type ViewStorage = ViewVecStorage<u8>;
146
147#[cfg_attr(feature = "zeroize", derive(Zeroize), zeroize(bound = "S: Zeroize"))]
152pub struct StringInner<LenT: LenType, S: StringStorage + ?Sized> {
153 vec: VecInner<u8, LenT, S>,
154}
155
156pub type String<const N: usize, LenT = usize> = StringInner<LenT, OwnedStorage<N>>;
158
159pub type StringView<LenT = usize> = StringInner<LenT, ViewStorage>;
161
162impl<LenT: LenType, const N: usize> String<N, LenT> {
163 #[inline]
179 pub const fn new() -> Self {
180 Self { vec: Vec::new() }
181 }
182
183 #[inline]
203 pub fn from_utf16(v: &[u16]) -> Result<Self, FromUtf16Error> {
204 let mut s = Self::new();
205
206 for c in char::decode_utf16(v.iter().cloned()) {
207 match c {
208 Ok(c) => {
209 s.push(c).map_err(|_| CapacityError)?;
210 }
211 Err(err) => {
212 return Err(FromUtf16Error::DecodeUtf16(err));
213 }
214 }
215 }
216
217 Ok(s)
218 }
219
220 #[inline]
251 pub fn from_utf8(vec: Vec<u8, N, LenT>) -> Result<Self, Utf8Error> {
252 core::str::from_utf8(&vec)?;
253
254 Ok(unsafe { Self::from_utf8_unchecked(vec) })
256 }
257
258 #[inline]
280 pub unsafe fn from_utf8_unchecked(vec: Vec<u8, N, LenT>) -> Self {
281 Self { vec }
282 }
283
284 #[inline]
303 pub fn into_bytes(self) -> Vec<u8, N, LenT> {
304 self.vec
305 }
306}
307
308impl<LenT: LenType, S: StringStorage + ?Sized> StringInner<LenT, S> {
309 pub fn drain<R>(&mut self, range: R) -> Drain<'_, LenT>
345 where
346 R: RangeBounds<usize>,
347 {
348 let Range { start, end } = crate::slice::range(range, ..self.len());
355 assert!(self.is_char_boundary(start));
356 assert!(self.is_char_boundary(end));
357
358 let self_ptr = self.as_mut_view() as *mut _;
361 let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
363
364 Drain {
365 start: LenT::from_usize(start),
366 end: LenT::from_usize(end),
367 iter: chars_iter,
368 string: self_ptr,
369 }
370 }
371
372 #[inline]
390 pub fn as_view(&self) -> &StringView<LenT> {
391 S::as_string_view(self)
392 }
393
394 #[inline]
412 pub fn as_mut_view(&mut self) -> &mut StringView<LenT> {
413 S::as_string_mut_view(self)
414 }
415
416 #[inline]
433 pub fn as_str(&self) -> &str {
434 unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
435 }
436
437 #[inline]
452 pub fn as_mut_str(&mut self) -> &mut str {
453 unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) }
454 }
455
456 pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, LenT, S> {
484 &mut self.vec
485 }
486
487 #[inline]
506 pub fn push_str(&mut self, string: &str) -> Result<(), CapacityError> {
507 self.vec.extend_from_slice(string.as_bytes())
508 }
509
510 #[inline]
523 pub fn capacity(&self) -> usize {
524 self.vec.capacity()
525 }
526
527 #[inline]
548 pub fn push(&mut self, c: char) -> Result<(), CapacityError> {
549 match c.len_utf8() {
550 1 => self.vec.push(c as u8).map_err(|_| CapacityError),
551 _ => self
552 .vec
553 .extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()),
554 }
555 }
556
557 #[inline]
584 pub fn truncate(&mut self, new_len: usize) {
585 if new_len <= self.len() {
586 assert!(self.is_char_boundary(new_len));
587 self.vec.truncate(new_len);
588 }
589 }
590
591 pub fn pop(&mut self) -> Option<char> {
612 let ch = self.chars().next_back()?;
613
614 for _ in 0..ch.len_utf8() {
616 unsafe {
617 self.vec.pop_unchecked();
618 }
619 }
620
621 Some(ch)
622 }
623
624 #[inline]
648 pub fn remove(&mut self, index: usize) -> char {
649 let ch = self[index..]
650 .chars()
651 .next()
652 .unwrap_or_else(|| panic!("cannot remove a char from the end of a string"));
653
654 let next = index + ch.len_utf8();
655 let len = self.len();
656 let ptr = self.vec.as_mut_ptr();
657 unsafe {
658 core::ptr::copy(ptr.add(next), ptr.add(index), len - next);
659 self.vec.set_len(len - (next - index));
660 }
661 ch
662 }
663
664 #[inline]
686 pub fn clear(&mut self) {
687 self.vec.clear();
688 }
689
690 #[inline]
715 pub fn insert(&mut self, idx: usize, ch: char) -> Result<(), CapacityError> {
716 assert!(self.is_char_boundary(idx), "index must be a char boundary");
717
718 let len = self.len();
719 let ch_len = ch.len_utf8();
720
721 if len + ch_len > self.capacity() {
723 return Err(CapacityError);
724 }
725
726 unsafe {
730 let ptr = self.vec.as_mut_ptr();
731 core::ptr::copy(ptr.add(idx), ptr.add(idx + ch_len), len - idx);
732 }
733
734 unsafe {
739 let buf = core::slice::from_raw_parts_mut(self.vec.as_mut_ptr().add(idx), ch_len);
740 ch.encode_utf8(buf);
741 }
742
743 unsafe {
746 self.vec.set_len(len + ch_len);
747 }
748
749 Ok(())
750 }
751
752 #[inline]
775 pub fn insert_str(&mut self, idx: usize, string: &str) -> Result<(), CapacityError> {
776 assert!(self.is_char_boundary(idx), "index must be a char boundary");
777
778 let len = self.len();
779 let string_len = string.len();
780
781 if len + string_len > self.capacity() {
783 return Err(CapacityError);
784 }
785
786 unsafe {
790 let ptr = self.vec.as_mut_ptr();
791 core::ptr::copy(ptr.add(idx), ptr.add(idx + string_len), len - idx);
792 }
793
794 unsafe {
798 core::ptr::copy_nonoverlapping(
799 string.as_ptr(),
800 self.vec.as_mut_ptr().add(idx),
801 string_len,
802 );
803 }
804
805 unsafe {
807 self.vec.set_len(len + string_len);
808 }
809
810 Ok(())
811 }
812}
813
814impl<LenT: LenType, const N: usize> Default for String<N, LenT> {
815 fn default() -> Self {
816 Self::new()
817 }
818}
819
820impl<'a, LenT: LenType, const N: usize> TryFrom<&'a str> for String<N, LenT> {
821 type Error = CapacityError;
822
823 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
824 let mut new = Self::new();
825 new.push_str(s)?;
826 Ok(new)
827 }
828}
829
830impl<LenT: LenType, const N: usize> str::FromStr for String<N, LenT> {
831 type Err = CapacityError;
832
833 fn from_str(s: &str) -> Result<Self, Self::Err> {
834 let mut new = Self::new();
835 new.push_str(s)?;
836 Ok(new)
837 }
838}
839
840impl<LenT: LenType, const N: usize> iter::FromIterator<char> for String<N, LenT> {
841 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
842 let mut new = Self::new();
843 for c in iter {
844 new.push(c).unwrap();
845 }
846 new
847 }
848}
849
850impl<'a, LenT: LenType, const N: usize> iter::FromIterator<&'a char> for String<N, LenT> {
851 fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
852 let mut new = Self::new();
853 for c in iter {
854 new.push(*c).unwrap();
855 }
856 new
857 }
858}
859
860impl<'a, LenT: LenType, const N: usize> iter::FromIterator<&'a str> for String<N, LenT> {
861 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
862 let mut new = Self::new();
863 for c in iter {
864 new.push_str(c).unwrap();
865 }
866 new
867 }
868}
869
870impl<LenT: LenType, const N: usize> Clone for String<N, LenT> {
871 fn clone(&self) -> Self {
872 Self {
873 vec: self.vec.clone(),
874 }
875 }
876}
877
878impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Debug for StringInner<LenT, S> {
879 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
880 <str as fmt::Debug>::fmt(self, f)
881 }
882}
883
884impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Display for StringInner<LenT, S> {
885 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
886 <str as fmt::Display>::fmt(self, f)
887 }
888}
889
890impl<LenT: LenType, S: StringStorage + ?Sized> hash::Hash for StringInner<LenT, S> {
891 #[inline]
892 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
893 <str as hash::Hash>::hash(self, hasher);
894 }
895}
896
897impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Write for StringInner<LenT, S> {
898 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
899 self.push_str(s).map_err(|_| fmt::Error)
900 }
901
902 fn write_char(&mut self, c: char) -> Result<(), fmt::Error> {
903 self.push(c).map_err(|_| fmt::Error)
904 }
905}
906
907impl<LenT: LenType, S: StringStorage + ?Sized> ops::Deref for StringInner<LenT, S> {
908 type Target = str;
909
910 fn deref(&self) -> &str {
911 self.as_str()
912 }
913}
914
915impl<LenT: LenType, S: StringStorage + ?Sized> ops::DerefMut for StringInner<LenT, S> {
916 fn deref_mut(&mut self) -> &mut str {
917 self.as_mut_str()
918 }
919}
920
921impl<LenT: LenType, S: StringStorage + ?Sized> borrow::Borrow<str> for StringInner<LenT, S> {
922 fn borrow(&self) -> &str {
923 self.as_str()
924 }
925}
926impl<LenT: LenType, S: StringStorage + ?Sized> borrow::BorrowMut<str> for StringInner<LenT, S> {
927 fn borrow_mut(&mut self) -> &mut str {
928 self.as_mut_str()
929 }
930}
931
932impl<LenT: LenType, S: StringStorage + ?Sized> AsRef<str> for StringInner<LenT, S> {
933 #[inline]
934 fn as_ref(&self) -> &str {
935 self
936 }
937}
938
939impl<LenT: LenType, S: StringStorage + ?Sized> AsRef<[u8]> for StringInner<LenT, S> {
940 #[inline]
941 fn as_ref(&self) -> &[u8] {
942 self.as_bytes()
943 }
944}
945
946impl<LenT1: LenType, LenT2: LenType, S1: StringStorage + ?Sized, S2: StringStorage + ?Sized>
947 PartialEq<StringInner<LenT1, S1>> for StringInner<LenT2, S2>
948{
949 fn eq(&self, rhs: &StringInner<LenT1, S1>) -> bool {
950 str::eq(&**self, &**rhs)
951 }
952}
953
954impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<str> for StringInner<LenT, S> {
956 #[inline]
957 fn eq(&self, other: &str) -> bool {
958 str::eq(self, other)
959 }
960}
961
962impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<&str> for StringInner<LenT, S> {
964 #[inline]
965 fn eq(&self, other: &&str) -> bool {
966 str::eq(self, &other[..])
967 }
968}
969
970impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<StringInner<LenT, S>> for str {
972 #[inline]
973 fn eq(&self, other: &StringInner<LenT, S>) -> bool {
974 Self::eq(self, &other[..])
975 }
976}
977
978impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<StringInner<LenT, S>> for &str {
980 #[inline]
981 fn eq(&self, other: &StringInner<LenT, S>) -> bool {
982 str::eq(self, &other[..])
983 }
984}
985
986impl<LenT: LenType, S: StringStorage + ?Sized> Eq for StringInner<LenT, S> {}
987
988impl<LenT1: LenType, LenT2: LenType, S1: StringStorage + ?Sized, S2: StringStorage + ?Sized>
989 PartialOrd<StringInner<LenT1, S1>> for StringInner<LenT2, S2>
990{
991 #[inline]
992 fn partial_cmp(&self, other: &StringInner<LenT1, S1>) -> Option<Ordering> {
993 PartialOrd::partial_cmp(&**self, &**other)
994 }
995}
996
997impl<LenT: LenType, S: StringStorage + ?Sized> Ord for StringInner<LenT, S> {
998 #[inline]
999 fn cmp(&self, other: &Self) -> Ordering {
1000 Ord::cmp(&**self, &**other)
1001 }
1002}
1003
1004#[doc(hidden)]
1019pub fn format<const N: usize, LenT: LenType>(
1020 args: Arguments<'_>,
1021) -> Result<String<N, LenT>, fmt::Error> {
1022 fn format_inner<const N: usize, LenT: LenType>(
1023 args: Arguments<'_>,
1024 ) -> Result<String<N, LenT>, fmt::Error> {
1025 let mut output = String::new();
1026 output.write_fmt(args)?;
1027 Ok(output)
1028 }
1029
1030 args.as_str().map_or_else(
1031 || format_inner(args),
1032 |s| s.try_into().map_err(|_| fmt::Error),
1033 )
1034}
1035
1036#[macro_export]
1070macro_rules! format {
1071 ($max:expr; $lenT:path; $($arg:tt)*) => {{
1074 let res = $crate::_export::format::<$max, $lenT>(core::format_args!($($arg)*));
1075 res
1076 }};
1077 ($max:expr; $($arg:tt)*) => {{
1078 let res = $crate::_export::format::<$max, usize>(core::format_args!($($arg)*));
1079 res
1080 }};
1081 ($($arg:tt)*) => {{
1082 let res = $crate::_export::format(core::format_args!($($arg)*));
1083 res
1084 }};
1085}
1086
1087macro_rules! impl_try_from_num {
1088 ($num:ty, $size:expr) => {
1089 impl<LenT: LenType, const N: usize> core::convert::TryFrom<$num> for String<N, LenT> {
1090 type Error = ();
1091 fn try_from(s: $num) -> Result<Self, Self::Error> {
1092 let mut new = String::new();
1093 write!(&mut new, "{}", s).map_err(|_| ())?;
1094 Ok(new)
1095 }
1096 }
1097 };
1098}
1099
1100impl_try_from_num!(i8, 4);
1101impl_try_from_num!(i16, 6);
1102impl_try_from_num!(i32, 11);
1103impl_try_from_num!(i64, 20);
1104
1105impl_try_from_num!(u8, 3);
1106impl_try_from_num!(u16, 5);
1107impl_try_from_num!(u32, 10);
1108impl_try_from_num!(u64, 20);
1109
1110#[cfg(test)]
1111mod tests {
1112 use crate::{CapacityError, String, Vec};
1113
1114 #[test]
1115 fn static_new() {
1116 static mut _S: String<8> = String::new();
1117 }
1118
1119 #[test]
1120 fn clone() {
1121 let s1: String<20> = String::try_from("abcd").unwrap();
1122 let mut s2 = s1.clone();
1123 s2.push_str(" efgh").unwrap();
1124
1125 assert_eq!(s1, "abcd");
1126 assert_eq!(s2, "abcd efgh");
1127 }
1128
1129 #[test]
1130 fn cmp() {
1131 let s1: String<4> = String::try_from("abcd").unwrap();
1132 let s2: String<4> = String::try_from("zzzz").unwrap();
1133
1134 assert!(s1 < s2);
1135 }
1136
1137 #[test]
1138 fn cmp_heterogenous_size() {
1139 let s1: String<4> = String::try_from("abcd").unwrap();
1140 let s2: String<8> = String::try_from("zzzz").unwrap();
1141
1142 assert!(s1 < s2);
1143 }
1144
1145 #[test]
1146 fn debug() {
1147 use core::fmt::Write;
1148
1149 let s: String<8> = String::try_from("abcd").unwrap();
1150 let mut std_s = std::string::String::new();
1151 write!(std_s, "{s:?}").unwrap();
1152 assert_eq!("\"abcd\"", std_s);
1153 }
1154
1155 #[test]
1156 fn display() {
1157 use core::fmt::Write;
1158
1159 let s: String<8> = String::try_from("abcd").unwrap();
1160 let mut std_s = std::string::String::new();
1161 write!(std_s, "{s}").unwrap();
1162 assert_eq!("abcd", std_s);
1163 }
1164
1165 #[test]
1166 fn empty() {
1167 let s: String<4> = String::new();
1168 assert!(s.capacity() == 4);
1169 assert_eq!(s, "");
1170 assert_eq!(s.len(), 0);
1171 assert_ne!(s.len(), 4);
1172 }
1173
1174 #[test]
1175 fn try_from() {
1176 let s: String<4> = String::try_from("123").unwrap();
1177 assert!(s.len() == 3);
1178 assert_eq!(s, "123");
1179
1180 let _: CapacityError = String::<2>::try_from("123").unwrap_err();
1181 }
1182
1183 #[test]
1184 fn from_str() {
1185 use core::str::FromStr;
1186
1187 let s: String<4> = String::<4>::from_str("123").unwrap();
1188 assert!(s.len() == 3);
1189 assert_eq!(s, "123");
1190
1191 let _: CapacityError = String::<2>::from_str("123").unwrap_err();
1192 }
1193
1194 #[test]
1195 fn from_iter() {
1196 let mut v: Vec<char, 5> = Vec::new();
1197 v.push('h').unwrap();
1198 v.push('e').unwrap();
1199 v.push('l').unwrap();
1200 v.push('l').unwrap();
1201 v.push('o').unwrap();
1202 let string1: String<5> = v.iter().collect(); let string2: String<5> = "hello".chars().collect(); assert_eq!(string1, "hello");
1205 assert_eq!(string2, "hello");
1206 }
1207
1208 #[test]
1209 #[should_panic]
1210 fn from_panic() {
1211 let _: String<4> = String::try_from("12345").unwrap();
1212 }
1213
1214 #[test]
1215 fn try_from_num() {
1216 let v: String<20> = String::try_from(18446744073709551615_u64).unwrap();
1217 assert_eq!(v, "18446744073709551615");
1218
1219 let _: () = String::<2>::try_from(18446744073709551615_u64).unwrap_err();
1220 }
1221
1222 #[test]
1223 fn into_bytes() {
1224 let s: String<4> = String::try_from("ab").unwrap();
1225 let b: Vec<u8, 4> = s.into_bytes();
1226 assert_eq!(b.len(), 2);
1227 assert_eq!(b"ab", &b[..]);
1228 }
1229
1230 #[test]
1231 fn as_str() {
1232 let s: String<4> = String::try_from("ab").unwrap();
1233
1234 assert_eq!(s.as_str(), "ab");
1235 }
1239
1240 #[test]
1241 fn as_mut_str() {
1242 let mut s: String<4> = String::try_from("ab").unwrap();
1243 let s = s.as_mut_str();
1244 s.make_ascii_uppercase();
1245 assert_eq!(s, "AB");
1246 }
1247
1248 #[test]
1249 fn push_str() {
1250 let mut s: String<8> = String::try_from("foo").unwrap();
1251 assert!(s.push_str("bar").is_ok());
1252 assert_eq!("foobar", s);
1253 assert_eq!(s, "foobar");
1254 assert!(s.push_str("tender").is_err());
1255 assert_eq!("foobar", s);
1256 assert_eq!(s, "foobar");
1257 }
1258
1259 #[test]
1260 fn push() {
1261 let mut s: String<6> = String::try_from("abc").unwrap();
1262 assert!(s.push('1').is_ok());
1263 assert!(s.push('2').is_ok());
1264 assert!(s.push('3').is_ok());
1265 assert!(s.push('4').is_err());
1266 assert!("abc123" == s.as_str());
1267 }
1268
1269 #[test]
1270 fn as_bytes() {
1271 let s: String<8> = String::try_from("hello").unwrap();
1272 assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
1273 }
1274
1275 #[test]
1276 fn truncate() {
1277 let mut s: String<8> = String::try_from("hello").unwrap();
1278 s.truncate(6);
1279 assert_eq!(s.len(), 5);
1280 s.truncate(2);
1281 assert_eq!(s.len(), 2);
1282 assert_eq!("he", s);
1283 assert_eq!(s, "he");
1284 }
1285
1286 #[test]
1287 fn pop() {
1288 let mut s: String<8> = String::try_from("foo").unwrap();
1289 assert_eq!(s.pop(), Some('o'));
1290 assert_eq!(s.pop(), Some('o'));
1291 assert_eq!(s.pop(), Some('f'));
1292 assert_eq!(s.pop(), None);
1293 }
1294
1295 #[test]
1296 fn pop_uenc() {
1297 let mut s: String<8> = String::try_from("é").unwrap();
1298 assert_eq!(s.len(), 3);
1299 match s.pop() {
1300 Some(c) => {
1301 assert_eq!(s.len(), 1);
1302 assert_eq!(c, '\u{0301}'); }
1304 None => panic!(),
1305 };
1306 }
1307
1308 #[test]
1309 fn is_empty() {
1310 let mut v: String<8> = String::new();
1311 assert!(v.is_empty());
1312 let _ = v.push('a');
1313 assert!(!v.is_empty());
1314 }
1315
1316 #[test]
1317 fn clear() {
1318 let mut s: String<8> = String::try_from("foo").unwrap();
1319 s.clear();
1320 assert!(s.is_empty());
1321 assert_eq!(0, s.len());
1322 assert_eq!(8, s.capacity());
1323 }
1324
1325 #[test]
1326 fn remove() {
1327 let mut s: String<8> = String::try_from("foo").unwrap();
1328 assert_eq!(s.remove(0), 'f');
1329 assert_eq!(s.as_str(), "oo");
1330 }
1331
1332 #[test]
1333 fn remove_uenc() {
1334 let mut s: String<8> = String::try_from("ĝėēƶ").unwrap();
1335 assert_eq!(s.remove(2), 'ė');
1336 assert_eq!(s.remove(2), 'ē');
1337 assert_eq!(s.remove(2), 'ƶ');
1338 assert_eq!(s.as_str(), "ĝ");
1339 }
1340
1341 #[test]
1342 fn remove_uenc_combo_characters() {
1343 let mut s: String<8> = String::try_from("héy").unwrap();
1344 assert_eq!(s.remove(2), '\u{0301}');
1345 assert_eq!(s.as_str(), "hey");
1346 }
1347
1348 #[test]
1349 fn format() {
1350 let number = 5;
1351 let float = 3.12;
1352 let formatted = format!(15; "{:0>3} plus {float}", number).unwrap();
1353 assert_eq!(formatted, "005 plus 3.12");
1354 }
1355 #[test]
1356 fn format_inferred_capacity() {
1357 let number = 5;
1358 let float = 3.12;
1359 let formatted: String<15> = format!("{:0>3} plus {float}", number).unwrap();
1360 assert_eq!(formatted, "005 plus 3.12");
1361 }
1362
1363 #[test]
1364 fn format_overflow() {
1365 let i = 1234567;
1366 let formatted = format!(4; "13{}", i);
1367 assert_eq!(formatted, Err(core::fmt::Error));
1368 }
1369
1370 #[test]
1371 fn format_plain_string_overflow() {
1372 let formatted = format!(2; "123");
1373 assert_eq!(formatted, Err(core::fmt::Error));
1374 }
1375
1376 #[test]
1377 fn insert() {
1378 let mut s: String<6> = String::try_from("123").unwrap();
1379 assert!(s.insert(0, 'a').is_ok());
1380 assert_eq!(s, "a123");
1381
1382 assert!(s.insert(2, 'b').is_ok());
1383 assert_eq!(s, "a1b23");
1384
1385 assert!(s.insert(s.len(), '4').is_ok());
1386 assert_eq!(s, "a1b234");
1387
1388 assert_eq!(s.len(), 6);
1389 assert!(s.insert(0, 'd').is_err());
1390 assert_eq!(s, "a1b234");
1391 }
1392
1393 #[test]
1394 fn insert_unicode() {
1395 let mut s: String<21> = String::try_from("ĝėēƶ").unwrap();
1396 let idx = s.find("ė").unwrap();
1397
1398 assert!(s.insert(idx, '🦀').is_ok());
1399 assert_eq!(s, "ĝ🦀ėēƶ");
1400
1401 s.insert(s.len(), '🦀').unwrap();
1402 assert_eq!(s, "ĝ🦀ėēƶ🦀");
1403
1404 s.insert(0, '🦀').unwrap();
1405 assert_eq!(s, "🦀ĝ🦀ėēƶ🦀");
1406
1407 assert_eq!(s.len(), 20);
1408 assert_eq!('ƶ'.len_utf8(), 2);
1409 assert!(s.insert(0, 'ƶ').is_err());
1410 assert_eq!(s, "🦀ĝ🦀ėēƶ🦀");
1411 }
1412
1413 #[test]
1414 #[should_panic = "index must be a char boundary"]
1415 fn insert_at_non_char_boundary_panics() {
1416 let mut s: String<8> = String::try_from("é").unwrap();
1417 _ = s.insert(1, 'a');
1418 }
1419
1420 #[test]
1421 #[should_panic = "index must be a char boundary"]
1422 fn insert_beyond_length_panics() {
1423 let mut s: String<8> = String::try_from("a").unwrap();
1424 _ = s.insert(2, 'a');
1425 }
1426
1427 #[test]
1428 fn insert_str() {
1429 let mut s: String<14> = String::try_from("bar").unwrap();
1430 assert!(s.insert_str(0, "foo").is_ok());
1431 assert_eq!(s, "foobar");
1432
1433 assert!(s.insert_str(3, "baz").is_ok());
1434 assert_eq!(s, "foobazbar");
1435
1436 assert!(s.insert_str(s.len(), "end").is_ok());
1437 assert_eq!(s, "foobazbarend");
1438
1439 assert_eq!(s.len(), 12);
1440 assert!(s.insert_str(0, "def").is_err());
1441 assert_eq!(s, "foobazbarend");
1442 }
1443
1444 #[test]
1445 fn insert_str_unicode() {
1446 let mut s: String<20> = String::try_from("Héllô").unwrap();
1447 let idx = s.find("lô").unwrap();
1448
1449 assert!(s.insert_str(idx, "p, í'm ").is_ok());
1450 assert_eq!(s, "Hélp, í'm lô");
1451
1452 assert!(s.insert_str(s.len(), "st").is_ok());
1453 assert_eq!(s, "Hélp, í'm lôst");
1454
1455 assert_eq!(s.len(), 17);
1456 assert_eq!("🦀".len(), 4);
1457 assert!(s.insert_str(0, "🦀").is_err());
1458 assert_eq!(s, "Hélp, í'm lôst");
1459 }
1460
1461 #[test]
1462 #[should_panic = "index must be a char boundary"]
1463 fn insert_str_at_non_char_boundary_panics() {
1464 let mut s: String<8> = String::try_from("é").unwrap();
1465 _ = s.insert_str(1, "a");
1466 }
1467
1468 #[test]
1469 #[should_panic = "index must be a char boundary"]
1470 fn insert_str_beyond_length_panics() {
1471 let mut s: String<8> = String::try_from("a").unwrap();
1472 _ = s.insert_str(2, "a");
1473 }
1474
1475 #[test]
1476 #[cfg(feature = "zeroize")]
1477 fn test_string_zeroize() {
1478 use zeroize::Zeroize;
1479
1480 let mut s: String<32> = String::try_from("sensitive_password").unwrap();
1481
1482 assert_eq!(s.as_str(), "sensitive_password");
1483 assert!(!s.is_empty());
1484 assert_eq!(s.len(), 18);
1485
1486 s.truncate(9);
1487 assert_eq!(s.as_str(), "sensitive");
1488 assert_eq!(s.len(), 9);
1489
1490 s.zeroize();
1492
1493 assert_eq!(s.len(), 0);
1494 assert!(s.is_empty());
1495 }
1496}