1 use std::assert_matches::assert_matches;
3 use std::cmp::Ordering::{Equal, Greater, Less};
4 use std::str::{from_utf8, from_utf8_unchecked};
10 assert!("foo" <= "foo");
11 assert_ne!("foo", "bar");
16 assert_eq!("hello".find('l'), Some(2));
17 assert_eq!("hello".find(|c: char| c == 'o'), Some(4));
18 assert!("hello".find('x').is_none());
19 assert!("hello".find(|c: char| c == 'x').is_none());
20 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
21 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
26 assert_eq!("hello".rfind('l'), Some(3));
27 assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4));
28 assert!("hello".rfind('x').is_none());
29 assert!("hello".rfind(|c: char| c == 'x').is_none());
30 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
31 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
37 let s: String = empty.chars().collect();
39 let data = "ประเทศไทย中";
40 let s: String = data.chars().collect();
45 fn test_into_bytes() {
46 let data = String::from("asdf");
47 let buf = data.into_bytes();
48 assert_eq!(buf, b"asdf");
54 assert_eq!("".find(""), Some(0));
55 assert!("banana".find("apple pie").is_none());
58 assert_eq!(data[0..6].find("ab"), Some(0));
59 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
60 assert!(data[2..4].find("ab").is_none());
62 let string = "ประเทศไทย中华Việt Nam";
63 let mut data = String::from(string);
64 data.push_str(string);
65 assert!(data.find("ไท华").is_none());
66 assert_eq!(data[0..43].find(""), Some(0));
67 assert_eq!(data[6..43].find(""), Some(6 - 6));
69 assert_eq!(data[0..43].find("ประ"), Some(0));
70 assert_eq!(data[0..43].find("ทศไ"), Some(12));
71 assert_eq!(data[0..43].find("ย中"), Some(24));
72 assert_eq!(data[0..43].find("iệt"), Some(34));
73 assert_eq!(data[0..43].find("Nam"), Some(40));
75 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
76 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
77 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
78 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
79 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
81 // find every substring -- assert that it finds it, or an earlier occurrence.
82 let string = "Việt Namacbaabcaabaaba";
83 for (i, ci) in string.char_indices() {
84 let ip = i + ci.len_utf8();
85 for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) {
86 let pat = &string[i..ip + j];
87 assert!(match string.find(pat) {
91 assert!(match string.rfind(pat) {
99 fn s(x: &str) -> String {
103 macro_rules! test_concat {
104 ($expected: expr, $string: expr) => {{
105 let s: String = $string.concat();
106 assert_eq!($expected, s);
111 fn test_concat_for_different_types() {
112 test_concat!("ab", vec![s("a"), s("b")]);
113 test_concat!("ab", vec!["a", "b"]);
117 fn test_concat_for_different_lengths() {
118 let empty: &[&str] = &[];
119 test_concat!("", empty);
120 test_concat!("a", ["a"]);
121 test_concat!("ab", ["a", "b"]);
122 test_concat!("abc", ["", "a", "bc"]);
125 macro_rules! test_join {
126 ($expected: expr, $string: expr, $delim: expr) => {{
127 let s = $string.join($delim);
128 assert_eq!($expected, s);
133 fn test_join_for_different_types() {
134 test_join!("a-b", ["a", "b"], "-");
135 let hyphen = "-".to_string();
136 test_join!("a-b", [s("a"), s("b")], &*hyphen);
137 test_join!("a-b", vec!["a", "b"], &*hyphen);
138 test_join!("a-b", &*vec!["a", "b"], "-");
139 test_join!("a-b", vec![s("a"), s("b")], "-");
143 fn test_join_for_different_lengths() {
144 let empty: &[&str] = &[];
145 test_join!("", empty, "-");
146 test_join!("a", ["a"], "-");
147 test_join!("a-b", ["a", "b"], "-");
148 test_join!("-a-bc", ["", "a", "bc"], "-");
151 // join has fast paths for small separators up to 4 bytes
152 // this tests the slow paths.
154 fn test_join_for_different_lengths_with_long_separator() {
155 assert_eq!("~~~~~".len(), 15);
157 let empty: &[&str] = &[];
158 test_join!("", empty, "~~~~~");
159 test_join!("a", ["a"], "~~~~~");
160 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
161 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
165 fn test_join_issue_80335() {
166 use core::{borrow::Borrow, cell::Cell};
172 impl Default for WeirdBorrow {
173 fn default() -> Self {
174 WeirdBorrow { state: Cell::new(false) }
178 impl Borrow<str> for WeirdBorrow {
179 fn borrow(&self) -> &str {
180 let state = self.state.get();
184 self.state.set(true);
190 let arr: [WeirdBorrow; 3] = Default::default();
191 test_join!("0-0-0", arr, "-");
195 #[cfg_attr(miri, ignore)] // Miri is too slow
196 fn test_unsafe_slice() {
197 assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) });
198 assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) });
199 assert_eq!("", unsafe { "abc".get_unchecked(1..1) });
200 fn a_million_letter_a() -> String {
202 let mut rs = String::new();
204 rs.push_str("aaaaaaaaaa");
209 fn half_a_million_letter_a() -> String {
211 let mut rs = String::new();
213 rs.push_str("aaaaa");
218 let letters = a_million_letter_a();
219 assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) });
223 fn test_starts_with() {
224 assert!("".starts_with(""));
225 assert!("abc".starts_with(""));
226 assert!("abc".starts_with("a"));
227 assert!(!"a".starts_with("abc"));
228 assert!(!"".starts_with("abc"));
229 assert!(!"ödd".starts_with("-"));
230 assert!("ödd".starts_with("öd"));
234 fn test_ends_with() {
235 assert!("".ends_with(""));
236 assert!("abc".ends_with(""));
237 assert!("abc".ends_with("c"));
238 assert!(!"a".ends_with("abc"));
239 assert!(!"".ends_with("abc"));
240 assert!(!"ddö".ends_with("-"));
241 assert!("ddö".ends_with("dö"));
246 assert!("".is_empty());
247 assert!(!"a".is_empty());
252 assert_eq!("".replacen('a', "b", 5), "");
253 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
254 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
257 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
258 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
259 assert_eq!(" test test ".replacen(test, "", 5), " ");
261 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
267 assert_eq!("".replace(a, "b"), "");
268 assert_eq!("a".replace(a, "b"), "b");
269 assert_eq!("ab".replace(a, "b"), "bb");
271 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
272 assert_eq!(" test test ".replace(test, ""), " ");
276 fn test_replace_2a() {
277 let data = "ประเทศไทย中华";
278 let repl = "دولة الكويت";
281 let a2 = "دولة الكويتทศไทย中华";
282 assert_eq!(data.replace(a, repl), a2);
286 fn test_replace_2b() {
287 let data = "ประเทศไทย中华";
288 let repl = "دولة الكويت";
291 let b2 = "ปรدولة الكويتทศไทย中华";
292 assert_eq!(data.replace(b, repl), b2);
296 fn test_replace_2c() {
297 let data = "ประเทศไทย中华";
298 let repl = "دولة الكويت";
301 let c2 = "ประเทศไทยدولة الكويت";
302 assert_eq!(data.replace(c, repl), c2);
306 fn test_replace_2d() {
307 let data = "ประเทศไทย中华";
308 let repl = "دولة الكويت";
311 assert_eq!(data.replace(d, repl), data);
315 fn test_replace_pattern() {
316 let data = "abcdαβγδabcdαβγδ";
317 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
318 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
319 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
320 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
323 // The current implementation of SliceIndex fails to handle methods
324 // orthogonally from range types; therefore, it is worth testing
325 // all of the indexing operations on each input.
327 // Test a slicing operation **that should succeed,**
328 // testing it on all of the indexing methods.
330 // This is not suitable for testing failure on invalid inputs.
331 macro_rules! assert_range_eq {
332 ($s:expr, $range:expr, $expected:expr) => {
333 let mut s: String = $s.to_owned();
334 let mut expected: String = $expected.to_owned();
337 let expected: &str = &expected;
339 assert_eq!(&s[$range], expected, "(in assertion for: index)");
340 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
343 s.get_unchecked($range),
345 "(in assertion for: get_unchecked)",
350 let s: &mut str = &mut s;
351 let expected: &mut str = &mut expected;
353 assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
356 Some(&mut expected[..]),
357 "(in assertion for: get_mut)",
361 s.get_unchecked_mut($range),
363 "(in assertion for: get_unchecked_mut)",
370 // Make sure the macro can actually detect bugs,
371 // because if it can't, then what are we even doing here?
373 // (Be aware this only demonstrates the ability to detect bugs
374 // in the FIRST method that panics, as the macro is not designed
375 // to be used in `should_panic`)
377 #[should_panic(expected = "out of bounds")]
378 fn assert_range_eq_can_fail_by_panic() {
379 assert_range_eq!("abc", 0..5, "abc");
382 // (Be aware this only demonstrates the ability to detect bugs
383 // in the FIRST method it calls, as the macro is not designed
384 // to be used in `should_panic`)
386 #[should_panic(expected = "==")]
387 fn assert_range_eq_can_fail_by_inequality() {
388 assert_range_eq!("abc", 0..2, "abc");
391 // Generates test cases for bad index operations.
393 // This generates `should_panic` test cases for Index/IndexMut
394 // and `None` test cases for get/get_mut.
395 macro_rules! panic_cases {
397 in mod $case_name:ident {
402 // a similar input for which DATA[input] succeeds, and the corresponding
403 // output str. This helps validate "critical points" where an input range
404 // straddles the boundary between valid and invalid.
405 // (such as the input `len..len`, which is just barely valid)
407 good: data[$good:expr] == $output:expr;
410 bad: data[$bad:expr];
411 message: $expect_msg:expr; // must be a literal
417 let mut v: String = $data.into();
419 $( assert_range_eq!(v, $good, $output); )*
423 assert_eq!(v.get($bad), None, "(in None assertion for get)");
427 let v: &mut str = &mut v;
428 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
433 #[should_panic(expected = $expect_msg)]
435 let v: String = $data.into();
441 #[should_panic(expected = $expect_msg)]
442 fn index_mut_fail() {
443 let mut v: String = $data.into();
444 let v: &mut str = &mut v;
445 let _v = &mut v[$bad];
453 assert_range_eq!("abc", .., "abc");
455 assert_range_eq!("abc", 0..2, "ab");
456 assert_range_eq!("abc", 0..=1, "ab");
457 assert_range_eq!("abc", ..2, "ab");
458 assert_range_eq!("abc", ..=1, "ab");
460 assert_range_eq!("abc", 1..3, "bc");
461 assert_range_eq!("abc", 1..=2, "bc");
462 assert_range_eq!("abc", 1..1, "");
463 assert_range_eq!("abc", 1..=0, "");
467 fn simple_unicode() {
469 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
471 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
472 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
473 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
474 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
476 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
477 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
478 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
480 let data = "ประเทศไทย中华";
481 assert_range_eq!(data, 0..3, "ป");
482 assert_range_eq!(data, 3..6, "ร");
483 assert_range_eq!(data, 3..3, "");
484 assert_range_eq!(data, 30..33, "华");
496 let ss = "中华Việt Nam";
497 assert_range_eq!(ss, 3..6, "华");
498 assert_range_eq!(ss, 6..16, "Việt Nam");
499 assert_range_eq!(ss, 6..=15, "Việt Nam");
500 assert_range_eq!(ss, 6.., "Việt Nam");
502 assert_range_eq!(ss, 0..3, "中");
503 assert_range_eq!(ss, 3..7, "华V");
504 assert_range_eq!(ss, 3..=6, "华V");
505 assert_range_eq!(ss, 3..3, "");
506 assert_range_eq!(ss, 3..=2, "");
510 #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM
511 #[cfg_attr(miri, ignore)] // Miri is too slow
513 fn a_million_letter_x() -> String {
515 let mut rs = String::new();
517 rs.push_str("华华华华华华华华华华");
522 fn half_a_million_letter_x() -> String {
524 let mut rs = String::new();
526 rs.push_str("华华华华华");
531 let letters = a_million_letter_x();
532 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
537 fn test_slice_fail() {
538 let _ = &"中华Việt Nam"[0..2];
542 in mod rangefrom_len {
544 good: data[6..] == "";
546 message: "out of bounds";
551 good: data[..6] == "abcdef";
553 message: "out of bounds";
556 in mod rangetoinclusive_len {
558 good: data[..=5] == "abcdef";
560 message: "out of bounds";
563 in mod rangeinclusive_len {
565 good: data[0..=5] == "abcdef";
567 message: "out of bounds";
570 in mod range_len_len {
572 good: data[6..6] == "";
574 message: "out of bounds";
577 in mod rangeinclusive_len_len {
579 good: data[6..=5] == "";
581 message: "out of bounds";
586 in mod rangeinclusive_exhausted {
589 good: data[0..=5] == "abcdef";
591 let mut iter = 0..=5;
592 iter.by_ref().count(); // exhaust it
596 // 0..=6 is out of bounds before exhaustion, so it
597 // stands to reason that it still would be after.
599 let mut iter = 0..=6;
600 iter.by_ref().count(); // exhaust it
603 message: "out of bounds";
608 in mod range_neg_width {
610 good: data[4..4] == "";
612 message: "begin <= end (4 <= 3)";
615 in mod rangeinclusive_neg_width {
617 good: data[4..=3] == "";
619 message: "begin <= end (4 <= 3)";
625 in mod rangeinclusive {
627 // note: using 0 specifically ensures that the result of overflowing is 0..0,
628 // so that `get` doesn't simply return None for the wrong reason.
629 bad: data[0..=usize::MAX];
630 message: "maximum usize";
633 in mod rangetoinclusive {
635 bad: data[..=usize::MAX];
636 message: "maximum usize";
642 const DATA: &str = "abcαβγ";
644 const BAD_START: usize = 4;
645 const GOOD_START: usize = 3;
646 const BAD_END: usize = 6;
647 const GOOD_END: usize = 7;
648 const BAD_END_INCL: usize = BAD_END - 1;
649 const GOOD_END_INCL: usize = GOOD_END - 1;
651 // it is especially important to test all of the different range types here
652 // because some of the logic may be duplicated as part of micro-optimizations
653 // to dodge unicode boundary checks on half-ranges.
657 bad: data[super::BAD_START..super::GOOD_END];
659 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
664 bad: data[super::GOOD_START..super::BAD_END];
666 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
671 bad: data[super::BAD_START..];
673 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
678 bad: data[..super::BAD_END];
680 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
683 in mod rangeinclusive_1 {
685 bad: data[super::BAD_START..=super::GOOD_END_INCL];
687 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
690 in mod rangeinclusive_2 {
692 bad: data[super::GOOD_START..=super::BAD_END_INCL];
694 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
697 in mod rangetoinclusive {
699 bad: data[..=super::BAD_END_INCL];
701 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
706 const LOREM_PARAGRAPH: &str = "\
707 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
708 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
709 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
710 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
711 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
714 // check the panic includes the prefix of the sliced string
716 #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
717 fn test_slice_fail_truncated_1() {
718 let _ = &LOREM_PARAGRAPH[..1024];
720 // check the truncation in the panic message
722 #[should_panic(expected = "luctus, im`[...]")]
723 fn test_slice_fail_truncated_2() {
724 let _ = &LOREM_PARAGRAPH[..1024];
729 fn test_str_slice_rangetoinclusive_ok() {
731 assert_eq!(&s[..=2], "abc");
732 assert_eq!(&s[..=4], "abcα");
737 fn test_str_slice_rangetoinclusive_notok() {
743 fn test_str_slicemut_rangetoinclusive_ok() {
744 let mut s = "abcαβγ".to_owned();
745 let s: &mut str = &mut s;
746 assert_eq!(&mut s[..=2], "abc");
747 assert_eq!(&mut s[..=4], "abcα");
752 fn test_str_slicemut_rangetoinclusive_notok() {
753 let mut s = "abcαβγ".to_owned();
754 let s: &mut str = &mut s;
755 let _ = &mut s[..=3];
759 fn test_is_char_boundary() {
760 let s = "ศไทย中华Việt Nam β-release 🐱123";
761 assert!(s.is_char_boundary(0));
762 assert!(s.is_char_boundary(s.len()));
763 assert!(!s.is_char_boundary(s.len() + 1));
764 for (i, ch) in s.char_indices() {
765 // ensure character locations are boundaries and continuation bytes are not
766 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
767 for j in 1..ch.len_utf8() {
769 !s.is_char_boundary(i + j),
770 "{} should not be a char boundary in {:?}",
779 fn test_trim_start_matches() {
780 let v: &[char] = &[];
781 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
782 let chars: &[char] = &['*', ' '];
783 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
784 assert_eq!(" *** *** ".trim_start_matches(chars), "");
785 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
787 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
788 let chars: &[char] = &['1', '2'];
789 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
790 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
794 fn test_trim_end_matches() {
795 let v: &[char] = &[];
796 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
797 let chars: &[char] = &['*', ' '];
798 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
799 assert_eq!(" *** *** ".trim_end_matches(chars), "");
800 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
802 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
803 let chars: &[char] = &['1', '2'];
804 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
805 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
809 fn test_trim_matches() {
810 let v: &[char] = &[];
811 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
812 let chars: &[char] = &['*', ' '];
813 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
814 assert_eq!(" *** *** ".trim_matches(chars), "");
815 assert_eq!("foo".trim_matches(chars), "foo");
817 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
818 let chars: &[char] = &['1', '2'];
819 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
820 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
824 fn test_trim_start() {
825 assert_eq!("".trim_start(), "");
826 assert_eq!("a".trim_start(), "a");
827 assert_eq!(" ".trim_start(), "");
828 assert_eq!(" blah".trim_start(), "blah");
829 assert_eq!(" \u{3000} wut".trim_start(), "wut");
830 assert_eq!("hey ".trim_start(), "hey ");
835 assert_eq!("".trim_end(), "");
836 assert_eq!("a".trim_end(), "a");
837 assert_eq!(" ".trim_end(), "");
838 assert_eq!("blah ".trim_end(), "blah");
839 assert_eq!("wut \u{3000} ".trim_end(), "wut");
840 assert_eq!(" hey".trim_end(), " hey");
845 assert_eq!("".trim(), "");
846 assert_eq!("a".trim(), "a");
847 assert_eq!(" ".trim(), "");
848 assert_eq!(" blah ".trim(), "blah");
849 assert_eq!("\nwut \u{3000} ".trim(), "wut");
850 assert_eq!(" hey dude ".trim(), "hey dude");
854 fn test_is_whitespace() {
855 assert!("".chars().all(|c| c.is_whitespace()));
856 assert!(" ".chars().all(|c| c.is_whitespace()));
857 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
858 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
859 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
864 // deny overlong encodings
865 assert!(from_utf8(&[0xc0, 0x80]).is_err());
866 assert!(from_utf8(&[0xc0, 0xae]).is_err());
867 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
868 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
869 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
870 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
871 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
874 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
875 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
877 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
878 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
879 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
880 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
881 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
882 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
883 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
884 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
888 fn test_const_is_utf8() {
890 // deny overlong encodings
891 assert!(from_utf8(&[0xc0, 0x80]).is_err());
892 assert!(from_utf8(&[0xc0, 0xae]).is_err());
893 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
894 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
895 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
896 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
897 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
900 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
901 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
903 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
904 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
905 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
906 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
907 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
908 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
909 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
910 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
915 fn from_utf8_mostly_ascii() {
916 // deny invalid bytes embedded in long stretches of ascii
918 let mut data = [0; 128];
920 assert!(from_utf8(&data).is_err());
922 assert!(from_utf8(&data).is_err());
927 fn const_from_utf8_mostly_ascii() {
929 // deny invalid bytes embedded in long stretches of ascii
932 let mut data = [0; 128];
934 assert!(from_utf8(&data).is_err());
936 assert!(from_utf8(&data).is_err());
944 fn from_utf8_error() {
946 ($input: expr, $expected_valid_up_to:pat, $expected_error_len:pat) => {
947 let error = from_utf8($input).unwrap_err();
948 assert_matches!(error.valid_up_to(), $expected_valid_up_to);
949 assert_matches!(error.error_len(), $expected_error_len);
952 match from_utf8($input) {
954 let valid_up_to = error.valid_up_to();
955 let error_len = error.error_len();
957 assert!(matches!(valid_up_to, $expected_valid_up_to));
958 assert!(matches!(error_len, $expected_error_len));
960 Ok(_) => unreachable!(),
965 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
966 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
967 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
968 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
969 test!(b"A\xC3\xA9 \xC2", 4, None);
970 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
971 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
972 test!(b"A\xC3\xA9 \xE0", 4, None);
973 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
974 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
975 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
976 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
977 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
978 test!(b"A\xC3\xA9 \xF1", 4, None);
979 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
980 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
981 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
982 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
983 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
990 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
991 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
994 assert_eq!("".as_bytes(), b);
995 assert_eq!("abc".as_bytes(), b"abc");
996 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
1001 fn test_as_bytes_fail() {
1002 // Don't double free. (I'm not sure if this exercises the
1003 // original problem code path anymore.)
1004 let s = String::from("");
1005 let _bytes = s.as_bytes();
1011 let buf = "hello".as_ptr();
1013 assert_eq!(*buf.offset(0), b'h');
1014 assert_eq!(*buf.offset(1), b'e');
1015 assert_eq!(*buf.offset(2), b'l');
1016 assert_eq!(*buf.offset(3), b'l');
1017 assert_eq!(*buf.offset(4), b'o');
1022 fn vec_str_conversions() {
1023 let s1: String = String::from("All mimsy were the borogoves");
1025 let v: Vec<u8> = s1.as_bytes().to_vec();
1026 let s2: String = String::from(from_utf8(&v).unwrap());
1032 let a: u8 = s1.as_bytes()[i];
1033 let b: u8 = s2.as_bytes()[i];
1040 fn test_contains() {
1041 assert!("abcde".contains("bcd"));
1042 assert!("abcde".contains("abcd"));
1043 assert!("abcde".contains("bcde"));
1044 assert!("abcde".contains(""));
1045 assert!("".contains(""));
1046 assert!(!"abcde".contains("def"));
1047 assert!(!"".contains("a"));
1049 let data = "ประเทศไทย中华Việt Nam";
1050 assert!(data.contains("ประเ"));
1051 assert!(data.contains("ะเ"));
1052 assert!(data.contains("中华"));
1053 assert!(!data.contains("ไท华"));
1057 fn test_contains_char() {
1058 assert!("abc".contains('b'));
1059 assert!("a".contains('a'));
1060 assert!(!"abc".contains('d'));
1061 assert!(!"".contains('a'));
1065 fn test_split_at() {
1066 let s = "ศไทย中华Việt Nam";
1067 for (index, _) in s.char_indices() {
1068 let (a, b) = s.split_at(index);
1069 assert_eq!(&s[..a.len()], a);
1070 assert_eq!(&s[a.len()..], b);
1072 let (a, b) = s.split_at(s.len());
1078 fn test_split_at_mut() {
1079 let mut s = "Hello World".to_string();
1081 let (a, b) = s.split_at_mut(5);
1082 a.make_ascii_uppercase();
1083 b.make_ascii_lowercase();
1085 assert_eq!(s, "HELLO world");
1090 fn test_split_at_boundscheck() {
1091 let s = "ศไทย中华Việt Nam";
1092 let _ = s.split_at(1);
1096 fn test_escape_unicode() {
1097 assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
1098 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
1099 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
1100 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
1101 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
1102 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
1103 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1104 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1105 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
1109 fn test_escape_debug() {
1110 // Note that there are subtleties with the number of backslashes
1111 // on the left- and right-hand sides. In particular, Unicode code points
1112 // are usually escaped with two backslashes on the right-hand side, as
1113 // they are escaped. However, when the character is unescaped (e.g., for
1114 // printable characters), only a single backslash appears (as the character
1115 // itself appears in the debug string).
1116 assert_eq!("abc".escape_debug().to_string(), "abc");
1117 assert_eq!("a c".escape_debug().to_string(), "a c");
1118 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1119 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1120 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1121 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1122 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1123 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1124 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1125 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1127 "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1128 "\\u{301}a\u{301}bé\\u{e000}"
1133 fn test_escape_default() {
1134 assert_eq!("abc".escape_default().to_string(), "abc");
1135 assert_eq!("a c".escape_default().to_string(), "a c");
1136 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1137 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1138 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1139 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1140 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1141 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1142 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1143 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1147 fn test_total_ord() {
1148 assert_eq!("1234".cmp("123"), Greater);
1149 assert_eq!("123".cmp("1234"), Less);
1150 assert_eq!("1234".cmp("1234"), Equal);
1151 assert_eq!("12345555".cmp("123456"), Less);
1152 assert_eq!("22".cmp("1234"), Greater);
1156 fn test_iterator() {
1157 let s = "ศไทย中华Việt Nam";
1158 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1164 assert_eq!(c, v[pos]);
1167 assert_eq!(pos, v.len());
1168 assert_eq!(s.chars().count(), v.len());
1172 fn test_rev_iterator() {
1173 let s = "ศไทย中华Việt Nam";
1174 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1177 let it = s.chars().rev();
1180 assert_eq!(c, v[pos]);
1183 assert_eq!(pos, v.len());
1187 fn test_to_lowercase_rev_iterator() {
1188 let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ";
1189 let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a'];
1192 let it = s.chars().flat_map(|c| c.to_lowercase()).rev();
1195 assert_eq!(c, v[pos]);
1198 assert_eq!(pos, v.len());
1202 fn test_to_uppercase_rev_iterator() {
1203 let s = "aößü💩στιγμαςDžfiᾀ";
1205 ['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A'];
1208 let it = s.chars().flat_map(|c| c.to_uppercase()).rev();
1211 assert_eq!(c, v[pos]);
1214 assert_eq!(pos, v.len());
1218 #[cfg_attr(miri, ignore)] // Miri is too slow
1219 fn test_chars_decoding() {
1220 let mut bytes = [0; 4];
1221 for c in (0..0x110000).filter_map(std::char::from_u32) {
1222 let s = c.encode_utf8(&mut bytes);
1223 if Some(c) != s.chars().next() {
1224 panic!("character {:x}={} does not decode correctly", c as u32, c);
1230 #[cfg_attr(miri, ignore)] // Miri is too slow
1231 fn test_chars_rev_decoding() {
1232 let mut bytes = [0; 4];
1233 for c in (0..0x110000).filter_map(std::char::from_u32) {
1234 let s = c.encode_utf8(&mut bytes);
1235 if Some(c) != s.chars().rev().next() {
1236 panic!("character {:x}={} does not decode correctly", c as u32, c);
1242 fn test_iterator_clone() {
1243 let s = "ศไทย中华Việt Nam";
1244 let mut it = s.chars();
1246 assert!(it.clone().zip(it).all(|(x, y)| x == y));
1250 fn test_iterator_last() {
1251 let s = "ศไทย中华Việt Nam";
1252 let mut it = s.chars();
1254 assert_eq!(it.last(), Some('m'));
1258 fn test_chars_debug() {
1259 let s = "ศไทย中华Việt Nam";
1263 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1268 fn test_bytesator() {
1269 let s = "ศไทย中华Việt Nam";
1271 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1272 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1276 for b in s.bytes() {
1277 assert_eq!(b, v[pos]);
1283 fn test_bytes_revator() {
1284 let s = "ศไทย中华Việt Nam";
1286 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1287 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1289 let mut pos = v.len();
1291 for b in s.bytes().rev() {
1293 assert_eq!(b, v[pos]);
1298 fn test_bytesator_nth() {
1299 let s = "ศไทย中华Việt Nam";
1301 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1302 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1305 let mut b = s.bytes();
1306 assert_eq!(b.nth(2).unwrap(), v[2]);
1307 assert_eq!(b.nth(10).unwrap(), v[10]);
1308 assert_eq!(b.nth(200), None);
1312 fn test_bytesator_count() {
1313 let s = "ศไทย中华Việt Nam";
1316 assert_eq!(b.count(), 28)
1320 fn test_bytesator_last() {
1321 let s = "ศไทย中华Việt Nam";
1324 assert_eq!(b.last().unwrap(), 109)
1328 fn test_char_indicesator() {
1329 let s = "ศไทย中华Việt Nam";
1330 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1331 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1334 let it = s.char_indices();
1337 assert_eq!(c, (p[pos], v[pos]));
1340 assert_eq!(pos, v.len());
1341 assert_eq!(pos, p.len());
1345 fn test_char_indices_revator() {
1346 let s = "ศไทย中华Việt Nam";
1347 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1348 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1351 let it = s.char_indices().rev();
1354 assert_eq!(c, (p[pos], v[pos]));
1357 assert_eq!(pos, v.len());
1358 assert_eq!(pos, p.len());
1362 fn test_char_indices_last() {
1363 let s = "ศไทย中华Việt Nam";
1364 let mut it = s.char_indices();
1366 assert_eq!(it.last(), Some((27, 'm')));
1370 fn test_splitn_char_iterator() {
1371 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1373 let split: Vec<&str> = data.splitn(4, ' ').collect();
1374 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1376 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1377 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1380 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1381 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1383 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1384 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1388 fn test_split_char_iterator_no_trailing() {
1389 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1391 let split: Vec<&str> = data.split('\n').collect();
1392 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1394 let split: Vec<&str> = data.split_terminator('\n').collect();
1395 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1399 fn test_split_char_iterator_inclusive() {
1400 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1402 let split: Vec<&str> = data.split_inclusive('\n').collect();
1403 assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1405 let uppercase_separated = "SheePSharKTurtlECaT";
1406 let mut first_char = true;
1407 let split: Vec<&str> = uppercase_separated
1408 .split_inclusive(|c: char| {
1409 let split = !first_char && c.is_uppercase();
1414 assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1418 fn test_split_char_iterator_inclusive_rev() {
1419 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1421 let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1422 assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1424 // Note that the predicate is stateful and thus dependent
1425 // on the iteration order.
1426 // (A different predicate is needed for reverse iterator vs normal iterator.)
1427 // Not sure if anything can be done though.
1428 let uppercase_separated = "SheePSharKTurtlECaT";
1429 let mut term_char = true;
1430 let split: Vec<&str> = uppercase_separated
1431 .split_inclusive(|c: char| {
1432 let split = term_char && c.is_uppercase();
1433 term_char = c.is_uppercase();
1438 assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1443 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1445 let split: Vec<&str> = data.rsplit(' ').collect();
1446 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1448 let split: Vec<&str> = data.rsplit("lämb").collect();
1449 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1451 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1452 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1457 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1459 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1460 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1462 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1463 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1465 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1466 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1470 fn test_split_once() {
1471 assert_eq!("".split_once("->"), None);
1472 assert_eq!("-".split_once("->"), None);
1473 assert_eq!("->".split_once("->"), Some(("", "")));
1474 assert_eq!("a->".split_once("->"), Some(("a", "")));
1475 assert_eq!("->b".split_once("->"), Some(("", "b")));
1476 assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1477 assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1478 assert_eq!("---".split_once("--"), Some(("", "-")));
1482 fn test_rsplit_once() {
1483 assert_eq!("".rsplit_once("->"), None);
1484 assert_eq!("-".rsplit_once("->"), None);
1485 assert_eq!("->".rsplit_once("->"), Some(("", "")));
1486 assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1487 assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1488 assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1489 assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1490 assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1494 fn test_split_whitespace() {
1495 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1496 let words: Vec<&str> = data.split_whitespace().collect();
1497 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1502 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1503 let lines: Vec<&str> = data.lines().collect();
1504 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1506 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1507 let lines: Vec<&str> = data.lines().collect();
1508 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1512 fn test_splitator() {
1513 fn t(s: &str, sep: &str, u: &[&str]) {
1514 let v: Vec<&str> = s.split(sep).collect();
1517 t("--1233345--", "12345", &["--1233345--"]);
1518 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1519 t("::hello::there", "::", &["", "hello", "there"]);
1520 t("hello::there::", "::", &["hello", "there", ""]);
1521 t("::hello::there::", "::", &["", "hello", "there", ""]);
1522 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1523 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1524 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1525 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1527 t("zz", "zz", &["", ""]);
1528 t("ok", "z", &["ok"]);
1529 t("zzz", "zz", &["", "z"]);
1530 t("zzzzz", "zz", &["", "", "z"]);
1534 fn test_str_default() {
1535 use std::default::Default;
1537 fn t<S: Default + AsRef<str>>() {
1538 let s: S = Default::default();
1539 assert_eq!(s.as_ref(), "");
1548 fn test_str_container() {
1549 fn sum_len(v: &[&str]) -> usize {
1550 v.iter().map(|x| x.len()).sum()
1554 assert_eq!(5, sum_len(&["012", "", "34"]));
1555 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1556 assert_eq!(5, sum_len(&[s]));
1560 fn test_str_from_utf8() {
1562 assert_eq!(from_utf8(xs), Ok("hello"));
1564 let xs = "ศไทย中华Việt Nam".as_bytes();
1565 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1567 let xs = b"hello\xFF";
1568 assert!(from_utf8(xs).is_err());
1572 fn test_pattern_deref_forward() {
1573 let data = "aabcdaa";
1574 assert!(data.contains("bcd"));
1575 assert!(data.contains(&"bcd"));
1576 assert!(data.contains(&"bcd".to_string()));
1580 fn test_empty_match_indices() {
1582 let vec: Vec<_> = data.match_indices("").collect();
1583 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1587 fn test_bool_from_str() {
1588 assert_eq!("true".parse().ok(), Some(true));
1589 assert_eq!("false".parse().ok(), Some(false));
1590 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1593 fn check_contains_all_substrings(s: &str) {
1594 assert!(s.contains(""));
1595 for i in 0..s.len() {
1596 for j in i + 1..=s.len() {
1597 assert!(s.contains(&s[i..j]));
1603 #[cfg_attr(miri, ignore)] // Miri is too slow
1604 fn strslice_issue_16589() {
1605 assert!("bananas".contains("nana"));
1607 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1608 // test all substrings for good measure
1609 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1613 fn strslice_issue_16878() {
1614 assert!(!"1234567ah012345678901ah".contains("hah"));
1615 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1619 #[cfg_attr(miri, ignore)] // Miri is too slow
1620 fn test_strslice_contains() {
1621 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1622 check_contains_all_substrings(x);
1626 fn test_rsplitn_char_iterator() {
1627 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1629 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1631 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1633 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1635 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1638 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1640 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1642 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1644 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1648 fn test_split_char_iterator() {
1649 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1651 let split: Vec<&str> = data.split(' ').collect();
1652 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1654 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1656 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1658 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1659 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1661 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1663 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1666 let split: Vec<&str> = data.split('ä').collect();
1667 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1669 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1671 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1673 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1674 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1676 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1678 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1682 fn test_rev_split_char_iterator_no_trailing() {
1683 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1685 let mut split: Vec<&str> = data.split('\n').rev().collect();
1687 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1689 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1691 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1695 fn test_utf16_code_units() {
1696 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1700 fn starts_with_in_unicode() {
1701 assert!(!"├── Cargo.toml".starts_with("# "));
1705 fn starts_short_long() {
1706 assert!(!"".starts_with("##"));
1707 assert!(!"##".starts_with("####"));
1708 assert!("####".starts_with("##"));
1709 assert!(!"##ä".starts_with("####"));
1710 assert!("####ä".starts_with("##"));
1711 assert!(!"##".starts_with("####ä"));
1712 assert!("##ä##".starts_with("##ä"));
1714 assert!("".starts_with(""));
1715 assert!("ä".starts_with(""));
1716 assert!("#ä".starts_with(""));
1717 assert!("##ä".starts_with(""));
1718 assert!("ä###".starts_with(""));
1719 assert!("#ä##".starts_with(""));
1720 assert!("##ä#".starts_with(""));
1724 fn contains_weird_cases() {
1725 assert!("* \t".contains(' '));
1726 assert!(!"* \t".contains('?'));
1727 assert!(!"* \t".contains('\u{1F4A9}'));
1732 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1733 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1734 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1735 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1736 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
1737 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1738 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1739 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1740 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1741 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
1746 assert_eq!("".to_lowercase(), "");
1747 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1749 // https://github.com/rust-lang/rust/issues/26035
1750 assert_eq!("ΑΣ".to_lowercase(), "ας");
1751 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1752 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1754 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1755 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1756 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1758 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1759 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1761 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1762 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1764 assert_eq!("Α Σ".to_lowercase(), "α σ");
1765 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1766 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1768 assert_eq!("Σ".to_lowercase(), "σ");
1769 assert_eq!("'Σ".to_lowercase(), "'σ");
1770 assert_eq!("''Σ".to_lowercase(), "''σ");
1772 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1773 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1774 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1779 assert_eq!("".to_uppercase(), "");
1780 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1784 fn test_into_string() {
1785 // The only way to acquire a Box<str> in the first place is through a String, so just
1786 // test that we can round-trip between Box<str> and String.
1787 let string = String::from("Some text goes here");
1788 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1792 fn test_box_slice_clone() {
1793 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1794 let data2 = data.clone().into_boxed_str().clone().into_string();
1796 assert_eq!(data, data2);
1800 fn test_cow_from() {
1801 let borrowed = "borrowed";
1802 let owned = String::from("owned");
1803 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1804 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1805 _ => panic!("invalid `Cow::from`"),
1811 assert_eq!("".repeat(3), "");
1812 assert_eq!("abc".repeat(0), "");
1813 assert_eq!("α".repeat(3), "ααα");
1817 use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1818 use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1820 macro_rules! make_test {
1821 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1822 #[allow(unused_imports)]
1824 use std::str::pattern::SearchStep::{Match, Reject};
1825 use super::{cmp_search_to_vec};
1828 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1832 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1838 fn cmp_search_to_vec<'a>(
1840 pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1842 right: Vec<SearchStep>,
1844 let mut searcher = pat.into_searcher(haystack);
1847 match if !rev { searcher.next() } else { searcher.next_back() } {
1848 Match(a, b) => v.push(Match(a, b)),
1849 Reject(a, b) => v.push(Reject(a, b)),
1857 let mut first_index = 0;
1860 for (i, e) in right.iter().enumerate() {
1862 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1872 if let Some(err) = err {
1873 panic!("Input skipped range at {}", err);
1876 if first_index != haystack.len() {
1877 panic!("Did not cover whole input");
1880 assert_eq!(v, right);
1884 str_searcher_ascii_haystack,
1887 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1890 str_searcher_ascii_haystack_seq,
1893 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1896 str_searcher_empty_needle_ascii_haystack,
1918 str_searcher_multibyte_haystack,
1921 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1924 str_searcher_empty_needle_multibyte_haystack,
1937 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1938 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1940 char_searcher_ascii_haystack,
1954 char_searcher_multibyte_haystack,
1957 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1960 char_searcher_short_haystack,
1963 [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1968 fn str_searcher_empty_needle_after_done() {
1969 // Empty needle and haystack
1971 let mut searcher = "".into_searcher("");
1973 assert_eq!(searcher.next(), SearchStep::Match(0, 0));
1974 assert_eq!(searcher.next(), SearchStep::Done);
1975 assert_eq!(searcher.next(), SearchStep::Done);
1976 assert_eq!(searcher.next(), SearchStep::Done);
1978 let mut searcher = "".into_searcher("");
1980 assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
1981 assert_eq!(searcher.next_back(), SearchStep::Done);
1982 assert_eq!(searcher.next_back(), SearchStep::Done);
1983 assert_eq!(searcher.next_back(), SearchStep::Done);
1985 // Empty needle and non-empty haystack
1987 let mut searcher = "".into_searcher("a");
1989 assert_eq!(searcher.next(), SearchStep::Match(0, 0));
1990 assert_eq!(searcher.next(), SearchStep::Reject(0, 1));
1991 assert_eq!(searcher.next(), SearchStep::Match(1, 1));
1992 assert_eq!(searcher.next(), SearchStep::Done);
1993 assert_eq!(searcher.next(), SearchStep::Done);
1994 assert_eq!(searcher.next(), SearchStep::Done);
1996 let mut searcher = "".into_searcher("a");
1998 assert_eq!(searcher.next_back(), SearchStep::Match(1, 1));
1999 assert_eq!(searcher.next_back(), SearchStep::Reject(0, 1));
2000 assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
2001 assert_eq!(searcher.next_back(), SearchStep::Done);
2002 assert_eq!(searcher.next_back(), SearchStep::Done);
2003 assert_eq!(searcher.next_back(), SearchStep::Done);
2008 macro_rules! generate_iterator_test {
2012 ($($arg:expr),*) -> [$($t:tt)*];
2015 with $fwd:expr, $bwd:expr;
2021 let res = vec![$($t)*];
2023 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
2024 assert_eq!(fwd_vec, res);
2026 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
2028 assert_eq!(bwd_vec, res);
2036 ($($arg:expr),*) -> [$($t:tt)*];
2045 let res = vec![$($t)*];
2047 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
2048 assert_eq!(fwd_vec, res);
2055 generate_iterator_test! {
2056 double_ended_split {
2057 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
2058 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
2060 with str::split, str::rsplit;
2063 generate_iterator_test! {
2064 double_ended_split_terminator {
2065 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
2067 with str::split_terminator, str::rsplit_terminator;
2070 generate_iterator_test! {
2071 double_ended_matches {
2072 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
2074 with str::matches, str::rmatches;
2077 generate_iterator_test! {
2078 double_ended_match_indices {
2079 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
2081 with str::match_indices, str::rmatch_indices;
2084 generate_iterator_test! {
2085 not_double_ended_splitn {
2086 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
2091 generate_iterator_test! {
2092 not_double_ended_rsplitn {
2093 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
2099 fn different_str_pattern_forwarding_lifetimes() {
2100 use std::str::pattern::Pattern;
2104 for<'b> &'b P: Pattern<'a>,
2115 fn test_str_multiline() {
2116 let a: String = "this \
2119 let b: String = "this \
2124 assert_eq!(a, "this is a test".to_string());
2125 assert_eq!(b, "this is another test".to_string());
2129 fn test_str_escapes() {
2132 assert_eq!(x, r"\\"); // extraneous whitespace stripped
2136 fn const_str_ptr() {
2137 const A: [u8; 2] = ['h' as u8, 'i' as u8];
2138 const B: &'static [u8; 2] = &A;
2139 const C: *const u8 = B as *const u8;
2141 // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
2144 let foo = &A as *const u8;
2149 assert_eq!(from_utf8_unchecked(&A), "hi");
2150 assert_eq!(*C, A[0]);
2151 assert_eq!(*(&B[0] as *const u8), A[0]);
2157 let yen: char = '¥'; // 0xa5
2158 let c_cedilla: char = 'ç'; // 0xe7
2159 let thorn: char = 'þ'; // 0xfe
2160 let y_diaeresis: char = 'ÿ'; // 0xff
2161 let pi: char = 'Π'; // 0x3a0
2163 assert_eq!(yen as isize, 0xa5);
2164 assert_eq!(c_cedilla as isize, 0xe7);
2165 assert_eq!(thorn as isize, 0xfe);
2166 assert_eq!(y_diaeresis as isize, 0xff);
2167 assert_eq!(pi as isize, 0x3a0);
2169 assert_eq!(pi as isize, '\u{3a0}' as isize);
2170 assert_eq!('\x0a' as isize, '\n' as isize);
2172 let bhutan: String = "འབྲུག་ཡུལ།".to_string();
2173 let japan: String = "日本".to_string();
2174 let uzbekistan: String = "Ўзбекистон".to_string();
2175 let austria: String = "Österreich".to_string();
2177 let bhutan_e: String =
2178 "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string();
2179 let japan_e: String = "\u{65e5}\u{672c}".to_string();
2180 let uzbekistan_e: String =
2181 "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string();
2182 let austria_e: String = "\u{d6}sterreich".to_string();
2185 assert_eq!(oo as isize, 0xd6);
2187 fn check_str_eq(a: String, b: String) {
2188 let mut i: isize = 0;
2189 for ab in a.bytes() {
2192 let bb: u8 = b.as_bytes()[i as usize];
2199 check_str_eq(bhutan, bhutan_e);
2200 check_str_eq(japan, japan_e);
2201 check_str_eq(uzbekistan, uzbekistan_e);
2202 check_str_eq(austria, austria_e);
2207 // Chars of 1, 2, 3, and 4 bytes
2208 let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}'];
2209 let s: String = chs.iter().cloned().collect();
2210 let schs: Vec<char> = s.chars().collect();
2212 assert_eq!(s.len(), 10);
2213 assert_eq!(s.chars().count(), 4);
2214 assert_eq!(schs.len(), 4);
2215 assert_eq!(schs.iter().cloned().collect::<String>(), s);
2217 assert!((from_utf8(s.as_bytes()).is_ok()));
2219 assert!((!from_utf8(&[0x80]).is_ok()));
2220 // invalid 2 byte prefix
2221 assert!((!from_utf8(&[0xc0]).is_ok()));
2222 assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
2223 // invalid 3 byte prefix
2224 assert!((!from_utf8(&[0xe0]).is_ok()));
2225 assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
2226 assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
2227 // invalid 4 byte prefix
2228 assert!((!from_utf8(&[0xf0]).is_ok()));
2229 assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
2230 assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
2231 assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));
2235 fn utf8_char_counts() {
2236 let strs = [("e", 1), ("é", 1), ("€", 1), ("\u{10000}", 1), ("eé€\u{10000}", 4)];
2238 [8, 64, 256, 512, 1024].iter().copied().flat_map(|n| n - 8..=n + 8).collect::<Vec<usize>>();
2239 if cfg!(not(miri)) {
2241 reps.extend(big - 8..=big + 8);
2243 let counts = if cfg!(miri) { 0..1 } else { 0..8 };
2244 let padding = counts.map(|len| " ".repeat(len)).collect::<Vec<String>>();
2246 for repeat in reps {
2247 for (tmpl_str, tmpl_char_count) in strs {
2248 for pad_start in &padding {
2249 for pad_end in &padding {
2250 // Create a string with padding...
2252 format!("{}{}{}", pad_start, tmpl_str.repeat(repeat), pad_end);
2253 // ...and then skip past that padding. This should ensure
2254 // that we test several different alignments for both head
2256 let si = pad_start.len();
2257 let ei = with_padding.len() - pad_end.len();
2258 let target = &with_padding[si..ei];
2260 assert!(!target.starts_with(" ") && !target.ends_with(" "));
2261 let expected_count = tmpl_char_count * repeat;
2264 target.chars().count(),
2265 "wrong count for `{:?}.repeat({})` (padding: `{:?}`)",
2268 (pad_start.len(), pad_end.len()),