2 use std::collections::TryReserveError::*;
4 use std::ops::Bound::*;
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.as_bytes(), b"hello\xff");
54 let err_clone = err.clone();
55 assert_eq!(err, err_clone);
56 assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
57 assert_eq!(err_clone.utf8_error().valid_up_to(), 5);
61 fn test_from_utf8_lossy() {
63 let ys: Cow<'_, str> = "hello".into_cow();
64 assert_eq!(String::from_utf8_lossy(xs), ys);
66 let xs = "ศไทย中华Việt Nam".as_bytes();
67 let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow();
68 assert_eq!(String::from_utf8_lossy(xs), ys);
70 let xs = b"Hello\xC2 There\xFF Goodbye";
72 String::from_utf8_lossy(xs),
73 String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()
76 let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
78 String::from_utf8_lossy(xs),
79 String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()
82 let xs = b"\xF5foo\xF5\x80bar";
84 String::from_utf8_lossy(xs),
85 String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()
88 let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
90 String::from_utf8_lossy(xs),
91 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()
94 let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
96 String::from_utf8_lossy(xs),
97 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()
100 let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
102 String::from_utf8_lossy(xs),
103 String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()
107 let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
109 String::from_utf8_lossy(xs),
110 String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()
115 fn test_from_utf16() {
118 String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
120 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39,
121 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a,
125 String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
127 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32,
128 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a,
132 String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
134 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11,
135 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800,
136 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a,
140 String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
142 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b,
143 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88,
144 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801,
145 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86,
149 // Issue #12318, even-numbered non-BMP planes
150 (String::from("\u{20000}"), vec![0xD840, 0xDC00]),
154 let (s, u) = (*p).clone();
155 let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
156 let u_as_string = String::from_utf16(&u).unwrap();
158 assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
159 assert_eq!(s_as_utf16, u);
161 assert_eq!(u_as_string, s);
162 assert_eq!(String::from_utf16_lossy(&u), s);
164 assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
165 assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
170 fn test_utf16_invalid() {
171 // completely positive cases tested above.
173 assert!(String::from_utf16(&[0xD800]).is_err());
175 assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
178 assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
181 assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
185 fn test_from_utf16_lossy() {
186 // completely positive cases tested above.
188 assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
190 assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}"));
193 assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
197 String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
198 String::from("\u{FFFD}𐒋\u{FFFD}")
203 fn test_push_bytes() {
204 let mut s = String::from("ABC");
206 let mv = s.as_mut_vec();
207 mv.extend_from_slice(&[b'D']);
209 assert_eq!(s, "ABCD");
214 let mut s = String::new();
216 assert_eq!(&s[0..], "");
218 assert_eq!(&s[0..], "abc");
219 s.push_str("ประเทศไทย中华Việt Nam");
220 assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
224 fn test_add_assign() {
225 let mut s = String::new();
227 assert_eq!(s.as_str(), "");
229 assert_eq!(s.as_str(), "abc");
230 s += "ประเทศไทย中华Việt Nam";
231 assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
236 let mut data = String::from("ประเทศไทย中");
238 data.push('b'); // 1 byte
239 data.push('¢'); // 2 byte
240 data.push('€'); // 3 byte
241 data.push('𤭢'); // 4 byte
242 assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
247 let mut data = String::from("ประเทศไทย中华b¢€𤭢");
248 assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
249 assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
250 assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
251 assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
252 assert_eq!(data.pop().unwrap(), '华');
253 assert_eq!(data, "ประเทศไทย中");
257 fn test_split_off_empty() {
258 let orig = "Hello, world!";
259 let mut split = String::from(orig);
260 let empty: String = split.split_off(orig.len());
261 assert!(empty.is_empty());
266 fn test_split_off_past_end() {
267 let orig = "Hello, world!";
268 let mut split = String::from(orig);
269 let _ = split.split_off(orig.len() + 1);
274 fn test_split_off_mid_char() {
275 let mut orig = String::from("山");
276 let _ = orig.split_off(1);
280 fn test_split_off_ascii() {
281 let mut ab = String::from("ABCD");
282 let orig_capacity = ab.capacity();
283 let cd = ab.split_off(2);
284 assert_eq!(ab, "AB");
285 assert_eq!(cd, "CD");
286 assert_eq!(ab.capacity(), orig_capacity);
290 fn test_split_off_unicode() {
291 let mut nihon = String::from("日本語");
292 let orig_capacity = nihon.capacity();
293 let go = nihon.split_off("日本".len());
294 assert_eq!(nihon, "日本");
296 assert_eq!(nihon.capacity(), orig_capacity);
300 fn test_str_truncate() {
301 let mut s = String::from("12345");
303 assert_eq!(s, "12345");
305 assert_eq!(s, "123");
309 let mut s = String::from("12345");
318 fn test_str_truncate_invalid_len() {
319 let mut s = String::from("12345");
321 assert_eq!(s, "12345");
326 fn test_str_truncate_split_codepoint() {
327 let mut s = String::from("\u{FC}"); // ü
332 fn test_str_clear() {
333 let mut s = String::from("12345");
335 assert_eq!(s.len(), 0);
341 let a = String::from("12345");
344 assert_eq!(b.len(), 7);
345 assert_eq!(b, "1234522");
350 let mut s = "ศไทย中华Việt Nam; foobar".to_string();
351 assert_eq!(s.remove(0), 'ศ');
352 assert_eq!(s.len(), 33);
353 assert_eq!(s, "ไทย中华Việt Nam; foobar");
354 assert_eq!(s.remove(17), 'ệ');
355 assert_eq!(s, "ไทย中华Vit Nam; foobar");
361 "ศ".to_string().remove(1);
366 let mut s = String::from("α_β_γ");
369 assert_eq!(s, "α_β_γ");
371 s.retain(|c| c != '_');
372 assert_eq!(s, "αβγ");
374 s.retain(|c| c != 'β');
377 s.retain(|c| c == 'α');
386 let mut s = "foobar".to_string();
388 assert_eq!(s, "ệfoobar");
390 assert_eq!(s, "ệfooยbar");
396 "".to_string().insert(1, 't');
401 "ệ".to_string().insert(1, 't');
406 let s = "foobar".to_string();
407 assert_eq!("foobar", &s[..]);
408 assert_eq!("foo", &s[..3]);
409 assert_eq!("bar", &s[3..]);
410 assert_eq!("oob", &s[1..4]);
414 fn test_simple_types() {
415 assert_eq!(1.to_string(), "1");
416 assert_eq!((-1).to_string(), "-1");
417 assert_eq!(200.to_string(), "200");
418 assert_eq!(2.to_string(), "2");
419 assert_eq!(true.to_string(), "true");
420 assert_eq!(false.to_string(), "false");
421 assert_eq!(("hi".to_string()).to_string(), "hi");
426 let x: Vec<i32> = vec![];
427 assert_eq!(format!("{:?}", x), "[]");
428 assert_eq!(format!("{:?}", vec![1]), "[1]");
429 assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
430 assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
434 fn test_from_iterator() {
435 let s = "ศไทย中华Việt Nam".to_string();
439 let a: String = s.chars().collect();
442 let mut b = t.to_string();
446 let c: String = vec![t, u].into_iter().collect();
449 let mut d = t.to_string();
456 let mut s = String::from("αβγ");
457 assert_eq!(s.drain(2..4).collect::<String>(), "β");
460 let mut t = String::from("abcd");
462 assert_eq!(t, "abcd");
464 assert_eq!(t, "bcd");
466 assert_eq!(t, "bcd");
473 fn test_drain_start_overflow() {
474 let mut s = String::from("abc");
475 s.drain((Excluded(usize::MAX), Included(0)));
480 fn test_drain_end_overflow() {
481 let mut s = String::from("abc");
482 s.drain((Included(0), Included(usize::MAX)));
486 fn test_replace_range() {
487 let mut s = "Hello, world!".to_owned();
488 s.replace_range(7..12, "世界");
489 assert_eq!(s, "Hello, 世界!");
494 fn test_replace_range_char_boundary() {
495 let mut s = "Hello, 世界!".to_owned();
496 s.replace_range(..8, "");
500 fn test_replace_range_inclusive_range() {
501 let mut v = String::from("12345");
502 v.replace_range(2..=3, "789");
503 assert_eq!(v, "127895");
504 v.replace_range(1..=2, "A");
505 assert_eq!(v, "1A895");
510 fn test_replace_range_out_of_bounds() {
511 let mut s = String::from("12345");
512 s.replace_range(5..6, "789");
517 fn test_replace_range_inclusive_out_of_bounds() {
518 let mut s = String::from("12345");
519 s.replace_range(5..=5, "789");
524 fn test_replace_range_start_overflow() {
525 let mut s = String::from("123");
526 s.replace_range((Excluded(usize::MAX), Included(0)), "");
531 fn test_replace_range_end_overflow() {
532 let mut s = String::from("456");
533 s.replace_range((Included(0), Included(usize::MAX)), "");
537 fn test_replace_range_empty() {
538 let mut s = String::from("12345");
539 s.replace_range(1..2, "");
540 assert_eq!(s, "1345");
544 fn test_replace_range_unbounded() {
545 let mut s = String::from("12345");
546 s.replace_range(.., "");
551 fn test_extend_ref() {
552 let mut a = "foo".to_string();
553 a.extend(&['b', 'a', 'r']);
555 assert_eq!(&a, "foobar");
559 fn test_into_boxed_str() {
560 let xs = String::from("hello my name is bob");
561 let ys = xs.into_boxed_str();
562 assert_eq!(&*ys, "hello my name is bob");
566 fn test_reserve_exact() {
567 // This is all the same as test_reserve
569 let mut s = String::new();
570 assert_eq!(s.capacity(), 0);
573 assert!(s.capacity() >= 2);
579 assert!(s.capacity() >= 16);
581 assert!(s.capacity() >= 32);
586 assert!(s.capacity() >= 33)
590 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
591 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
592 fn test_try_reserve() {
593 // These are the interesting cases:
594 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
595 // * > isize::MAX should always fail
596 // * On 16/32-bit should CapacityOverflow
597 // * On 64-bit should OOM
598 // * overflow may trigger when adding `len` to `cap` (in number of elements)
599 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
601 const MAX_CAP: usize = isize::MAX as usize;
602 const MAX_USIZE: usize = usize::MAX;
604 // On 16/32-bit, we check that allocations don't exceed isize::MAX,
605 // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
606 // Any platform that succeeds for these requests is technically broken with
607 // ptr::offset because LLVM is the worst.
608 let guards_against_isize = size_of::<usize>() < 8;
611 // Note: basic stuff is checked by test_reserve
612 let mut empty_string: String = String::new();
614 // Check isize::MAX doesn't count as an overflow
615 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
616 panic!("isize::MAX shouldn't trigger an overflow!");
618 // Play it again, frank! (just to be sure)
619 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
620 panic!("isize::MAX shouldn't trigger an overflow!");
623 if guards_against_isize {
624 // Check isize::MAX + 1 does count as overflow
625 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) {
627 panic!("isize::MAX + 1 should trigger an overflow!")
630 // Check usize::MAX does count as overflow
631 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) {
633 panic!("usize::MAX should trigger an overflow!")
636 // Check isize::MAX + 1 is an OOM
637 if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
639 panic!("isize::MAX + 1 should trigger an OOM!")
642 // Check usize::MAX is an OOM
643 if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
645 panic!("usize::MAX should trigger an OOM!")
651 // Same basic idea, but with non-zero len
652 let mut ten_bytes: String = String::from("0123456789");
654 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
655 panic!("isize::MAX shouldn't trigger an overflow!");
657 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
658 panic!("isize::MAX shouldn't trigger an overflow!");
660 if guards_against_isize {
661 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
663 panic!("isize::MAX + 1 should trigger an overflow!");
666 if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
668 panic!("isize::MAX + 1 should trigger an OOM!")
671 // Should always overflow in the add-to-len
672 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
674 panic!("usize::MAX should trigger an overflow!")
680 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
681 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
682 fn test_try_reserve_exact() {
683 // This is exactly the same as test_try_reserve with the method changed.
684 // See that test for comments.
686 const MAX_CAP: usize = isize::MAX as usize;
687 const MAX_USIZE: usize = usize::MAX;
689 let guards_against_isize = size_of::<usize>() < 8;
692 let mut empty_string: String = String::new();
694 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
695 panic!("isize::MAX shouldn't trigger an overflow!");
697 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
698 panic!("isize::MAX shouldn't trigger an overflow!");
701 if guards_against_isize {
702 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) {
704 panic!("isize::MAX + 1 should trigger an overflow!")
707 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
709 panic!("usize::MAX should trigger an overflow!")
712 if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
714 panic!("isize::MAX + 1 should trigger an OOM!")
717 if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
719 panic!("usize::MAX should trigger an OOM!")
725 let mut ten_bytes: String = String::from("0123456789");
727 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
728 panic!("isize::MAX shouldn't trigger an overflow!");
730 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
731 panic!("isize::MAX shouldn't trigger an overflow!");
733 if guards_against_isize {
734 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
736 panic!("isize::MAX + 1 should trigger an overflow!");
739 if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
741 panic!("isize::MAX + 1 should trigger an OOM!")
744 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
746 panic!("usize::MAX should trigger an overflow!")
752 fn test_from_char() {
753 assert_eq!(String::from('a'), 'a'.to_string());
754 let s: String = 'x'.into();
755 assert_eq!(s, 'x'.to_string());
759 fn test_str_concat() {
760 let a: String = "hello".to_string();
761 let b: String = "world".to_string();
762 let s: String = format!("{}{}", a, b);
763 assert_eq!(s.as_bytes()[9], 'd' as u8);