2 use std::collections::TryReserveError::*;
4 use std::{isize, usize};
6 pub trait IntoCow<'a, B: ?Sized>
10 fn into_cow(self) -> Cow<'a, B>;
13 impl<'a> IntoCow<'a, str> for String {
14 fn into_cow(self) -> Cow<'a, str> {
19 impl<'a> IntoCow<'a, str> for &'a str {
20 fn into_cow(self) -> Cow<'a, str> {
27 let owned: Option<std::string::String> = "string".parse().ok();
28 assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
32 fn test_from_cow_str() {
33 assert_eq!(String::from(Cow::Borrowed("string")), "string");
34 assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
38 fn test_unsized_to_string() {
40 let _: String = (*s).to_string();
45 let xs = b"hello".to_vec();
46 assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
48 let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
49 assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam"));
51 let xs = b"hello\xFF".to_vec();
52 let err = String::from_utf8(xs).unwrap_err();
53 assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
57 fn test_from_utf8_lossy() {
59 let ys: Cow<'_, str> = "hello".into_cow();
60 assert_eq!(String::from_utf8_lossy(xs), ys);
62 let xs = "ศไทย中华Việt Nam".as_bytes();
63 let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow();
64 assert_eq!(String::from_utf8_lossy(xs), ys);
66 let xs = b"Hello\xC2 There\xFF Goodbye";
68 String::from_utf8_lossy(xs),
69 String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()
72 let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
74 String::from_utf8_lossy(xs),
75 String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()
78 let xs = b"\xF5foo\xF5\x80bar";
80 String::from_utf8_lossy(xs),
81 String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()
84 let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
86 String::from_utf8_lossy(xs),
87 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()
90 let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
92 String::from_utf8_lossy(xs),
93 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()
96 let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
98 String::from_utf8_lossy(xs),
99 String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()
103 let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
105 String::from_utf8_lossy(xs),
106 String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()
111 fn test_from_utf16() {
114 String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
116 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39,
117 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a,
121 String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
123 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32,
124 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a,
128 String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
130 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11,
131 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800,
132 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a,
136 String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
138 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b,
139 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88,
140 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801,
141 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86,
145 // Issue #12318, even-numbered non-BMP planes
146 (String::from("\u{20000}"), vec![0xD840, 0xDC00]),
150 let (s, u) = (*p).clone();
151 let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
152 let u_as_string = String::from_utf16(&u).unwrap();
154 assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
155 assert_eq!(s_as_utf16, u);
157 assert_eq!(u_as_string, s);
158 assert_eq!(String::from_utf16_lossy(&u), s);
160 assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
161 assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
166 fn test_utf16_invalid() {
167 // completely positive cases tested above.
169 assert!(String::from_utf16(&[0xD800]).is_err());
171 assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
174 assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
177 assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
181 fn test_from_utf16_lossy() {
182 // completely positive cases tested above.
184 assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
186 assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}"));
189 assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
193 String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
194 String::from("\u{FFFD}𐒋\u{FFFD}")
199 fn test_push_bytes() {
200 let mut s = String::from("ABC");
202 let mv = s.as_mut_vec();
203 mv.extend_from_slice(&[b'D']);
205 assert_eq!(s, "ABCD");
210 let mut s = String::new();
212 assert_eq!(&s[0..], "");
214 assert_eq!(&s[0..], "abc");
215 s.push_str("ประเทศไทย中华Việt Nam");
216 assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
220 fn test_add_assign() {
221 let mut s = String::new();
223 assert_eq!(s.as_str(), "");
225 assert_eq!(s.as_str(), "abc");
226 s += "ประเทศไทย中华Việt Nam";
227 assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
232 let mut data = String::from("ประเทศไทย中");
234 data.push('b'); // 1 byte
235 data.push('¢'); // 2 byte
236 data.push('€'); // 3 byte
237 data.push('𤭢'); // 4 byte
238 assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
243 let mut data = String::from("ประเทศไทย中华b¢€𤭢");
244 assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
245 assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
246 assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
247 assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
248 assert_eq!(data.pop().unwrap(), '华');
249 assert_eq!(data, "ประเทศไทย中");
253 fn test_split_off_empty() {
254 let orig = "Hello, world!";
255 let mut split = String::from(orig);
256 let empty: String = split.split_off(orig.len());
257 assert!(empty.is_empty());
262 fn test_split_off_past_end() {
263 let orig = "Hello, world!";
264 let mut split = String::from(orig);
265 split.split_off(orig.len() + 1);
270 fn test_split_off_mid_char() {
271 let mut orig = String::from("山");
276 fn test_split_off_ascii() {
277 let mut ab = String::from("ABCD");
278 let cd = ab.split_off(2);
279 assert_eq!(ab, "AB");
280 assert_eq!(cd, "CD");
284 fn test_split_off_unicode() {
285 let mut nihon = String::from("日本語");
286 let go = nihon.split_off("日本".len());
287 assert_eq!(nihon, "日本");
292 fn test_str_truncate() {
293 let mut s = String::from("12345");
295 assert_eq!(s, "12345");
297 assert_eq!(s, "123");
301 let mut s = String::from("12345");
310 fn test_str_truncate_invalid_len() {
311 let mut s = String::from("12345");
313 assert_eq!(s, "12345");
318 fn test_str_truncate_split_codepoint() {
319 let mut s = String::from("\u{FC}"); // ü
324 fn test_str_clear() {
325 let mut s = String::from("12345");
327 assert_eq!(s.len(), 0);
333 let a = String::from("12345");
336 assert_eq!(b.len(), 7);
337 assert_eq!(b, "1234522");
342 let mut s = "ศไทย中华Việt Nam; foobar".to_string();
343 assert_eq!(s.remove(0), 'ศ');
344 assert_eq!(s.len(), 33);
345 assert_eq!(s, "ไทย中华Việt Nam; foobar");
346 assert_eq!(s.remove(17), 'ệ');
347 assert_eq!(s, "ไทย中华Vit Nam; foobar");
353 "ศ".to_string().remove(1);
358 let mut s = String::from("α_β_γ");
361 assert_eq!(s, "α_β_γ");
363 s.retain(|c| c != '_');
364 assert_eq!(s, "αβγ");
366 s.retain(|c| c != 'β');
369 s.retain(|c| c == 'α');
378 let mut s = "foobar".to_string();
380 assert_eq!(s, "ệfoobar");
382 assert_eq!(s, "ệfooยbar");
388 "".to_string().insert(1, 't');
393 "ệ".to_string().insert(1, 't');
398 let s = "foobar".to_string();
399 assert_eq!("foobar", &s[..]);
400 assert_eq!("foo", &s[..3]);
401 assert_eq!("bar", &s[3..]);
402 assert_eq!("oob", &s[1..4]);
406 fn test_simple_types() {
407 assert_eq!(1.to_string(), "1");
408 assert_eq!((-1).to_string(), "-1");
409 assert_eq!(200.to_string(), "200");
410 assert_eq!(2.to_string(), "2");
411 assert_eq!(true.to_string(), "true");
412 assert_eq!(false.to_string(), "false");
413 assert_eq!(("hi".to_string()).to_string(), "hi");
418 let x: Vec<i32> = vec![];
419 assert_eq!(format!("{:?}", x), "[]");
420 assert_eq!(format!("{:?}", vec![1]), "[1]");
421 assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
422 assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
426 fn test_from_iterator() {
427 let s = "ศไทย中华Việt Nam".to_string();
431 let a: String = s.chars().collect();
434 let mut b = t.to_string();
438 let c: String = vec![t, u].into_iter().collect();
441 let mut d = t.to_string();
448 let mut s = String::from("αβγ");
449 assert_eq!(s.drain(2..4).collect::<String>(), "β");
452 let mut t = String::from("abcd");
454 assert_eq!(t, "abcd");
456 assert_eq!(t, "bcd");
458 assert_eq!(t, "bcd");
464 fn test_replace_range() {
465 let mut s = "Hello, world!".to_owned();
466 s.replace_range(7..12, "世界");
467 assert_eq!(s, "Hello, 世界!");
472 fn test_replace_range_char_boundary() {
473 let mut s = "Hello, 世界!".to_owned();
474 s.replace_range(..8, "");
478 fn test_replace_range_inclusive_range() {
479 let mut v = String::from("12345");
480 v.replace_range(2..=3, "789");
481 assert_eq!(v, "127895");
482 v.replace_range(1..=2, "A");
483 assert_eq!(v, "1A895");
488 fn test_replace_range_out_of_bounds() {
489 let mut s = String::from("12345");
490 s.replace_range(5..6, "789");
495 fn test_replace_range_inclusive_out_of_bounds() {
496 let mut s = String::from("12345");
497 s.replace_range(5..=5, "789");
501 fn test_replace_range_empty() {
502 let mut s = String::from("12345");
503 s.replace_range(1..2, "");
504 assert_eq!(s, "1345");
508 fn test_replace_range_unbounded() {
509 let mut s = String::from("12345");
510 s.replace_range(.., "");
515 fn test_extend_ref() {
516 let mut a = "foo".to_string();
517 a.extend(&['b', 'a', 'r']);
519 assert_eq!(&a, "foobar");
523 fn test_into_boxed_str() {
524 let xs = String::from("hello my name is bob");
525 let ys = xs.into_boxed_str();
526 assert_eq!(&*ys, "hello my name is bob");
530 fn test_reserve_exact() {
531 // This is all the same as test_reserve
533 let mut s = String::new();
534 assert_eq!(s.capacity(), 0);
537 assert!(s.capacity() >= 2);
543 assert!(s.capacity() >= 16);
545 assert!(s.capacity() >= 32);
550 assert!(s.capacity() >= 33)
554 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
555 fn test_try_reserve() {
556 // These are the interesting cases:
557 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
558 // * > isize::MAX should always fail
559 // * On 16/32-bit should CapacityOverflow
560 // * On 64-bit should OOM
561 // * overflow may trigger when adding `len` to `cap` (in number of elements)
562 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
564 const MAX_CAP: usize = isize::MAX as usize;
565 const MAX_USIZE: usize = usize::MAX;
567 // On 16/32-bit, we check that allocations don't exceed isize::MAX,
568 // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
569 // Any platform that succeeds for these requests is technically broken with
570 // ptr::offset because LLVM is the worst.
571 let guards_against_isize = size_of::<usize>() < 8;
574 // Note: basic stuff is checked by test_reserve
575 let mut empty_string: String = String::new();
577 // Check isize::MAX doesn't count as an overflow
578 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
579 panic!("isize::MAX shouldn't trigger an overflow!");
581 // Play it again, frank! (just to be sure)
582 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
583 panic!("isize::MAX shouldn't trigger an overflow!");
586 if guards_against_isize {
587 // Check isize::MAX + 1 does count as overflow
588 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) {
590 panic!("isize::MAX + 1 should trigger an overflow!")
593 // Check usize::MAX does count as overflow
594 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) {
596 panic!("usize::MAX should trigger an overflow!")
599 // Check isize::MAX + 1 is an OOM
600 if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
602 panic!("isize::MAX + 1 should trigger an OOM!")
605 // Check usize::MAX is an OOM
606 if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
608 panic!("usize::MAX should trigger an OOM!")
614 // Same basic idea, but with non-zero len
615 let mut ten_bytes: String = String::from("0123456789");
617 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
618 panic!("isize::MAX shouldn't trigger an overflow!");
620 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
621 panic!("isize::MAX shouldn't trigger an overflow!");
623 if guards_against_isize {
624 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
626 panic!("isize::MAX + 1 should trigger an overflow!");
629 if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
631 panic!("isize::MAX + 1 should trigger an OOM!")
634 // Should always overflow in the add-to-len
635 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
637 panic!("usize::MAX should trigger an overflow!")
643 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
644 fn test_try_reserve_exact() {
645 // This is exactly the same as test_try_reserve with the method changed.
646 // See that test for comments.
648 const MAX_CAP: usize = isize::MAX as usize;
649 const MAX_USIZE: usize = usize::MAX;
651 let guards_against_isize = size_of::<usize>() < 8;
654 let mut empty_string: String = String::new();
656 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
657 panic!("isize::MAX shouldn't trigger an overflow!");
659 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
660 panic!("isize::MAX shouldn't trigger an overflow!");
663 if guards_against_isize {
664 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) {
666 panic!("isize::MAX + 1 should trigger an overflow!")
669 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
671 panic!("usize::MAX should trigger an overflow!")
674 if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
676 panic!("isize::MAX + 1 should trigger an OOM!")
679 if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
681 panic!("usize::MAX should trigger an OOM!")
687 let mut ten_bytes: String = String::from("0123456789");
689 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
690 panic!("isize::MAX shouldn't trigger an overflow!");
692 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
693 panic!("isize::MAX shouldn't trigger an overflow!");
695 if guards_against_isize {
696 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
698 panic!("isize::MAX + 1 should trigger an overflow!");
701 if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
703 panic!("isize::MAX + 1 should trigger an OOM!")
706 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
708 panic!("usize::MAX should trigger an overflow!")