2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::from_utf8;
9 assert!("foo" <= "foo");
10 assert_ne!("foo", "bar");
15 assert_eq!("hello".find('l'), Some(2));
16 assert_eq!("hello".find(|c: char| c == 'o'), Some(4));
17 assert!("hello".find('x').is_none());
18 assert!("hello".find(|c: char| c == 'x').is_none());
19 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
20 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
25 assert_eq!("hello".rfind('l'), Some(3));
26 assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4));
27 assert!("hello".rfind('x').is_none());
28 assert!("hello".rfind(|c: char| c == 'x').is_none());
29 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
30 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
36 let s: String = empty.chars().collect();
38 let data = "ประเทศไทย中";
39 let s: String = data.chars().collect();
44 fn test_into_bytes() {
45 let data = String::from("asdf");
46 let buf = data.into_bytes();
47 assert_eq!(buf, b"asdf");
53 assert_eq!("".find(""), Some(0));
54 assert!("banana".find("apple pie").is_none());
57 assert_eq!(data[0..6].find("ab"), Some(0));
58 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
59 assert!(data[2..4].find("ab").is_none());
61 let string = "ประเทศไทย中华Việt Nam";
62 let mut data = String::from(string);
63 data.push_str(string);
64 assert!(data.find("ไท华").is_none());
65 assert_eq!(data[0..43].find(""), Some(0));
66 assert_eq!(data[6..43].find(""), Some(6 - 6));
68 assert_eq!(data[0..43].find("ประ"), Some(0));
69 assert_eq!(data[0..43].find("ทศไ"), Some(12));
70 assert_eq!(data[0..43].find("ย中"), Some(24));
71 assert_eq!(data[0..43].find("iệt"), Some(34));
72 assert_eq!(data[0..43].find("Nam"), Some(40));
74 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
75 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
76 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
77 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
78 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
80 // find every substring -- assert that it finds it, or an earlier occurrence.
81 let string = "Việt Namacbaabcaabaaba";
82 for (i, ci) in string.char_indices() {
83 let ip = i + ci.len_utf8();
84 for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) {
85 let pat = &string[i..ip + j];
86 assert!(match string.find(pat) {
90 assert!(match string.rfind(pat) {
98 fn s(x: &str) -> String {
102 macro_rules! test_concat {
103 ($expected: expr, $string: expr) => {{
104 let s: String = $string.concat();
105 assert_eq!($expected, s);
110 fn test_concat_for_different_types() {
111 test_concat!("ab", vec![s("a"), s("b")]);
112 test_concat!("ab", vec!["a", "b"]);
116 fn test_concat_for_different_lengths() {
117 let empty: &[&str] = &[];
118 test_concat!("", empty);
119 test_concat!("a", ["a"]);
120 test_concat!("ab", ["a", "b"]);
121 test_concat!("abc", ["", "a", "bc"]);
124 macro_rules! test_join {
125 ($expected: expr, $string: expr, $delim: expr) => {{
126 let s = $string.join($delim);
127 assert_eq!($expected, s);
132 fn test_join_for_different_types() {
133 test_join!("a-b", ["a", "b"], "-");
134 let hyphen = "-".to_string();
135 test_join!("a-b", [s("a"), s("b")], &*hyphen);
136 test_join!("a-b", vec!["a", "b"], &*hyphen);
137 test_join!("a-b", &*vec!["a", "b"], "-");
138 test_join!("a-b", vec![s("a"), s("b")], "-");
142 fn test_join_for_different_lengths() {
143 let empty: &[&str] = &[];
144 test_join!("", empty, "-");
145 test_join!("a", ["a"], "-");
146 test_join!("a-b", ["a", "b"], "-");
147 test_join!("-a-bc", ["", "a", "bc"], "-");
150 // join has fast paths for small separators up to 4 bytes
151 // this tests the slow paths.
153 fn test_join_for_different_lengths_with_long_separator() {
154 assert_eq!("~~~~~".len(), 15);
156 let empty: &[&str] = &[];
157 test_join!("", empty, "~~~~~");
158 test_join!("a", ["a"], "~~~~~");
159 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
160 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
164 #[cfg_attr(miri, ignore)] // Miri is too slow
165 fn test_unsafe_slice() {
166 assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) });
167 assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) });
168 assert_eq!("", unsafe { "abc".get_unchecked(1..1) });
169 fn a_million_letter_a() -> String {
171 let mut rs = String::new();
173 rs.push_str("aaaaaaaaaa");
178 fn half_a_million_letter_a() -> String {
180 let mut rs = String::new();
182 rs.push_str("aaaaa");
187 let letters = a_million_letter_a();
188 assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) });
192 fn test_starts_with() {
193 assert!("".starts_with(""));
194 assert!("abc".starts_with(""));
195 assert!("abc".starts_with("a"));
196 assert!(!"a".starts_with("abc"));
197 assert!(!"".starts_with("abc"));
198 assert!(!"ödd".starts_with("-"));
199 assert!("ödd".starts_with("öd"));
203 fn test_ends_with() {
204 assert!("".ends_with(""));
205 assert!("abc".ends_with(""));
206 assert!("abc".ends_with("c"));
207 assert!(!"a".ends_with("abc"));
208 assert!(!"".ends_with("abc"));
209 assert!(!"ddö".ends_with("-"));
210 assert!("ddö".ends_with("dö"));
215 assert!("".is_empty());
216 assert!(!"a".is_empty());
221 assert_eq!("".replacen('a', "b", 5), "");
222 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
223 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
226 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
227 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
228 assert_eq!(" test test ".replacen(test, "", 5), " ");
230 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
236 assert_eq!("".replace(a, "b"), "");
237 assert_eq!("a".replace(a, "b"), "b");
238 assert_eq!("ab".replace(a, "b"), "bb");
240 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
241 assert_eq!(" test test ".replace(test, ""), " ");
245 fn test_replace_2a() {
246 let data = "ประเทศไทย中华";
247 let repl = "دولة الكويت";
250 let a2 = "دولة الكويتทศไทย中华";
251 assert_eq!(data.replace(a, repl), a2);
255 fn test_replace_2b() {
256 let data = "ประเทศไทย中华";
257 let repl = "دولة الكويت";
260 let b2 = "ปรدولة الكويتทศไทย中华";
261 assert_eq!(data.replace(b, repl), b2);
265 fn test_replace_2c() {
266 let data = "ประเทศไทย中华";
267 let repl = "دولة الكويت";
270 let c2 = "ประเทศไทยدولة الكويت";
271 assert_eq!(data.replace(c, repl), c2);
275 fn test_replace_2d() {
276 let data = "ประเทศไทย中华";
277 let repl = "دولة الكويت";
280 assert_eq!(data.replace(d, repl), data);
284 fn test_replace_pattern() {
285 let data = "abcdαβγδabcdαβγδ";
286 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
287 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
288 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
289 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
292 // The current implementation of SliceIndex fails to handle methods
293 // orthogonally from range types; therefore, it is worth testing
294 // all of the indexing operations on each input.
296 // Test a slicing operation **that should succeed,**
297 // testing it on all of the indexing methods.
299 // This is not suitable for testing failure on invalid inputs.
300 macro_rules! assert_range_eq {
301 ($s:expr, $range:expr, $expected:expr) => {
302 let mut s: String = $s.to_owned();
303 let mut expected: String = $expected.to_owned();
306 let expected: &str = &expected;
308 assert_eq!(&s[$range], expected, "(in assertion for: index)");
309 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
312 s.get_unchecked($range),
314 "(in assertion for: get_unchecked)",
319 let s: &mut str = &mut s;
320 let expected: &mut str = &mut expected;
322 assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
325 Some(&mut expected[..]),
326 "(in assertion for: get_mut)",
330 s.get_unchecked_mut($range),
332 "(in assertion for: get_unchecked_mut)",
339 // Make sure the macro can actually detect bugs,
340 // because if it can't, then what are we even doing here?
342 // (Be aware this only demonstrates the ability to detect bugs
343 // in the FIRST method that panics, as the macro is not designed
344 // to be used in `should_panic`)
346 #[should_panic(expected = "out of bounds")]
347 fn assert_range_eq_can_fail_by_panic() {
348 assert_range_eq!("abc", 0..5, "abc");
351 // (Be aware this only demonstrates the ability to detect bugs
352 // in the FIRST method it calls, as the macro is not designed
353 // to be used in `should_panic`)
355 #[should_panic(expected = "==")]
356 fn assert_range_eq_can_fail_by_inequality() {
357 assert_range_eq!("abc", 0..2, "abc");
360 // Generates test cases for bad index operations.
362 // This generates `should_panic` test cases for Index/IndexMut
363 // and `None` test cases for get/get_mut.
364 macro_rules! panic_cases {
366 in mod $case_name:ident {
371 // a similar input for which DATA[input] succeeds, and the corresponding
372 // output str. This helps validate "critical points" where an input range
373 // straddles the boundary between valid and invalid.
374 // (such as the input `len..len`, which is just barely valid)
376 good: data[$good:expr] == $output:expr;
379 bad: data[$bad:expr];
380 message: $expect_msg:expr; // must be a literal
386 let mut v: String = $data.into();
388 $( assert_range_eq!(v, $good, $output); )*
392 assert_eq!(v.get($bad), None, "(in None assertion for get)");
396 let v: &mut str = &mut v;
397 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
402 #[should_panic(expected = $expect_msg)]
404 let v: String = $data.into();
410 #[should_panic(expected = $expect_msg)]
411 fn index_mut_fail() {
412 let mut v: String = $data.into();
413 let v: &mut str = &mut v;
414 let _v = &mut v[$bad];
422 assert_range_eq!("abc", .., "abc");
424 assert_range_eq!("abc", 0..2, "ab");
425 assert_range_eq!("abc", 0..=1, "ab");
426 assert_range_eq!("abc", ..2, "ab");
427 assert_range_eq!("abc", ..=1, "ab");
429 assert_range_eq!("abc", 1..3, "bc");
430 assert_range_eq!("abc", 1..=2, "bc");
431 assert_range_eq!("abc", 1..1, "");
432 assert_range_eq!("abc", 1..=0, "");
436 fn simple_unicode() {
438 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
440 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
441 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
442 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
443 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
445 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
446 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
447 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
449 let data = "ประเทศไทย中华";
450 assert_range_eq!(data, 0..3, "ป");
451 assert_range_eq!(data, 3..6, "ร");
452 assert_range_eq!(data, 3..3, "");
453 assert_range_eq!(data, 30..33, "华");
465 let ss = "中华Việt Nam";
466 assert_range_eq!(ss, 3..6, "华");
467 assert_range_eq!(ss, 6..16, "Việt Nam");
468 assert_range_eq!(ss, 6..=15, "Việt Nam");
469 assert_range_eq!(ss, 6.., "Việt Nam");
471 assert_range_eq!(ss, 0..3, "中");
472 assert_range_eq!(ss, 3..7, "华V");
473 assert_range_eq!(ss, 3..=6, "华V");
474 assert_range_eq!(ss, 3..3, "");
475 assert_range_eq!(ss, 3..=2, "");
479 #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM
480 #[cfg_attr(miri, ignore)] // Miri is too slow
482 fn a_million_letter_x() -> String {
484 let mut rs = String::new();
486 rs.push_str("华华华华华华华华华华");
491 fn half_a_million_letter_x() -> String {
493 let mut rs = String::new();
495 rs.push_str("华华华华华");
500 let letters = a_million_letter_x();
501 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
506 fn test_slice_fail() {
511 in mod rangefrom_len {
513 good: data[6..] == "";
515 message: "out of bounds";
520 good: data[..6] == "abcdef";
522 message: "out of bounds";
525 in mod rangetoinclusive_len {
527 good: data[..=5] == "abcdef";
529 message: "out of bounds";
532 in mod range_len_len {
534 good: data[6..6] == "";
536 message: "out of bounds";
539 in mod rangeinclusive_len_len {
541 good: data[6..=5] == "";
543 message: "out of bounds";
548 in mod range_neg_width {
550 good: data[4..4] == "";
552 message: "begin <= end (4 <= 3)";
555 in mod rangeinclusive_neg_width {
557 good: data[4..=3] == "";
559 message: "begin <= end (4 <= 3)";
565 in mod rangeinclusive {
567 // note: using 0 specifically ensures that the result of overflowing is 0..0,
568 // so that `get` doesn't simply return None for the wrong reason.
569 bad: data[0..=usize::MAX];
570 message: "maximum usize";
573 in mod rangetoinclusive {
575 bad: data[..=usize::MAX];
576 message: "maximum usize";
582 const DATA: &str = "abcαβγ";
584 const BAD_START: usize = 4;
585 const GOOD_START: usize = 3;
586 const BAD_END: usize = 6;
587 const GOOD_END: usize = 7;
588 const BAD_END_INCL: usize = BAD_END - 1;
589 const GOOD_END_INCL: usize = GOOD_END - 1;
591 // it is especially important to test all of the different range types here
592 // because some of the logic may be duplicated as part of micro-optimizations
593 // to dodge unicode boundary checks on half-ranges.
597 bad: data[super::BAD_START..super::GOOD_END];
599 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
604 bad: data[super::GOOD_START..super::BAD_END];
606 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
611 bad: data[super::BAD_START..];
613 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
618 bad: data[..super::BAD_END];
620 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
623 in mod rangeinclusive_1 {
625 bad: data[super::BAD_START..=super::GOOD_END_INCL];
627 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
630 in mod rangeinclusive_2 {
632 bad: data[super::GOOD_START..=super::BAD_END_INCL];
634 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
637 in mod rangetoinclusive {
639 bad: data[..=super::BAD_END_INCL];
641 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
646 const LOREM_PARAGRAPH: &str = "\
647 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
648 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
649 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
650 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
651 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
654 // check the panic includes the prefix of the sliced string
656 #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
657 fn test_slice_fail_truncated_1() {
658 &LOREM_PARAGRAPH[..1024];
660 // check the truncation in the panic message
662 #[should_panic(expected = "luctus, im`[...]")]
663 fn test_slice_fail_truncated_2() {
664 &LOREM_PARAGRAPH[..1024];
669 fn test_str_slice_rangetoinclusive_ok() {
671 assert_eq!(&s[..=2], "abc");
672 assert_eq!(&s[..=4], "abcα");
677 fn test_str_slice_rangetoinclusive_notok() {
683 fn test_str_slicemut_rangetoinclusive_ok() {
684 let mut s = "abcαβγ".to_owned();
685 let s: &mut str = &mut s;
686 assert_eq!(&mut s[..=2], "abc");
687 assert_eq!(&mut s[..=4], "abcα");
692 fn test_str_slicemut_rangetoinclusive_notok() {
693 let mut s = "abcαβγ".to_owned();
694 let s: &mut str = &mut s;
699 fn test_is_char_boundary() {
700 let s = "ศไทย中华Việt Nam β-release 🐱123";
701 assert!(s.is_char_boundary(0));
702 assert!(s.is_char_boundary(s.len()));
703 assert!(!s.is_char_boundary(s.len() + 1));
704 for (i, ch) in s.char_indices() {
705 // ensure character locations are boundaries and continuation bytes are not
706 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
707 for j in 1..ch.len_utf8() {
709 !s.is_char_boundary(i + j),
710 "{} should not be a char boundary in {:?}",
719 fn test_trim_start_matches() {
720 let v: &[char] = &[];
721 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
722 let chars: &[char] = &['*', ' '];
723 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
724 assert_eq!(" *** *** ".trim_start_matches(chars), "");
725 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
727 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
728 let chars: &[char] = &['1', '2'];
729 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
730 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
734 fn test_trim_end_matches() {
735 let v: &[char] = &[];
736 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
737 let chars: &[char] = &['*', ' '];
738 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
739 assert_eq!(" *** *** ".trim_end_matches(chars), "");
740 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
742 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
743 let chars: &[char] = &['1', '2'];
744 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
745 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
749 fn test_trim_matches() {
750 let v: &[char] = &[];
751 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
752 let chars: &[char] = &['*', ' '];
753 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
754 assert_eq!(" *** *** ".trim_matches(chars), "");
755 assert_eq!("foo".trim_matches(chars), "foo");
757 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
758 let chars: &[char] = &['1', '2'];
759 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
760 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
764 fn test_trim_start() {
765 assert_eq!("".trim_start(), "");
766 assert_eq!("a".trim_start(), "a");
767 assert_eq!(" ".trim_start(), "");
768 assert_eq!(" blah".trim_start(), "blah");
769 assert_eq!(" \u{3000} wut".trim_start(), "wut");
770 assert_eq!("hey ".trim_start(), "hey ");
775 assert_eq!("".trim_end(), "");
776 assert_eq!("a".trim_end(), "a");
777 assert_eq!(" ".trim_end(), "");
778 assert_eq!("blah ".trim_end(), "blah");
779 assert_eq!("wut \u{3000} ".trim_end(), "wut");
780 assert_eq!(" hey".trim_end(), " hey");
785 assert_eq!("".trim(), "");
786 assert_eq!("a".trim(), "a");
787 assert_eq!(" ".trim(), "");
788 assert_eq!(" blah ".trim(), "blah");
789 assert_eq!("\nwut \u{3000} ".trim(), "wut");
790 assert_eq!(" hey dude ".trim(), "hey dude");
794 fn test_is_whitespace() {
795 assert!("".chars().all(|c| c.is_whitespace()));
796 assert!(" ".chars().all(|c| c.is_whitespace()));
797 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
798 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
799 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
804 // deny overlong encodings
805 assert!(from_utf8(&[0xc0, 0x80]).is_err());
806 assert!(from_utf8(&[0xc0, 0xae]).is_err());
807 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
808 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
809 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
810 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
811 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
814 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
815 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
817 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
818 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
819 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
820 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
821 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
822 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
823 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
824 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
828 fn from_utf8_mostly_ascii() {
829 // deny invalid bytes embedded in long stretches of ascii
831 let mut data = [0; 128];
833 assert!(from_utf8(&data).is_err());
835 assert!(from_utf8(&data).is_err());
840 fn from_utf8_error() {
842 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
843 let error = from_utf8($input).unwrap_err();
844 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
845 assert_eq!(error.error_len(), $expected_error_len);
848 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
849 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
850 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
851 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
852 test!(b"A\xC3\xA9 \xC2", 4, None);
853 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
854 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
855 test!(b"A\xC3\xA9 \xE0", 4, None);
856 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
857 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
858 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
859 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
860 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
861 test!(b"A\xC3\xA9 \xF1", 4, None);
862 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
863 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
864 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
865 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
866 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
873 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
874 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
877 assert_eq!("".as_bytes(), b);
878 assert_eq!("abc".as_bytes(), b"abc");
879 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
884 fn test_as_bytes_fail() {
885 // Don't double free. (I'm not sure if this exercises the
886 // original problem code path anymore.)
887 let s = String::from("");
888 let _bytes = s.as_bytes();
894 let buf = "hello".as_ptr();
896 assert_eq!(*buf.offset(0), b'h');
897 assert_eq!(*buf.offset(1), b'e');
898 assert_eq!(*buf.offset(2), b'l');
899 assert_eq!(*buf.offset(3), b'l');
900 assert_eq!(*buf.offset(4), b'o');
905 fn vec_str_conversions() {
906 let s1: String = String::from("All mimsy were the borogoves");
908 let v: Vec<u8> = s1.as_bytes().to_vec();
909 let s2: String = String::from(from_utf8(&v).unwrap());
915 let a: u8 = s1.as_bytes()[i];
916 let b: u8 = s2.as_bytes()[i];
924 assert!("abcde".contains("bcd"));
925 assert!("abcde".contains("abcd"));
926 assert!("abcde".contains("bcde"));
927 assert!("abcde".contains(""));
928 assert!("".contains(""));
929 assert!(!"abcde".contains("def"));
930 assert!(!"".contains("a"));
932 let data = "ประเทศไทย中华Việt Nam";
933 assert!(data.contains("ประเ"));
934 assert!(data.contains("ะเ"));
935 assert!(data.contains("中华"));
936 assert!(!data.contains("ไท华"));
940 fn test_contains_char() {
941 assert!("abc".contains('b'));
942 assert!("a".contains('a'));
943 assert!(!"abc".contains('d'));
944 assert!(!"".contains('a'));
949 let s = "ศไทย中华Việt Nam";
950 for (index, _) in s.char_indices() {
951 let (a, b) = s.split_at(index);
952 assert_eq!(&s[..a.len()], a);
953 assert_eq!(&s[a.len()..], b);
955 let (a, b) = s.split_at(s.len());
961 fn test_split_at_mut() {
962 let mut s = "Hello World".to_string();
964 let (a, b) = s.split_at_mut(5);
965 a.make_ascii_uppercase();
966 b.make_ascii_lowercase();
968 assert_eq!(s, "HELLO world");
973 fn test_split_at_boundscheck() {
974 let s = "ศไทย中华Việt Nam";
979 fn test_escape_unicode() {
980 assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
981 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
982 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
983 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
984 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
985 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
986 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
987 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
988 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
992 fn test_escape_debug() {
993 // Note that there are subtleties with the number of backslashes
994 // on the left- and right-hand sides. In particular, Unicode code points
995 // are usually escaped with two backslashes on the right-hand side, as
996 // they are escaped. However, when the character is unescaped (e.g., for
997 // printable characters), only a single backslash appears (as the character
998 // itself appears in the debug string).
999 assert_eq!("abc".escape_debug().to_string(), "abc");
1000 assert_eq!("a c".escape_debug().to_string(), "a c");
1001 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1002 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1003 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1004 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1005 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1006 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1007 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1008 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1010 "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1011 "\\u{301}a\u{301}bé\\u{e000}"
1016 fn test_escape_default() {
1017 assert_eq!("abc".escape_default().to_string(), "abc");
1018 assert_eq!("a c".escape_default().to_string(), "a c");
1019 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1020 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1021 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1022 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1023 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1024 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1025 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1026 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1030 fn test_total_ord() {
1031 assert_eq!("1234".cmp("123"), Greater);
1032 assert_eq!("123".cmp("1234"), Less);
1033 assert_eq!("1234".cmp("1234"), Equal);
1034 assert_eq!("12345555".cmp("123456"), Less);
1035 assert_eq!("22".cmp("1234"), Greater);
1039 fn test_iterator() {
1040 let s = "ศไทย中华Việt Nam";
1041 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1047 assert_eq!(c, v[pos]);
1050 assert_eq!(pos, v.len());
1051 assert_eq!(s.chars().count(), v.len());
1055 fn test_rev_iterator() {
1056 let s = "ศไทย中华Việt Nam";
1057 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1060 let it = s.chars().rev();
1063 assert_eq!(c, v[pos]);
1066 assert_eq!(pos, v.len());
1070 #[cfg_attr(miri, ignore)] // Miri is too slow
1071 fn test_chars_decoding() {
1072 let mut bytes = [0; 4];
1073 for c in (0..0x110000).filter_map(std::char::from_u32) {
1074 let s = c.encode_utf8(&mut bytes);
1075 if Some(c) != s.chars().next() {
1076 panic!("character {:x}={} does not decode correctly", c as u32, c);
1082 #[cfg_attr(miri, ignore)] // Miri is too slow
1083 fn test_chars_rev_decoding() {
1084 let mut bytes = [0; 4];
1085 for c in (0..0x110000).filter_map(std::char::from_u32) {
1086 let s = c.encode_utf8(&mut bytes);
1087 if Some(c) != s.chars().rev().next() {
1088 panic!("character {:x}={} does not decode correctly", c as u32, c);
1094 fn test_iterator_clone() {
1095 let s = "ศไทย中华Việt Nam";
1096 let mut it = s.chars();
1098 assert!(it.clone().zip(it).all(|(x, y)| x == y));
1102 fn test_iterator_last() {
1103 let s = "ศไทย中华Việt Nam";
1104 let mut it = s.chars();
1106 assert_eq!(it.last(), Some('m'));
1110 fn test_chars_debug() {
1111 let s = "ศไทย中华Việt Nam";
1115 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1120 fn test_bytesator() {
1121 let s = "ศไทย中华Việt Nam";
1123 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1124 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1128 for b in s.bytes() {
1129 assert_eq!(b, v[pos]);
1135 fn test_bytes_revator() {
1136 let s = "ศไทย中华Việt Nam";
1138 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1139 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1141 let mut pos = v.len();
1143 for b in s.bytes().rev() {
1145 assert_eq!(b, v[pos]);
1150 fn test_bytesator_nth() {
1151 let s = "ศไทย中华Việt Nam";
1153 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1154 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1157 let mut b = s.bytes();
1158 assert_eq!(b.nth(2).unwrap(), v[2]);
1159 assert_eq!(b.nth(10).unwrap(), v[10]);
1160 assert_eq!(b.nth(200), None);
1164 fn test_bytesator_count() {
1165 let s = "ศไทย中华Việt Nam";
1168 assert_eq!(b.count(), 28)
1172 fn test_bytesator_last() {
1173 let s = "ศไทย中华Việt Nam";
1176 assert_eq!(b.last().unwrap(), 109)
1180 fn test_char_indicesator() {
1181 let s = "ศไทย中华Việt Nam";
1182 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1183 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1186 let it = s.char_indices();
1189 assert_eq!(c, (p[pos], v[pos]));
1192 assert_eq!(pos, v.len());
1193 assert_eq!(pos, p.len());
1197 fn test_char_indices_revator() {
1198 let s = "ศไทย中华Việt Nam";
1199 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1200 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1203 let it = s.char_indices().rev();
1206 assert_eq!(c, (p[pos], v[pos]));
1209 assert_eq!(pos, v.len());
1210 assert_eq!(pos, p.len());
1214 fn test_char_indices_last() {
1215 let s = "ศไทย中华Việt Nam";
1216 let mut it = s.char_indices();
1218 assert_eq!(it.last(), Some((27, 'm')));
1222 fn test_splitn_char_iterator() {
1223 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1225 let split: Vec<&str> = data.splitn(4, ' ').collect();
1226 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1228 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1229 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1232 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1233 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1235 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1236 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1240 fn test_split_char_iterator_no_trailing() {
1241 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1243 let split: Vec<&str> = data.split('\n').collect();
1244 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1246 let split: Vec<&str> = data.split_terminator('\n').collect();
1247 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1251 fn test_split_char_iterator_inclusive() {
1252 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1254 let split: Vec<&str> = data.split_inclusive('\n').collect();
1255 assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1257 let uppercase_separated = "SheePSharKTurtlECaT";
1258 let mut first_char = true;
1259 let split: Vec<&str> = uppercase_separated
1260 .split_inclusive(|c: char| {
1261 let split = !first_char && c.is_uppercase();
1266 assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1270 fn test_split_char_iterator_inclusive_rev() {
1271 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1273 let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1274 assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1276 // Note that the predicate is stateful and thus dependent
1277 // on the iteration order.
1278 // (A different predicate is needed for reverse iterator vs normal iterator.)
1279 // Not sure if anything can be done though.
1280 let uppercase_separated = "SheePSharKTurtlECaT";
1281 let mut term_char = true;
1282 let split: Vec<&str> = uppercase_separated
1283 .split_inclusive(|c: char| {
1284 let split = term_char && c.is_uppercase();
1285 term_char = c.is_uppercase();
1290 assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1295 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1297 let split: Vec<&str> = data.rsplit(' ').collect();
1298 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1300 let split: Vec<&str> = data.rsplit("lämb").collect();
1301 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1303 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1304 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1309 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1311 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1312 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1314 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1315 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1317 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1318 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1322 fn test_split_once() {
1323 assert_eq!("".split_once("->"), None);
1324 assert_eq!("-".split_once("->"), None);
1325 assert_eq!("->".split_once("->"), Some(("", "")));
1326 assert_eq!("a->".split_once("->"), Some(("a", "")));
1327 assert_eq!("->b".split_once("->"), Some(("", "b")));
1328 assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1329 assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1330 assert_eq!("---".split_once("--"), Some(("", "-")));
1334 fn test_rsplit_once() {
1335 assert_eq!("".rsplit_once("->"), None);
1336 assert_eq!("-".rsplit_once("->"), None);
1337 assert_eq!("->".rsplit_once("->"), Some(("", "")));
1338 assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1339 assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1340 assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1341 assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1342 assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1346 fn test_split_whitespace() {
1347 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1348 let words: Vec<&str> = data.split_whitespace().collect();
1349 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1354 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1355 let lines: Vec<&str> = data.lines().collect();
1356 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1358 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1359 let lines: Vec<&str> = data.lines().collect();
1360 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1364 fn test_splitator() {
1365 fn t(s: &str, sep: &str, u: &[&str]) {
1366 let v: Vec<&str> = s.split(sep).collect();
1369 t("--1233345--", "12345", &["--1233345--"]);
1370 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1371 t("::hello::there", "::", &["", "hello", "there"]);
1372 t("hello::there::", "::", &["hello", "there", ""]);
1373 t("::hello::there::", "::", &["", "hello", "there", ""]);
1374 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1375 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1376 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1377 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1379 t("zz", "zz", &["", ""]);
1380 t("ok", "z", &["ok"]);
1381 t("zzz", "zz", &["", "z"]);
1382 t("zzzzz", "zz", &["", "", "z"]);
1386 fn test_str_default() {
1387 use std::default::Default;
1389 fn t<S: Default + AsRef<str>>() {
1390 let s: S = Default::default();
1391 assert_eq!(s.as_ref(), "");
1400 fn test_str_container() {
1401 fn sum_len(v: &[&str]) -> usize {
1402 v.iter().map(|x| x.len()).sum()
1406 assert_eq!(5, sum_len(&["012", "", "34"]));
1407 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1408 assert_eq!(5, sum_len(&[s]));
1412 fn test_str_from_utf8() {
1414 assert_eq!(from_utf8(xs), Ok("hello"));
1416 let xs = "ศไทย中华Việt Nam".as_bytes();
1417 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1419 let xs = b"hello\xFF";
1420 assert!(from_utf8(xs).is_err());
1424 fn test_pattern_deref_forward() {
1425 let data = "aabcdaa";
1426 assert!(data.contains("bcd"));
1427 assert!(data.contains(&"bcd"));
1428 assert!(data.contains(&"bcd".to_string()));
1432 fn test_empty_match_indices() {
1434 let vec: Vec<_> = data.match_indices("").collect();
1435 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1439 fn test_bool_from_str() {
1440 assert_eq!("true".parse().ok(), Some(true));
1441 assert_eq!("false".parse().ok(), Some(false));
1442 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1445 fn check_contains_all_substrings(s: &str) {
1446 assert!(s.contains(""));
1447 for i in 0..s.len() {
1448 for j in i + 1..=s.len() {
1449 assert!(s.contains(&s[i..j]));
1455 #[cfg_attr(miri, ignore)] // Miri is too slow
1456 fn strslice_issue_16589() {
1457 assert!("bananas".contains("nana"));
1459 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1460 // test all substrings for good measure
1461 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1465 fn strslice_issue_16878() {
1466 assert!(!"1234567ah012345678901ah".contains("hah"));
1467 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1471 #[cfg_attr(miri, ignore)] // Miri is too slow
1472 fn test_strslice_contains() {
1473 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1474 check_contains_all_substrings(x);
1478 fn test_rsplitn_char_iterator() {
1479 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1481 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1483 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1485 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1487 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1490 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1492 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1494 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1496 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1500 fn test_split_char_iterator() {
1501 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1503 let split: Vec<&str> = data.split(' ').collect();
1504 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1506 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1508 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1510 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1511 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1513 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1515 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1518 let split: Vec<&str> = data.split('ä').collect();
1519 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1521 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1523 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1525 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1526 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1528 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1530 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1534 fn test_rev_split_char_iterator_no_trailing() {
1535 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1537 let mut split: Vec<&str> = data.split('\n').rev().collect();
1539 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1541 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1543 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1547 fn test_utf16_code_units() {
1548 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1552 fn starts_with_in_unicode() {
1553 assert!(!"├── Cargo.toml".starts_with("# "));
1557 fn starts_short_long() {
1558 assert!(!"".starts_with("##"));
1559 assert!(!"##".starts_with("####"));
1560 assert!("####".starts_with("##"));
1561 assert!(!"##ä".starts_with("####"));
1562 assert!("####ä".starts_with("##"));
1563 assert!(!"##".starts_with("####ä"));
1564 assert!("##ä##".starts_with("##ä"));
1566 assert!("".starts_with(""));
1567 assert!("ä".starts_with(""));
1568 assert!("#ä".starts_with(""));
1569 assert!("##ä".starts_with(""));
1570 assert!("ä###".starts_with(""));
1571 assert!("#ä##".starts_with(""));
1572 assert!("##ä#".starts_with(""));
1576 fn contains_weird_cases() {
1577 assert!("* \t".contains(' '));
1578 assert!(!"* \t".contains('?'));
1579 assert!(!"* \t".contains('\u{1F4A9}'));
1584 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1585 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1586 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1587 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1588 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
1589 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1590 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1591 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1592 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1593 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
1598 assert_eq!("".to_lowercase(), "");
1599 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1601 // https://github.com/rust-lang/rust/issues/26035
1602 assert_eq!("ΑΣ".to_lowercase(), "ας");
1603 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1604 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1606 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1607 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1608 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1610 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1611 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1613 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1614 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1616 assert_eq!("Α Σ".to_lowercase(), "α σ");
1617 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1618 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1620 assert_eq!("Σ".to_lowercase(), "σ");
1621 assert_eq!("'Σ".to_lowercase(), "'σ");
1622 assert_eq!("''Σ".to_lowercase(), "''σ");
1624 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1625 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1626 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1631 assert_eq!("".to_uppercase(), "");
1632 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1636 fn test_into_string() {
1637 // The only way to acquire a Box<str> in the first place is through a String, so just
1638 // test that we can round-trip between Box<str> and String.
1639 let string = String::from("Some text goes here");
1640 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1644 fn test_box_slice_clone() {
1645 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1646 let data2 = data.clone().into_boxed_str().clone().into_string();
1648 assert_eq!(data, data2);
1652 fn test_cow_from() {
1653 let borrowed = "borrowed";
1654 let owned = String::from("owned");
1655 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1656 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1657 _ => panic!("invalid `Cow::from`"),
1663 assert_eq!("".repeat(3), "");
1664 assert_eq!("abc".repeat(0), "");
1665 assert_eq!("α".repeat(3), "ααα");
1669 use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1670 use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1672 macro_rules! make_test {
1673 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1674 #[allow(unused_imports)]
1676 use std::str::pattern::SearchStep::{Match, Reject};
1677 use super::{cmp_search_to_vec};
1680 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1684 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1690 fn cmp_search_to_vec<'a>(
1692 pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1694 right: Vec<SearchStep>,
1696 let mut searcher = pat.into_searcher(haystack);
1699 match if !rev { searcher.next() } else { searcher.next_back() } {
1700 Match(a, b) => v.push(Match(a, b)),
1701 Reject(a, b) => v.push(Reject(a, b)),
1709 let mut first_index = 0;
1712 for (i, e) in right.iter().enumerate() {
1714 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1724 if let Some(err) = err {
1725 panic!("Input skipped range at {}", err);
1728 if first_index != haystack.len() {
1729 panic!("Did not cover whole input");
1732 assert_eq!(v, right);
1736 str_searcher_ascii_haystack,
1739 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1742 str_searcher_ascii_haystack_seq,
1745 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1748 str_searcher_empty_needle_ascii_haystack,
1770 str_searcher_multibyte_haystack,
1773 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1776 str_searcher_empty_needle_multibyte_haystack,
1789 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1790 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1792 char_searcher_ascii_haystack,
1806 char_searcher_multibyte_haystack,
1809 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1812 char_searcher_short_haystack,
1815 [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1819 macro_rules! generate_iterator_test {
1823 ($($arg:expr),*) -> [$($t:tt)*];
1826 with $fwd:expr, $bwd:expr;
1832 let res = vec![$($t)*];
1834 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1835 assert_eq!(fwd_vec, res);
1837 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1839 assert_eq!(bwd_vec, res);
1847 ($($arg:expr),*) -> [$($t:tt)*];
1856 let res = vec![$($t)*];
1858 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1859 assert_eq!(fwd_vec, res);
1866 generate_iterator_test! {
1867 double_ended_split {
1868 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1869 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1871 with str::split, str::rsplit;
1874 generate_iterator_test! {
1875 double_ended_split_terminator {
1876 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1878 with str::split_terminator, str::rsplit_terminator;
1881 generate_iterator_test! {
1882 double_ended_matches {
1883 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1885 with str::matches, str::rmatches;
1888 generate_iterator_test! {
1889 double_ended_match_indices {
1890 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1892 with str::match_indices, str::rmatch_indices;
1895 generate_iterator_test! {
1896 not_double_ended_splitn {
1897 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1902 generate_iterator_test! {
1903 not_double_ended_rsplitn {
1904 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1910 fn different_str_pattern_forwarding_lifetimes() {
1911 use std::str::pattern::Pattern;
1915 for<'b> &'b P: Pattern<'a>,