2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::{from_utf8, from_utf8_unchecked};
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 rangeinclusive_len {
534 good: data[0..=5] == "abcdef";
536 message: "out of bounds";
539 in mod range_len_len {
541 good: data[6..6] == "";
543 message: "out of bounds";
546 in mod rangeinclusive_len_len {
548 good: data[6..=5] == "";
550 message: "out of bounds";
555 in mod rangeinclusive_exhausted {
558 good: data[0..=5] == "abcdef";
560 let mut iter = 0..=5;
561 iter.by_ref().count(); // exhaust it
565 // 0..=6 is out of bounds before exhaustion, so it
566 // stands to reason that it still would be after.
568 let mut iter = 0..=6;
569 iter.by_ref().count(); // exhaust it
572 message: "out of bounds";
577 in mod range_neg_width {
579 good: data[4..4] == "";
581 message: "begin <= end (4 <= 3)";
584 in mod rangeinclusive_neg_width {
586 good: data[4..=3] == "";
588 message: "begin <= end (4 <= 3)";
594 in mod rangeinclusive {
596 // note: using 0 specifically ensures that the result of overflowing is 0..0,
597 // so that `get` doesn't simply return None for the wrong reason.
598 bad: data[0..=usize::MAX];
599 message: "maximum usize";
602 in mod rangetoinclusive {
604 bad: data[..=usize::MAX];
605 message: "maximum usize";
611 const DATA: &str = "abcαβγ";
613 const BAD_START: usize = 4;
614 const GOOD_START: usize = 3;
615 const BAD_END: usize = 6;
616 const GOOD_END: usize = 7;
617 const BAD_END_INCL: usize = BAD_END - 1;
618 const GOOD_END_INCL: usize = GOOD_END - 1;
620 // it is especially important to test all of the different range types here
621 // because some of the logic may be duplicated as part of micro-optimizations
622 // to dodge unicode boundary checks on half-ranges.
626 bad: data[super::BAD_START..super::GOOD_END];
628 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
633 bad: data[super::GOOD_START..super::BAD_END];
635 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
640 bad: data[super::BAD_START..];
642 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
647 bad: data[..super::BAD_END];
649 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
652 in mod rangeinclusive_1 {
654 bad: data[super::BAD_START..=super::GOOD_END_INCL];
656 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
659 in mod rangeinclusive_2 {
661 bad: data[super::GOOD_START..=super::BAD_END_INCL];
663 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
666 in mod rangetoinclusive {
668 bad: data[..=super::BAD_END_INCL];
670 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
675 const LOREM_PARAGRAPH: &str = "\
676 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
677 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
678 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
679 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
680 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
683 // check the panic includes the prefix of the sliced string
685 #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
686 fn test_slice_fail_truncated_1() {
687 &LOREM_PARAGRAPH[..1024];
689 // check the truncation in the panic message
691 #[should_panic(expected = "luctus, im`[...]")]
692 fn test_slice_fail_truncated_2() {
693 &LOREM_PARAGRAPH[..1024];
698 fn test_str_slice_rangetoinclusive_ok() {
700 assert_eq!(&s[..=2], "abc");
701 assert_eq!(&s[..=4], "abcα");
706 fn test_str_slice_rangetoinclusive_notok() {
712 fn test_str_slicemut_rangetoinclusive_ok() {
713 let mut s = "abcαβγ".to_owned();
714 let s: &mut str = &mut s;
715 assert_eq!(&mut s[..=2], "abc");
716 assert_eq!(&mut s[..=4], "abcα");
721 fn test_str_slicemut_rangetoinclusive_notok() {
722 let mut s = "abcαβγ".to_owned();
723 let s: &mut str = &mut s;
728 fn test_is_char_boundary() {
729 let s = "ศไทย中华Việt Nam β-release 🐱123";
730 assert!(s.is_char_boundary(0));
731 assert!(s.is_char_boundary(s.len()));
732 assert!(!s.is_char_boundary(s.len() + 1));
733 for (i, ch) in s.char_indices() {
734 // ensure character locations are boundaries and continuation bytes are not
735 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
736 for j in 1..ch.len_utf8() {
738 !s.is_char_boundary(i + j),
739 "{} should not be a char boundary in {:?}",
748 fn test_trim_start_matches() {
749 let v: &[char] = &[];
750 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
751 let chars: &[char] = &['*', ' '];
752 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
753 assert_eq!(" *** *** ".trim_start_matches(chars), "");
754 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
756 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
757 let chars: &[char] = &['1', '2'];
758 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
759 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
763 fn test_trim_end_matches() {
764 let v: &[char] = &[];
765 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
766 let chars: &[char] = &['*', ' '];
767 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
768 assert_eq!(" *** *** ".trim_end_matches(chars), "");
769 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
771 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
772 let chars: &[char] = &['1', '2'];
773 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
774 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
778 fn test_trim_matches() {
779 let v: &[char] = &[];
780 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
781 let chars: &[char] = &['*', ' '];
782 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
783 assert_eq!(" *** *** ".trim_matches(chars), "");
784 assert_eq!("foo".trim_matches(chars), "foo");
786 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
787 let chars: &[char] = &['1', '2'];
788 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
789 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
793 fn test_trim_start() {
794 assert_eq!("".trim_start(), "");
795 assert_eq!("a".trim_start(), "a");
796 assert_eq!(" ".trim_start(), "");
797 assert_eq!(" blah".trim_start(), "blah");
798 assert_eq!(" \u{3000} wut".trim_start(), "wut");
799 assert_eq!("hey ".trim_start(), "hey ");
804 assert_eq!("".trim_end(), "");
805 assert_eq!("a".trim_end(), "a");
806 assert_eq!(" ".trim_end(), "");
807 assert_eq!("blah ".trim_end(), "blah");
808 assert_eq!("wut \u{3000} ".trim_end(), "wut");
809 assert_eq!(" hey".trim_end(), " hey");
814 assert_eq!("".trim(), "");
815 assert_eq!("a".trim(), "a");
816 assert_eq!(" ".trim(), "");
817 assert_eq!(" blah ".trim(), "blah");
818 assert_eq!("\nwut \u{3000} ".trim(), "wut");
819 assert_eq!(" hey dude ".trim(), "hey dude");
823 fn test_is_whitespace() {
824 assert!("".chars().all(|c| c.is_whitespace()));
825 assert!(" ".chars().all(|c| c.is_whitespace()));
826 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
827 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
828 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
833 // deny overlong encodings
834 assert!(from_utf8(&[0xc0, 0x80]).is_err());
835 assert!(from_utf8(&[0xc0, 0xae]).is_err());
836 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
837 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
838 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
839 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
840 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
843 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
844 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
846 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
847 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
848 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
849 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
850 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
851 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
852 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
853 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
857 fn from_utf8_mostly_ascii() {
858 // deny invalid bytes embedded in long stretches of ascii
860 let mut data = [0; 128];
862 assert!(from_utf8(&data).is_err());
864 assert!(from_utf8(&data).is_err());
869 fn from_utf8_error() {
871 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
872 let error = from_utf8($input).unwrap_err();
873 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
874 assert_eq!(error.error_len(), $expected_error_len);
877 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
878 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
879 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
880 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
881 test!(b"A\xC3\xA9 \xC2", 4, None);
882 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
883 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
884 test!(b"A\xC3\xA9 \xE0", 4, None);
885 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
886 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
887 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
888 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
889 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
890 test!(b"A\xC3\xA9 \xF1", 4, None);
891 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
892 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
893 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
894 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
895 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
902 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
903 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
906 assert_eq!("".as_bytes(), b);
907 assert_eq!("abc".as_bytes(), b"abc");
908 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
913 fn test_as_bytes_fail() {
914 // Don't double free. (I'm not sure if this exercises the
915 // original problem code path anymore.)
916 let s = String::from("");
917 let _bytes = s.as_bytes();
923 let buf = "hello".as_ptr();
925 assert_eq!(*buf.offset(0), b'h');
926 assert_eq!(*buf.offset(1), b'e');
927 assert_eq!(*buf.offset(2), b'l');
928 assert_eq!(*buf.offset(3), b'l');
929 assert_eq!(*buf.offset(4), b'o');
934 fn vec_str_conversions() {
935 let s1: String = String::from("All mimsy were the borogoves");
937 let v: Vec<u8> = s1.as_bytes().to_vec();
938 let s2: String = String::from(from_utf8(&v).unwrap());
944 let a: u8 = s1.as_bytes()[i];
945 let b: u8 = s2.as_bytes()[i];
953 assert!("abcde".contains("bcd"));
954 assert!("abcde".contains("abcd"));
955 assert!("abcde".contains("bcde"));
956 assert!("abcde".contains(""));
957 assert!("".contains(""));
958 assert!(!"abcde".contains("def"));
959 assert!(!"".contains("a"));
961 let data = "ประเทศไทย中华Việt Nam";
962 assert!(data.contains("ประเ"));
963 assert!(data.contains("ะเ"));
964 assert!(data.contains("中华"));
965 assert!(!data.contains("ไท华"));
969 fn test_contains_char() {
970 assert!("abc".contains('b'));
971 assert!("a".contains('a'));
972 assert!(!"abc".contains('d'));
973 assert!(!"".contains('a'));
978 let s = "ศไทย中华Việt Nam";
979 for (index, _) in s.char_indices() {
980 let (a, b) = s.split_at(index);
981 assert_eq!(&s[..a.len()], a);
982 assert_eq!(&s[a.len()..], b);
984 let (a, b) = s.split_at(s.len());
990 fn test_split_at_mut() {
991 let mut s = "Hello World".to_string();
993 let (a, b) = s.split_at_mut(5);
994 a.make_ascii_uppercase();
995 b.make_ascii_lowercase();
997 assert_eq!(s, "HELLO world");
1002 fn test_split_at_boundscheck() {
1003 let s = "ศไทย中华Việt Nam";
1008 fn test_escape_unicode() {
1009 assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
1010 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
1011 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
1012 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
1013 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
1014 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
1015 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1016 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1017 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
1021 fn test_escape_debug() {
1022 // Note that there are subtleties with the number of backslashes
1023 // on the left- and right-hand sides. In particular, Unicode code points
1024 // are usually escaped with two backslashes on the right-hand side, as
1025 // they are escaped. However, when the character is unescaped (e.g., for
1026 // printable characters), only a single backslash appears (as the character
1027 // itself appears in the debug string).
1028 assert_eq!("abc".escape_debug().to_string(), "abc");
1029 assert_eq!("a c".escape_debug().to_string(), "a c");
1030 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1031 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1032 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1033 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1034 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1035 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1036 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1037 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1039 "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1040 "\\u{301}a\u{301}bé\\u{e000}"
1045 fn test_escape_default() {
1046 assert_eq!("abc".escape_default().to_string(), "abc");
1047 assert_eq!("a c".escape_default().to_string(), "a c");
1048 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1049 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1050 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1051 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1052 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1053 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1054 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1055 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1059 fn test_total_ord() {
1060 assert_eq!("1234".cmp("123"), Greater);
1061 assert_eq!("123".cmp("1234"), Less);
1062 assert_eq!("1234".cmp("1234"), Equal);
1063 assert_eq!("12345555".cmp("123456"), Less);
1064 assert_eq!("22".cmp("1234"), Greater);
1068 fn test_iterator() {
1069 let s = "ศไทย中华Việt Nam";
1070 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1076 assert_eq!(c, v[pos]);
1079 assert_eq!(pos, v.len());
1080 assert_eq!(s.chars().count(), v.len());
1084 fn test_rev_iterator() {
1085 let s = "ศไทย中华Việt Nam";
1086 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1089 let it = s.chars().rev();
1092 assert_eq!(c, v[pos]);
1095 assert_eq!(pos, v.len());
1099 #[cfg_attr(miri, ignore)] // Miri is too slow
1100 fn test_chars_decoding() {
1101 let mut bytes = [0; 4];
1102 for c in (0..0x110000).filter_map(std::char::from_u32) {
1103 let s = c.encode_utf8(&mut bytes);
1104 if Some(c) != s.chars().next() {
1105 panic!("character {:x}={} does not decode correctly", c as u32, c);
1111 #[cfg_attr(miri, ignore)] // Miri is too slow
1112 fn test_chars_rev_decoding() {
1113 let mut bytes = [0; 4];
1114 for c in (0..0x110000).filter_map(std::char::from_u32) {
1115 let s = c.encode_utf8(&mut bytes);
1116 if Some(c) != s.chars().rev().next() {
1117 panic!("character {:x}={} does not decode correctly", c as u32, c);
1123 fn test_iterator_clone() {
1124 let s = "ศไทย中华Việt Nam";
1125 let mut it = s.chars();
1127 assert!(it.clone().zip(it).all(|(x, y)| x == y));
1131 fn test_iterator_last() {
1132 let s = "ศไทย中华Việt Nam";
1133 let mut it = s.chars();
1135 assert_eq!(it.last(), Some('m'));
1139 fn test_chars_debug() {
1140 let s = "ศไทย中华Việt Nam";
1144 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1149 fn test_bytesator() {
1150 let s = "ศไทย中华Việt Nam";
1152 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1153 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1157 for b in s.bytes() {
1158 assert_eq!(b, v[pos]);
1164 fn test_bytes_revator() {
1165 let s = "ศไทย中华Việt Nam";
1167 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1168 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1170 let mut pos = v.len();
1172 for b in s.bytes().rev() {
1174 assert_eq!(b, v[pos]);
1179 fn test_bytesator_nth() {
1180 let s = "ศไทย中华Việt Nam";
1182 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1183 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1186 let mut b = s.bytes();
1187 assert_eq!(b.nth(2).unwrap(), v[2]);
1188 assert_eq!(b.nth(10).unwrap(), v[10]);
1189 assert_eq!(b.nth(200), None);
1193 fn test_bytesator_count() {
1194 let s = "ศไทย中华Việt Nam";
1197 assert_eq!(b.count(), 28)
1201 fn test_bytesator_last() {
1202 let s = "ศไทย中华Việt Nam";
1205 assert_eq!(b.last().unwrap(), 109)
1209 fn test_char_indicesator() {
1210 let s = "ศไทย中华Việt Nam";
1211 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1212 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1215 let it = s.char_indices();
1218 assert_eq!(c, (p[pos], v[pos]));
1221 assert_eq!(pos, v.len());
1222 assert_eq!(pos, p.len());
1226 fn test_char_indices_revator() {
1227 let s = "ศไทย中华Việt Nam";
1228 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1229 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1232 let it = s.char_indices().rev();
1235 assert_eq!(c, (p[pos], v[pos]));
1238 assert_eq!(pos, v.len());
1239 assert_eq!(pos, p.len());
1243 fn test_char_indices_last() {
1244 let s = "ศไทย中华Việt Nam";
1245 let mut it = s.char_indices();
1247 assert_eq!(it.last(), Some((27, 'm')));
1251 fn test_splitn_char_iterator() {
1252 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1254 let split: Vec<&str> = data.splitn(4, ' ').collect();
1255 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1257 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1258 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1261 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1262 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1264 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1265 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1269 fn test_split_char_iterator_no_trailing() {
1270 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1272 let split: Vec<&str> = data.split('\n').collect();
1273 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1275 let split: Vec<&str> = data.split_terminator('\n').collect();
1276 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1280 fn test_split_char_iterator_inclusive() {
1281 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1283 let split: Vec<&str> = data.split_inclusive('\n').collect();
1284 assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1286 let uppercase_separated = "SheePSharKTurtlECaT";
1287 let mut first_char = true;
1288 let split: Vec<&str> = uppercase_separated
1289 .split_inclusive(|c: char| {
1290 let split = !first_char && c.is_uppercase();
1295 assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1299 fn test_split_char_iterator_inclusive_rev() {
1300 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1302 let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1303 assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1305 // Note that the predicate is stateful and thus dependent
1306 // on the iteration order.
1307 // (A different predicate is needed for reverse iterator vs normal iterator.)
1308 // Not sure if anything can be done though.
1309 let uppercase_separated = "SheePSharKTurtlECaT";
1310 let mut term_char = true;
1311 let split: Vec<&str> = uppercase_separated
1312 .split_inclusive(|c: char| {
1313 let split = term_char && c.is_uppercase();
1314 term_char = c.is_uppercase();
1319 assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1324 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1326 let split: Vec<&str> = data.rsplit(' ').collect();
1327 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1329 let split: Vec<&str> = data.rsplit("lämb").collect();
1330 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1332 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1333 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1338 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1340 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1341 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1343 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1344 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1346 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1347 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1351 fn test_split_once() {
1352 assert_eq!("".split_once("->"), None);
1353 assert_eq!("-".split_once("->"), None);
1354 assert_eq!("->".split_once("->"), Some(("", "")));
1355 assert_eq!("a->".split_once("->"), Some(("a", "")));
1356 assert_eq!("->b".split_once("->"), Some(("", "b")));
1357 assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1358 assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1359 assert_eq!("---".split_once("--"), Some(("", "-")));
1363 fn test_rsplit_once() {
1364 assert_eq!("".rsplit_once("->"), None);
1365 assert_eq!("-".rsplit_once("->"), None);
1366 assert_eq!("->".rsplit_once("->"), Some(("", "")));
1367 assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1368 assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1369 assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1370 assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1371 assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1375 fn test_split_whitespace() {
1376 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1377 let words: Vec<&str> = data.split_whitespace().collect();
1378 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1383 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1384 let lines: Vec<&str> = data.lines().collect();
1385 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1387 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1388 let lines: Vec<&str> = data.lines().collect();
1389 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1393 fn test_splitator() {
1394 fn t(s: &str, sep: &str, u: &[&str]) {
1395 let v: Vec<&str> = s.split(sep).collect();
1398 t("--1233345--", "12345", &["--1233345--"]);
1399 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1400 t("::hello::there", "::", &["", "hello", "there"]);
1401 t("hello::there::", "::", &["hello", "there", ""]);
1402 t("::hello::there::", "::", &["", "hello", "there", ""]);
1403 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1404 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1405 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1406 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1408 t("zz", "zz", &["", ""]);
1409 t("ok", "z", &["ok"]);
1410 t("zzz", "zz", &["", "z"]);
1411 t("zzzzz", "zz", &["", "", "z"]);
1415 fn test_str_default() {
1416 use std::default::Default;
1418 fn t<S: Default + AsRef<str>>() {
1419 let s: S = Default::default();
1420 assert_eq!(s.as_ref(), "");
1429 fn test_str_container() {
1430 fn sum_len(v: &[&str]) -> usize {
1431 v.iter().map(|x| x.len()).sum()
1435 assert_eq!(5, sum_len(&["012", "", "34"]));
1436 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1437 assert_eq!(5, sum_len(&[s]));
1441 fn test_str_from_utf8() {
1443 assert_eq!(from_utf8(xs), Ok("hello"));
1445 let xs = "ศไทย中华Việt Nam".as_bytes();
1446 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1448 let xs = b"hello\xFF";
1449 assert!(from_utf8(xs).is_err());
1453 fn test_pattern_deref_forward() {
1454 let data = "aabcdaa";
1455 assert!(data.contains("bcd"));
1456 assert!(data.contains(&"bcd"));
1457 assert!(data.contains(&"bcd".to_string()));
1461 fn test_empty_match_indices() {
1463 let vec: Vec<_> = data.match_indices("").collect();
1464 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1468 fn test_bool_from_str() {
1469 assert_eq!("true".parse().ok(), Some(true));
1470 assert_eq!("false".parse().ok(), Some(false));
1471 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1474 fn check_contains_all_substrings(s: &str) {
1475 assert!(s.contains(""));
1476 for i in 0..s.len() {
1477 for j in i + 1..=s.len() {
1478 assert!(s.contains(&s[i..j]));
1484 #[cfg_attr(miri, ignore)] // Miri is too slow
1485 fn strslice_issue_16589() {
1486 assert!("bananas".contains("nana"));
1488 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1489 // test all substrings for good measure
1490 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1494 fn strslice_issue_16878() {
1495 assert!(!"1234567ah012345678901ah".contains("hah"));
1496 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1500 #[cfg_attr(miri, ignore)] // Miri is too slow
1501 fn test_strslice_contains() {
1502 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1503 check_contains_all_substrings(x);
1507 fn test_rsplitn_char_iterator() {
1508 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1510 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1512 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1514 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1516 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1519 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1521 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1523 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1525 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1529 fn test_split_char_iterator() {
1530 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1532 let split: Vec<&str> = data.split(' ').collect();
1533 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1535 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1537 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1539 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1540 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1542 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1544 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1547 let split: Vec<&str> = data.split('ä').collect();
1548 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1550 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1552 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1554 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1555 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1557 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1559 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1563 fn test_rev_split_char_iterator_no_trailing() {
1564 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1566 let mut split: Vec<&str> = data.split('\n').rev().collect();
1568 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1570 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1572 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1576 fn test_utf16_code_units() {
1577 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1581 fn starts_with_in_unicode() {
1582 assert!(!"├── Cargo.toml".starts_with("# "));
1586 fn starts_short_long() {
1587 assert!(!"".starts_with("##"));
1588 assert!(!"##".starts_with("####"));
1589 assert!("####".starts_with("##"));
1590 assert!(!"##ä".starts_with("####"));
1591 assert!("####ä".starts_with("##"));
1592 assert!(!"##".starts_with("####ä"));
1593 assert!("##ä##".starts_with("##ä"));
1595 assert!("".starts_with(""));
1596 assert!("ä".starts_with(""));
1597 assert!("#ä".starts_with(""));
1598 assert!("##ä".starts_with(""));
1599 assert!("ä###".starts_with(""));
1600 assert!("#ä##".starts_with(""));
1601 assert!("##ä#".starts_with(""));
1605 fn contains_weird_cases() {
1606 assert!("* \t".contains(' '));
1607 assert!(!"* \t".contains('?'));
1608 assert!(!"* \t".contains('\u{1F4A9}'));
1613 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1614 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1615 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1616 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1617 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
1618 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1619 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1620 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1621 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1622 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
1627 assert_eq!("".to_lowercase(), "");
1628 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1630 // https://github.com/rust-lang/rust/issues/26035
1631 assert_eq!("ΑΣ".to_lowercase(), "ας");
1632 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1633 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1635 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1636 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1637 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1639 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1640 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1642 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1643 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1645 assert_eq!("Α Σ".to_lowercase(), "α σ");
1646 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1647 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1649 assert_eq!("Σ".to_lowercase(), "σ");
1650 assert_eq!("'Σ".to_lowercase(), "'σ");
1651 assert_eq!("''Σ".to_lowercase(), "''σ");
1653 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1654 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1655 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1660 assert_eq!("".to_uppercase(), "");
1661 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1665 fn test_into_string() {
1666 // The only way to acquire a Box<str> in the first place is through a String, so just
1667 // test that we can round-trip between Box<str> and String.
1668 let string = String::from("Some text goes here");
1669 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1673 fn test_box_slice_clone() {
1674 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1675 let data2 = data.clone().into_boxed_str().clone().into_string();
1677 assert_eq!(data, data2);
1681 fn test_cow_from() {
1682 let borrowed = "borrowed";
1683 let owned = String::from("owned");
1684 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1685 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1686 _ => panic!("invalid `Cow::from`"),
1692 assert_eq!("".repeat(3), "");
1693 assert_eq!("abc".repeat(0), "");
1694 assert_eq!("α".repeat(3), "ααα");
1698 use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1699 use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1701 macro_rules! make_test {
1702 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1703 #[allow(unused_imports)]
1705 use std::str::pattern::SearchStep::{Match, Reject};
1706 use super::{cmp_search_to_vec};
1709 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1713 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1719 fn cmp_search_to_vec<'a>(
1721 pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1723 right: Vec<SearchStep>,
1725 let mut searcher = pat.into_searcher(haystack);
1728 match if !rev { searcher.next() } else { searcher.next_back() } {
1729 Match(a, b) => v.push(Match(a, b)),
1730 Reject(a, b) => v.push(Reject(a, b)),
1738 let mut first_index = 0;
1741 for (i, e) in right.iter().enumerate() {
1743 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1753 if let Some(err) = err {
1754 panic!("Input skipped range at {}", err);
1757 if first_index != haystack.len() {
1758 panic!("Did not cover whole input");
1761 assert_eq!(v, right);
1765 str_searcher_ascii_haystack,
1768 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1771 str_searcher_ascii_haystack_seq,
1774 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1777 str_searcher_empty_needle_ascii_haystack,
1799 str_searcher_multibyte_haystack,
1802 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1805 str_searcher_empty_needle_multibyte_haystack,
1818 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1819 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1821 char_searcher_ascii_haystack,
1835 char_searcher_multibyte_haystack,
1838 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1841 char_searcher_short_haystack,
1844 [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1848 macro_rules! generate_iterator_test {
1852 ($($arg:expr),*) -> [$($t:tt)*];
1855 with $fwd:expr, $bwd:expr;
1861 let res = vec![$($t)*];
1863 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1864 assert_eq!(fwd_vec, res);
1866 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1868 assert_eq!(bwd_vec, res);
1876 ($($arg:expr),*) -> [$($t:tt)*];
1885 let res = vec![$($t)*];
1887 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1888 assert_eq!(fwd_vec, res);
1895 generate_iterator_test! {
1896 double_ended_split {
1897 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1898 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1900 with str::split, str::rsplit;
1903 generate_iterator_test! {
1904 double_ended_split_terminator {
1905 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1907 with str::split_terminator, str::rsplit_terminator;
1910 generate_iterator_test! {
1911 double_ended_matches {
1912 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1914 with str::matches, str::rmatches;
1917 generate_iterator_test! {
1918 double_ended_match_indices {
1919 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1921 with str::match_indices, str::rmatch_indices;
1924 generate_iterator_test! {
1925 not_double_ended_splitn {
1926 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1931 generate_iterator_test! {
1932 not_double_ended_rsplitn {
1933 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1939 fn different_str_pattern_forwarding_lifetimes() {
1940 use std::str::pattern::Pattern;
1944 for<'b> &'b P: Pattern<'a>,
1955 fn test_str_multiline() {
1956 let a: String = "this \
1959 let b: String = "this \
1964 assert_eq!(a, "this is a test".to_string());
1965 assert_eq!(b, "this is another test".to_string());
1969 fn test_str_escapes() {
1972 assert_eq!(x, r"\\"); // extraneous whitespace stripped
1976 fn const_str_ptr() {
1977 const A: [u8; 2] = ['h' as u8, 'i' as u8];
1978 const B: &'static [u8; 2] = &A;
1979 const C: *const u8 = B as *const u8;
1981 // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
1984 let foo = &A as *const u8;
1989 assert_eq!(from_utf8_unchecked(&A), "hi");
1990 assert_eq!(*C, A[0]);
1991 assert_eq!(*(&B[0] as *const u8), A[0]);
1997 let yen: char = '¥'; // 0xa5
1998 let c_cedilla: char = 'ç'; // 0xe7
1999 let thorn: char = 'þ'; // 0xfe
2000 let y_diaeresis: char = 'ÿ'; // 0xff
2001 let pi: char = 'Π'; // 0x3a0
2003 assert_eq!(yen as isize, 0xa5);
2004 assert_eq!(c_cedilla as isize, 0xe7);
2005 assert_eq!(thorn as isize, 0xfe);
2006 assert_eq!(y_diaeresis as isize, 0xff);
2007 assert_eq!(pi as isize, 0x3a0);
2009 assert_eq!(pi as isize, '\u{3a0}' as isize);
2010 assert_eq!('\x0a' as isize, '\n' as isize);
2012 let bhutan: String = "འབྲུག་ཡུལ།".to_string();
2013 let japan: String = "日本".to_string();
2014 let uzbekistan: String = "Ўзбекистон".to_string();
2015 let austria: String = "Österreich".to_string();
2017 let bhutan_e: String =
2018 "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string();
2019 let japan_e: String = "\u{65e5}\u{672c}".to_string();
2020 let uzbekistan_e: String =
2021 "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string();
2022 let austria_e: String = "\u{d6}sterreich".to_string();
2025 assert_eq!(oo as isize, 0xd6);
2027 fn check_str_eq(a: String, b: String) {
2028 let mut i: isize = 0;
2029 for ab in a.bytes() {
2032 let bb: u8 = b.as_bytes()[i as usize];
2039 check_str_eq(bhutan, bhutan_e);
2040 check_str_eq(japan, japan_e);
2041 check_str_eq(uzbekistan, uzbekistan_e);
2042 check_str_eq(austria, austria_e);
2047 // Chars of 1, 2, 3, and 4 bytes
2048 let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}'];
2049 let s: String = chs.iter().cloned().collect();
2050 let schs: Vec<char> = s.chars().collect();
2052 assert_eq!(s.len(), 10);
2053 assert_eq!(s.chars().count(), 4);
2054 assert_eq!(schs.len(), 4);
2055 assert_eq!(schs.iter().cloned().collect::<String>(), s);
2057 assert!((from_utf8(s.as_bytes()).is_ok()));
2059 assert!((!from_utf8(&[0x80]).is_ok()));
2060 // invalid 2 byte prefix
2061 assert!((!from_utf8(&[0xc0]).is_ok()));
2062 assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
2063 // invalid 3 byte prefix
2064 assert!((!from_utf8(&[0xe0]).is_ok()));
2065 assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
2066 assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
2067 // invalid 4 byte prefix
2068 assert!((!from_utf8(&[0xf0]).is_ok()));
2069 assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
2070 assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
2071 assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));