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 fn test_join_isue_80335() {
165 use core::{borrow::Borrow, cell::Cell};
171 impl Default for WeirdBorrow {
172 fn default() -> Self {
173 WeirdBorrow { state: Cell::new(false) }
177 impl Borrow<str> for WeirdBorrow {
178 fn borrow(&self) -> &str {
179 let state = self.state.get();
183 self.state.set(true);
189 let arr: [WeirdBorrow; 3] = Default::default();
190 test_join!("0-0-0", arr, "-");
194 #[cfg_attr(miri, ignore)] // Miri is too slow
195 fn test_unsafe_slice() {
196 assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) });
197 assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) });
198 assert_eq!("", unsafe { "abc".get_unchecked(1..1) });
199 fn a_million_letter_a() -> String {
201 let mut rs = String::new();
203 rs.push_str("aaaaaaaaaa");
208 fn half_a_million_letter_a() -> String {
210 let mut rs = String::new();
212 rs.push_str("aaaaa");
217 let letters = a_million_letter_a();
218 assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) });
222 fn test_starts_with() {
223 assert!("".starts_with(""));
224 assert!("abc".starts_with(""));
225 assert!("abc".starts_with("a"));
226 assert!(!"a".starts_with("abc"));
227 assert!(!"".starts_with("abc"));
228 assert!(!"ödd".starts_with("-"));
229 assert!("ödd".starts_with("öd"));
233 fn test_ends_with() {
234 assert!("".ends_with(""));
235 assert!("abc".ends_with(""));
236 assert!("abc".ends_with("c"));
237 assert!(!"a".ends_with("abc"));
238 assert!(!"".ends_with("abc"));
239 assert!(!"ddö".ends_with("-"));
240 assert!("ddö".ends_with("dö"));
245 assert!("".is_empty());
246 assert!(!"a".is_empty());
251 assert_eq!("".replacen('a', "b", 5), "");
252 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
253 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
256 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
257 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
258 assert_eq!(" test test ".replacen(test, "", 5), " ");
260 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
266 assert_eq!("".replace(a, "b"), "");
267 assert_eq!("a".replace(a, "b"), "b");
268 assert_eq!("ab".replace(a, "b"), "bb");
270 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
271 assert_eq!(" test test ".replace(test, ""), " ");
275 fn test_replace_2a() {
276 let data = "ประเทศไทย中华";
277 let repl = "دولة الكويت";
280 let a2 = "دولة الكويتทศไทย中华";
281 assert_eq!(data.replace(a, repl), a2);
285 fn test_replace_2b() {
286 let data = "ประเทศไทย中华";
287 let repl = "دولة الكويت";
290 let b2 = "ปรدولة الكويتทศไทย中华";
291 assert_eq!(data.replace(b, repl), b2);
295 fn test_replace_2c() {
296 let data = "ประเทศไทย中华";
297 let repl = "دولة الكويت";
300 let c2 = "ประเทศไทยدولة الكويت";
301 assert_eq!(data.replace(c, repl), c2);
305 fn test_replace_2d() {
306 let data = "ประเทศไทย中华";
307 let repl = "دولة الكويت";
310 assert_eq!(data.replace(d, repl), data);
314 fn test_replace_pattern() {
315 let data = "abcdαβγδabcdαβγδ";
316 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
317 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
318 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
319 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
322 // The current implementation of SliceIndex fails to handle methods
323 // orthogonally from range types; therefore, it is worth testing
324 // all of the indexing operations on each input.
326 // Test a slicing operation **that should succeed,**
327 // testing it on all of the indexing methods.
329 // This is not suitable for testing failure on invalid inputs.
330 macro_rules! assert_range_eq {
331 ($s:expr, $range:expr, $expected:expr) => {
332 let mut s: String = $s.to_owned();
333 let mut expected: String = $expected.to_owned();
336 let expected: &str = &expected;
338 assert_eq!(&s[$range], expected, "(in assertion for: index)");
339 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
342 s.get_unchecked($range),
344 "(in assertion for: get_unchecked)",
349 let s: &mut str = &mut s;
350 let expected: &mut str = &mut expected;
352 assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
355 Some(&mut expected[..]),
356 "(in assertion for: get_mut)",
360 s.get_unchecked_mut($range),
362 "(in assertion for: get_unchecked_mut)",
369 // Make sure the macro can actually detect bugs,
370 // because if it can't, then what are we even doing here?
372 // (Be aware this only demonstrates the ability to detect bugs
373 // in the FIRST method that panics, as the macro is not designed
374 // to be used in `should_panic`)
376 #[should_panic(expected = "out of bounds")]
377 fn assert_range_eq_can_fail_by_panic() {
378 assert_range_eq!("abc", 0..5, "abc");
381 // (Be aware this only demonstrates the ability to detect bugs
382 // in the FIRST method it calls, as the macro is not designed
383 // to be used in `should_panic`)
385 #[should_panic(expected = "==")]
386 fn assert_range_eq_can_fail_by_inequality() {
387 assert_range_eq!("abc", 0..2, "abc");
390 // Generates test cases for bad index operations.
392 // This generates `should_panic` test cases for Index/IndexMut
393 // and `None` test cases for get/get_mut.
394 macro_rules! panic_cases {
396 in mod $case_name:ident {
401 // a similar input for which DATA[input] succeeds, and the corresponding
402 // output str. This helps validate "critical points" where an input range
403 // straddles the boundary between valid and invalid.
404 // (such as the input `len..len`, which is just barely valid)
406 good: data[$good:expr] == $output:expr;
409 bad: data[$bad:expr];
410 message: $expect_msg:expr; // must be a literal
416 let mut v: String = $data.into();
418 $( assert_range_eq!(v, $good, $output); )*
422 assert_eq!(v.get($bad), None, "(in None assertion for get)");
426 let v: &mut str = &mut v;
427 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
432 #[should_panic(expected = $expect_msg)]
434 let v: String = $data.into();
440 #[should_panic(expected = $expect_msg)]
441 fn index_mut_fail() {
442 let mut v: String = $data.into();
443 let v: &mut str = &mut v;
444 let _v = &mut v[$bad];
452 assert_range_eq!("abc", .., "abc");
454 assert_range_eq!("abc", 0..2, "ab");
455 assert_range_eq!("abc", 0..=1, "ab");
456 assert_range_eq!("abc", ..2, "ab");
457 assert_range_eq!("abc", ..=1, "ab");
459 assert_range_eq!("abc", 1..3, "bc");
460 assert_range_eq!("abc", 1..=2, "bc");
461 assert_range_eq!("abc", 1..1, "");
462 assert_range_eq!("abc", 1..=0, "");
466 fn simple_unicode() {
468 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
470 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
471 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
472 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
473 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
475 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
476 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
477 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
479 let data = "ประเทศไทย中华";
480 assert_range_eq!(data, 0..3, "ป");
481 assert_range_eq!(data, 3..6, "ร");
482 assert_range_eq!(data, 3..3, "");
483 assert_range_eq!(data, 30..33, "华");
495 let ss = "中华Việt Nam";
496 assert_range_eq!(ss, 3..6, "华");
497 assert_range_eq!(ss, 6..16, "Việt Nam");
498 assert_range_eq!(ss, 6..=15, "Việt Nam");
499 assert_range_eq!(ss, 6.., "Việt Nam");
501 assert_range_eq!(ss, 0..3, "中");
502 assert_range_eq!(ss, 3..7, "华V");
503 assert_range_eq!(ss, 3..=6, "华V");
504 assert_range_eq!(ss, 3..3, "");
505 assert_range_eq!(ss, 3..=2, "");
509 #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM
510 #[cfg_attr(miri, ignore)] // Miri is too slow
512 fn a_million_letter_x() -> String {
514 let mut rs = String::new();
516 rs.push_str("华华华华华华华华华华");
521 fn half_a_million_letter_x() -> String {
523 let mut rs = String::new();
525 rs.push_str("华华华华华");
530 let letters = a_million_letter_x();
531 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
536 fn test_slice_fail() {
537 let _ = &"中华Việt Nam"[0..2];
541 in mod rangefrom_len {
543 good: data[6..] == "";
545 message: "out of bounds";
550 good: data[..6] == "abcdef";
552 message: "out of bounds";
555 in mod rangetoinclusive_len {
557 good: data[..=5] == "abcdef";
559 message: "out of bounds";
562 in mod rangeinclusive_len {
564 good: data[0..=5] == "abcdef";
566 message: "out of bounds";
569 in mod range_len_len {
571 good: data[6..6] == "";
573 message: "out of bounds";
576 in mod rangeinclusive_len_len {
578 good: data[6..=5] == "";
580 message: "out of bounds";
585 in mod rangeinclusive_exhausted {
588 good: data[0..=5] == "abcdef";
590 let mut iter = 0..=5;
591 iter.by_ref().count(); // exhaust it
595 // 0..=6 is out of bounds before exhaustion, so it
596 // stands to reason that it still would be after.
598 let mut iter = 0..=6;
599 iter.by_ref().count(); // exhaust it
602 message: "out of bounds";
607 in mod range_neg_width {
609 good: data[4..4] == "";
611 message: "begin <= end (4 <= 3)";
614 in mod rangeinclusive_neg_width {
616 good: data[4..=3] == "";
618 message: "begin <= end (4 <= 3)";
624 in mod rangeinclusive {
626 // note: using 0 specifically ensures that the result of overflowing is 0..0,
627 // so that `get` doesn't simply return None for the wrong reason.
628 bad: data[0..=usize::MAX];
629 message: "maximum usize";
632 in mod rangetoinclusive {
634 bad: data[..=usize::MAX];
635 message: "maximum usize";
641 const DATA: &str = "abcαβγ";
643 const BAD_START: usize = 4;
644 const GOOD_START: usize = 3;
645 const BAD_END: usize = 6;
646 const GOOD_END: usize = 7;
647 const BAD_END_INCL: usize = BAD_END - 1;
648 const GOOD_END_INCL: usize = GOOD_END - 1;
650 // it is especially important to test all of the different range types here
651 // because some of the logic may be duplicated as part of micro-optimizations
652 // to dodge unicode boundary checks on half-ranges.
656 bad: data[super::BAD_START..super::GOOD_END];
658 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
663 bad: data[super::GOOD_START..super::BAD_END];
665 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
670 bad: data[super::BAD_START..];
672 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
677 bad: data[..super::BAD_END];
679 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
682 in mod rangeinclusive_1 {
684 bad: data[super::BAD_START..=super::GOOD_END_INCL];
686 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
689 in mod rangeinclusive_2 {
691 bad: data[super::GOOD_START..=super::BAD_END_INCL];
693 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
696 in mod rangetoinclusive {
698 bad: data[..=super::BAD_END_INCL];
700 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
705 const LOREM_PARAGRAPH: &str = "\
706 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
707 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
708 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
709 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
710 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
713 // check the panic includes the prefix of the sliced string
715 #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
716 fn test_slice_fail_truncated_1() {
717 let _ = &LOREM_PARAGRAPH[..1024];
719 // check the truncation in the panic message
721 #[should_panic(expected = "luctus, im`[...]")]
722 fn test_slice_fail_truncated_2() {
723 let _ = &LOREM_PARAGRAPH[..1024];
728 fn test_str_slice_rangetoinclusive_ok() {
730 assert_eq!(&s[..=2], "abc");
731 assert_eq!(&s[..=4], "abcα");
736 fn test_str_slice_rangetoinclusive_notok() {
742 fn test_str_slicemut_rangetoinclusive_ok() {
743 let mut s = "abcαβγ".to_owned();
744 let s: &mut str = &mut s;
745 assert_eq!(&mut s[..=2], "abc");
746 assert_eq!(&mut s[..=4], "abcα");
751 fn test_str_slicemut_rangetoinclusive_notok() {
752 let mut s = "abcαβγ".to_owned();
753 let s: &mut str = &mut s;
754 let _ = &mut s[..=3];
758 fn test_is_char_boundary() {
759 let s = "ศไทย中华Việt Nam β-release 🐱123";
760 assert!(s.is_char_boundary(0));
761 assert!(s.is_char_boundary(s.len()));
762 assert!(!s.is_char_boundary(s.len() + 1));
763 for (i, ch) in s.char_indices() {
764 // ensure character locations are boundaries and continuation bytes are not
765 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
766 for j in 1..ch.len_utf8() {
768 !s.is_char_boundary(i + j),
769 "{} should not be a char boundary in {:?}",
778 fn test_trim_start_matches() {
779 let v: &[char] = &[];
780 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
781 let chars: &[char] = &['*', ' '];
782 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
783 assert_eq!(" *** *** ".trim_start_matches(chars), "");
784 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
786 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
787 let chars: &[char] = &['1', '2'];
788 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
789 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
793 fn test_trim_end_matches() {
794 let v: &[char] = &[];
795 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
796 let chars: &[char] = &['*', ' '];
797 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
798 assert_eq!(" *** *** ".trim_end_matches(chars), "");
799 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
801 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
802 let chars: &[char] = &['1', '2'];
803 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
804 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
808 fn test_trim_matches() {
809 let v: &[char] = &[];
810 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
811 let chars: &[char] = &['*', ' '];
812 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
813 assert_eq!(" *** *** ".trim_matches(chars), "");
814 assert_eq!("foo".trim_matches(chars), "foo");
816 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
817 let chars: &[char] = &['1', '2'];
818 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
819 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
823 fn test_trim_start() {
824 assert_eq!("".trim_start(), "");
825 assert_eq!("a".trim_start(), "a");
826 assert_eq!(" ".trim_start(), "");
827 assert_eq!(" blah".trim_start(), "blah");
828 assert_eq!(" \u{3000} wut".trim_start(), "wut");
829 assert_eq!("hey ".trim_start(), "hey ");
834 assert_eq!("".trim_end(), "");
835 assert_eq!("a".trim_end(), "a");
836 assert_eq!(" ".trim_end(), "");
837 assert_eq!("blah ".trim_end(), "blah");
838 assert_eq!("wut \u{3000} ".trim_end(), "wut");
839 assert_eq!(" hey".trim_end(), " hey");
844 assert_eq!("".trim(), "");
845 assert_eq!("a".trim(), "a");
846 assert_eq!(" ".trim(), "");
847 assert_eq!(" blah ".trim(), "blah");
848 assert_eq!("\nwut \u{3000} ".trim(), "wut");
849 assert_eq!(" hey dude ".trim(), "hey dude");
853 fn test_is_whitespace() {
854 assert!("".chars().all(|c| c.is_whitespace()));
855 assert!(" ".chars().all(|c| c.is_whitespace()));
856 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
857 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
858 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
863 // deny overlong encodings
864 assert!(from_utf8(&[0xc0, 0x80]).is_err());
865 assert!(from_utf8(&[0xc0, 0xae]).is_err());
866 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
867 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
868 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
869 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
870 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
873 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
874 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
876 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
877 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
878 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
879 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
880 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
881 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
882 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
883 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
887 fn from_utf8_mostly_ascii() {
888 // deny invalid bytes embedded in long stretches of ascii
890 let mut data = [0; 128];
892 assert!(from_utf8(&data).is_err());
894 assert!(from_utf8(&data).is_err());
899 fn from_utf8_error() {
901 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
902 let error = from_utf8($input).unwrap_err();
903 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
904 assert_eq!(error.error_len(), $expected_error_len);
907 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
908 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
909 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
910 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
911 test!(b"A\xC3\xA9 \xC2", 4, None);
912 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
913 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
914 test!(b"A\xC3\xA9 \xE0", 4, None);
915 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
916 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
917 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
918 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
919 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
920 test!(b"A\xC3\xA9 \xF1", 4, None);
921 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
922 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
923 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
924 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
925 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
932 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
933 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
936 assert_eq!("".as_bytes(), b);
937 assert_eq!("abc".as_bytes(), b"abc");
938 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
943 fn test_as_bytes_fail() {
944 // Don't double free. (I'm not sure if this exercises the
945 // original problem code path anymore.)
946 let s = String::from("");
947 let _bytes = s.as_bytes();
953 let buf = "hello".as_ptr();
955 assert_eq!(*buf.offset(0), b'h');
956 assert_eq!(*buf.offset(1), b'e');
957 assert_eq!(*buf.offset(2), b'l');
958 assert_eq!(*buf.offset(3), b'l');
959 assert_eq!(*buf.offset(4), b'o');
964 fn vec_str_conversions() {
965 let s1: String = String::from("All mimsy were the borogoves");
967 let v: Vec<u8> = s1.as_bytes().to_vec();
968 let s2: String = String::from(from_utf8(&v).unwrap());
974 let a: u8 = s1.as_bytes()[i];
975 let b: u8 = s2.as_bytes()[i];
983 assert!("abcde".contains("bcd"));
984 assert!("abcde".contains("abcd"));
985 assert!("abcde".contains("bcde"));
986 assert!("abcde".contains(""));
987 assert!("".contains(""));
988 assert!(!"abcde".contains("def"));
989 assert!(!"".contains("a"));
991 let data = "ประเทศไทย中华Việt Nam";
992 assert!(data.contains("ประเ"));
993 assert!(data.contains("ะเ"));
994 assert!(data.contains("中华"));
995 assert!(!data.contains("ไท华"));
999 fn test_contains_char() {
1000 assert!("abc".contains('b'));
1001 assert!("a".contains('a'));
1002 assert!(!"abc".contains('d'));
1003 assert!(!"".contains('a'));
1007 fn test_split_at() {
1008 let s = "ศไทย中华Việt Nam";
1009 for (index, _) in s.char_indices() {
1010 let (a, b) = s.split_at(index);
1011 assert_eq!(&s[..a.len()], a);
1012 assert_eq!(&s[a.len()..], b);
1014 let (a, b) = s.split_at(s.len());
1020 fn test_split_at_mut() {
1021 let mut s = "Hello World".to_string();
1023 let (a, b) = s.split_at_mut(5);
1024 a.make_ascii_uppercase();
1025 b.make_ascii_lowercase();
1027 assert_eq!(s, "HELLO world");
1032 fn test_split_at_boundscheck() {
1033 let s = "ศไทย中华Việt Nam";
1038 fn test_escape_unicode() {
1039 assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
1040 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
1041 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
1042 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
1043 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
1044 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
1045 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1046 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1047 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
1051 fn test_escape_debug() {
1052 // Note that there are subtleties with the number of backslashes
1053 // on the left- and right-hand sides. In particular, Unicode code points
1054 // are usually escaped with two backslashes on the right-hand side, as
1055 // they are escaped. However, when the character is unescaped (e.g., for
1056 // printable characters), only a single backslash appears (as the character
1057 // itself appears in the debug string).
1058 assert_eq!("abc".escape_debug().to_string(), "abc");
1059 assert_eq!("a c".escape_debug().to_string(), "a c");
1060 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1061 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1062 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1063 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1064 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1065 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1066 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1067 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1069 "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1070 "\\u{301}a\u{301}bé\\u{e000}"
1075 fn test_escape_default() {
1076 assert_eq!("abc".escape_default().to_string(), "abc");
1077 assert_eq!("a c".escape_default().to_string(), "a c");
1078 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1079 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1080 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1081 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1082 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1083 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1084 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1085 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1089 fn test_total_ord() {
1090 assert_eq!("1234".cmp("123"), Greater);
1091 assert_eq!("123".cmp("1234"), Less);
1092 assert_eq!("1234".cmp("1234"), Equal);
1093 assert_eq!("12345555".cmp("123456"), Less);
1094 assert_eq!("22".cmp("1234"), Greater);
1098 fn test_iterator() {
1099 let s = "ศไทย中华Việt Nam";
1100 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1106 assert_eq!(c, v[pos]);
1109 assert_eq!(pos, v.len());
1110 assert_eq!(s.chars().count(), v.len());
1114 fn test_rev_iterator() {
1115 let s = "ศไทย中华Việt Nam";
1116 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1119 let it = s.chars().rev();
1122 assert_eq!(c, v[pos]);
1125 assert_eq!(pos, v.len());
1129 #[cfg_attr(miri, ignore)] // Miri is too slow
1130 fn test_chars_decoding() {
1131 let mut bytes = [0; 4];
1132 for c in (0..0x110000).filter_map(std::char::from_u32) {
1133 let s = c.encode_utf8(&mut bytes);
1134 if Some(c) != s.chars().next() {
1135 panic!("character {:x}={} does not decode correctly", c as u32, c);
1141 #[cfg_attr(miri, ignore)] // Miri is too slow
1142 fn test_chars_rev_decoding() {
1143 let mut bytes = [0; 4];
1144 for c in (0..0x110000).filter_map(std::char::from_u32) {
1145 let s = c.encode_utf8(&mut bytes);
1146 if Some(c) != s.chars().rev().next() {
1147 panic!("character {:x}={} does not decode correctly", c as u32, c);
1153 fn test_iterator_clone() {
1154 let s = "ศไทย中华Việt Nam";
1155 let mut it = s.chars();
1157 assert!(it.clone().zip(it).all(|(x, y)| x == y));
1161 fn test_iterator_last() {
1162 let s = "ศไทย中华Việt Nam";
1163 let mut it = s.chars();
1165 assert_eq!(it.last(), Some('m'));
1169 fn test_chars_debug() {
1170 let s = "ศไทย中华Việt Nam";
1174 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1179 fn test_bytesator() {
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,
1187 for b in s.bytes() {
1188 assert_eq!(b, v[pos]);
1194 fn test_bytes_revator() {
1195 let s = "ศไทย中华Việt Nam";
1197 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1198 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1200 let mut pos = v.len();
1202 for b in s.bytes().rev() {
1204 assert_eq!(b, v[pos]);
1209 fn test_bytesator_nth() {
1210 let s = "ศไทย中华Việt Nam";
1212 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1213 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1216 let mut b = s.bytes();
1217 assert_eq!(b.nth(2).unwrap(), v[2]);
1218 assert_eq!(b.nth(10).unwrap(), v[10]);
1219 assert_eq!(b.nth(200), None);
1223 fn test_bytesator_count() {
1224 let s = "ศไทย中华Việt Nam";
1227 assert_eq!(b.count(), 28)
1231 fn test_bytesator_last() {
1232 let s = "ศไทย中华Việt Nam";
1235 assert_eq!(b.last().unwrap(), 109)
1239 fn test_char_indicesator() {
1240 let s = "ศไทย中华Việt Nam";
1241 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1242 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1245 let it = s.char_indices();
1248 assert_eq!(c, (p[pos], v[pos]));
1251 assert_eq!(pos, v.len());
1252 assert_eq!(pos, p.len());
1256 fn test_char_indices_revator() {
1257 let s = "ศไทย中华Việt Nam";
1258 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1259 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1262 let it = s.char_indices().rev();
1265 assert_eq!(c, (p[pos], v[pos]));
1268 assert_eq!(pos, v.len());
1269 assert_eq!(pos, p.len());
1273 fn test_char_indices_last() {
1274 let s = "ศไทย中华Việt Nam";
1275 let mut it = s.char_indices();
1277 assert_eq!(it.last(), Some((27, 'm')));
1281 fn test_splitn_char_iterator() {
1282 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1284 let split: Vec<&str> = data.splitn(4, ' ').collect();
1285 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1287 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1288 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1291 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1292 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1294 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1295 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1299 fn test_split_char_iterator_no_trailing() {
1300 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1302 let split: Vec<&str> = data.split('\n').collect();
1303 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1305 let split: Vec<&str> = data.split_terminator('\n').collect();
1306 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1310 fn test_split_char_iterator_inclusive() {
1311 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1313 let split: Vec<&str> = data.split_inclusive('\n').collect();
1314 assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1316 let uppercase_separated = "SheePSharKTurtlECaT";
1317 let mut first_char = true;
1318 let split: Vec<&str> = uppercase_separated
1319 .split_inclusive(|c: char| {
1320 let split = !first_char && c.is_uppercase();
1325 assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1329 fn test_split_char_iterator_inclusive_rev() {
1330 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1332 let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1333 assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1335 // Note that the predicate is stateful and thus dependent
1336 // on the iteration order.
1337 // (A different predicate is needed for reverse iterator vs normal iterator.)
1338 // Not sure if anything can be done though.
1339 let uppercase_separated = "SheePSharKTurtlECaT";
1340 let mut term_char = true;
1341 let split: Vec<&str> = uppercase_separated
1342 .split_inclusive(|c: char| {
1343 let split = term_char && c.is_uppercase();
1344 term_char = c.is_uppercase();
1349 assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1354 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1356 let split: Vec<&str> = data.rsplit(' ').collect();
1357 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1359 let split: Vec<&str> = data.rsplit("lämb").collect();
1360 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1362 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1363 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1368 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1370 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1371 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1373 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1374 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1376 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1377 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1381 fn test_split_once() {
1382 assert_eq!("".split_once("->"), None);
1383 assert_eq!("-".split_once("->"), None);
1384 assert_eq!("->".split_once("->"), Some(("", "")));
1385 assert_eq!("a->".split_once("->"), Some(("a", "")));
1386 assert_eq!("->b".split_once("->"), Some(("", "b")));
1387 assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1388 assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1389 assert_eq!("---".split_once("--"), Some(("", "-")));
1393 fn test_rsplit_once() {
1394 assert_eq!("".rsplit_once("->"), None);
1395 assert_eq!("-".rsplit_once("->"), None);
1396 assert_eq!("->".rsplit_once("->"), Some(("", "")));
1397 assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1398 assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1399 assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1400 assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1401 assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1405 fn test_split_whitespace() {
1406 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1407 let words: Vec<&str> = data.split_whitespace().collect();
1408 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1413 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1414 let lines: Vec<&str> = data.lines().collect();
1415 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1417 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1418 let lines: Vec<&str> = data.lines().collect();
1419 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1423 fn test_splitator() {
1424 fn t(s: &str, sep: &str, u: &[&str]) {
1425 let v: Vec<&str> = s.split(sep).collect();
1428 t("--1233345--", "12345", &["--1233345--"]);
1429 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1430 t("::hello::there", "::", &["", "hello", "there"]);
1431 t("hello::there::", "::", &["hello", "there", ""]);
1432 t("::hello::there::", "::", &["", "hello", "there", ""]);
1433 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1434 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1435 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1436 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1438 t("zz", "zz", &["", ""]);
1439 t("ok", "z", &["ok"]);
1440 t("zzz", "zz", &["", "z"]);
1441 t("zzzzz", "zz", &["", "", "z"]);
1445 fn test_str_default() {
1446 use std::default::Default;
1448 fn t<S: Default + AsRef<str>>() {
1449 let s: S = Default::default();
1450 assert_eq!(s.as_ref(), "");
1459 fn test_str_container() {
1460 fn sum_len(v: &[&str]) -> usize {
1461 v.iter().map(|x| x.len()).sum()
1465 assert_eq!(5, sum_len(&["012", "", "34"]));
1466 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1467 assert_eq!(5, sum_len(&[s]));
1471 fn test_str_from_utf8() {
1473 assert_eq!(from_utf8(xs), Ok("hello"));
1475 let xs = "ศไทย中华Việt Nam".as_bytes();
1476 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1478 let xs = b"hello\xFF";
1479 assert!(from_utf8(xs).is_err());
1483 fn test_pattern_deref_forward() {
1484 let data = "aabcdaa";
1485 assert!(data.contains("bcd"));
1486 assert!(data.contains(&"bcd"));
1487 assert!(data.contains(&"bcd".to_string()));
1491 fn test_empty_match_indices() {
1493 let vec: Vec<_> = data.match_indices("").collect();
1494 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1498 fn test_bool_from_str() {
1499 assert_eq!("true".parse().ok(), Some(true));
1500 assert_eq!("false".parse().ok(), Some(false));
1501 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1504 fn check_contains_all_substrings(s: &str) {
1505 assert!(s.contains(""));
1506 for i in 0..s.len() {
1507 for j in i + 1..=s.len() {
1508 assert!(s.contains(&s[i..j]));
1514 #[cfg_attr(miri, ignore)] // Miri is too slow
1515 fn strslice_issue_16589() {
1516 assert!("bananas".contains("nana"));
1518 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1519 // test all substrings for good measure
1520 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1524 fn strslice_issue_16878() {
1525 assert!(!"1234567ah012345678901ah".contains("hah"));
1526 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1530 #[cfg_attr(miri, ignore)] // Miri is too slow
1531 fn test_strslice_contains() {
1532 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1533 check_contains_all_substrings(x);
1537 fn test_rsplitn_char_iterator() {
1538 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1540 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1542 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1544 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1546 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1549 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1551 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1553 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1555 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1559 fn test_split_char_iterator() {
1560 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1562 let split: Vec<&str> = data.split(' ').collect();
1563 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1565 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1567 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1569 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1570 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1572 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1574 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1577 let split: Vec<&str> = data.split('ä').collect();
1578 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1580 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1582 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1584 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1585 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1587 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1589 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1593 fn test_rev_split_char_iterator_no_trailing() {
1594 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1596 let mut split: Vec<&str> = data.split('\n').rev().collect();
1598 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1600 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1602 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1606 fn test_utf16_code_units() {
1607 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1611 fn starts_with_in_unicode() {
1612 assert!(!"├── Cargo.toml".starts_with("# "));
1616 fn starts_short_long() {
1617 assert!(!"".starts_with("##"));
1618 assert!(!"##".starts_with("####"));
1619 assert!("####".starts_with("##"));
1620 assert!(!"##ä".starts_with("####"));
1621 assert!("####ä".starts_with("##"));
1622 assert!(!"##".starts_with("####ä"));
1623 assert!("##ä##".starts_with("##ä"));
1625 assert!("".starts_with(""));
1626 assert!("ä".starts_with(""));
1627 assert!("#ä".starts_with(""));
1628 assert!("##ä".starts_with(""));
1629 assert!("ä###".starts_with(""));
1630 assert!("#ä##".starts_with(""));
1631 assert!("##ä#".starts_with(""));
1635 fn contains_weird_cases() {
1636 assert!("* \t".contains(' '));
1637 assert!(!"* \t".contains('?'));
1638 assert!(!"* \t".contains('\u{1F4A9}'));
1643 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1644 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1645 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1646 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1647 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
1648 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1649 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1650 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1651 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1652 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
1657 assert_eq!("".to_lowercase(), "");
1658 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1660 // https://github.com/rust-lang/rust/issues/26035
1661 assert_eq!("ΑΣ".to_lowercase(), "ας");
1662 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1663 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1665 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1666 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1667 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1669 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1670 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1672 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1673 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1675 assert_eq!("Α Σ".to_lowercase(), "α σ");
1676 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1677 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1679 assert_eq!("Σ".to_lowercase(), "σ");
1680 assert_eq!("'Σ".to_lowercase(), "'σ");
1681 assert_eq!("''Σ".to_lowercase(), "''σ");
1683 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1684 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1685 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1690 assert_eq!("".to_uppercase(), "");
1691 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1695 fn test_into_string() {
1696 // The only way to acquire a Box<str> in the first place is through a String, so just
1697 // test that we can round-trip between Box<str> and String.
1698 let string = String::from("Some text goes here");
1699 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1703 fn test_box_slice_clone() {
1704 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1705 let data2 = data.clone().into_boxed_str().clone().into_string();
1707 assert_eq!(data, data2);
1711 fn test_cow_from() {
1712 let borrowed = "borrowed";
1713 let owned = String::from("owned");
1714 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1715 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1716 _ => panic!("invalid `Cow::from`"),
1722 assert_eq!("".repeat(3), "");
1723 assert_eq!("abc".repeat(0), "");
1724 assert_eq!("α".repeat(3), "ααα");
1728 use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1729 use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1731 macro_rules! make_test {
1732 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1733 #[allow(unused_imports)]
1735 use std::str::pattern::SearchStep::{Match, Reject};
1736 use super::{cmp_search_to_vec};
1739 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1743 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1749 fn cmp_search_to_vec<'a>(
1751 pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1753 right: Vec<SearchStep>,
1755 let mut searcher = pat.into_searcher(haystack);
1758 match if !rev { searcher.next() } else { searcher.next_back() } {
1759 Match(a, b) => v.push(Match(a, b)),
1760 Reject(a, b) => v.push(Reject(a, b)),
1768 let mut first_index = 0;
1771 for (i, e) in right.iter().enumerate() {
1773 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1783 if let Some(err) = err {
1784 panic!("Input skipped range at {}", err);
1787 if first_index != haystack.len() {
1788 panic!("Did not cover whole input");
1791 assert_eq!(v, right);
1795 str_searcher_ascii_haystack,
1798 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1801 str_searcher_ascii_haystack_seq,
1804 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1807 str_searcher_empty_needle_ascii_haystack,
1829 str_searcher_multibyte_haystack,
1832 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1835 str_searcher_empty_needle_multibyte_haystack,
1848 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1849 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1851 char_searcher_ascii_haystack,
1865 char_searcher_multibyte_haystack,
1868 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1871 char_searcher_short_haystack,
1874 [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1878 macro_rules! generate_iterator_test {
1882 ($($arg:expr),*) -> [$($t:tt)*];
1885 with $fwd:expr, $bwd:expr;
1891 let res = vec![$($t)*];
1893 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1894 assert_eq!(fwd_vec, res);
1896 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1898 assert_eq!(bwd_vec, res);
1906 ($($arg:expr),*) -> [$($t:tt)*];
1915 let res = vec![$($t)*];
1917 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1918 assert_eq!(fwd_vec, res);
1925 generate_iterator_test! {
1926 double_ended_split {
1927 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1928 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1930 with str::split, str::rsplit;
1933 generate_iterator_test! {
1934 double_ended_split_terminator {
1935 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1937 with str::split_terminator, str::rsplit_terminator;
1940 generate_iterator_test! {
1941 double_ended_matches {
1942 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1944 with str::matches, str::rmatches;
1947 generate_iterator_test! {
1948 double_ended_match_indices {
1949 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1951 with str::match_indices, str::rmatch_indices;
1954 generate_iterator_test! {
1955 not_double_ended_splitn {
1956 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1961 generate_iterator_test! {
1962 not_double_ended_rsplitn {
1963 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1969 fn different_str_pattern_forwarding_lifetimes() {
1970 use std::str::pattern::Pattern;
1974 for<'b> &'b P: Pattern<'a>,
1985 fn test_str_multiline() {
1986 let a: String = "this \
1989 let b: String = "this \
1994 assert_eq!(a, "this is a test".to_string());
1995 assert_eq!(b, "this is another test".to_string());
1999 fn test_str_escapes() {
2002 assert_eq!(x, r"\\"); // extraneous whitespace stripped
2006 fn const_str_ptr() {
2007 const A: [u8; 2] = ['h' as u8, 'i' as u8];
2008 const B: &'static [u8; 2] = &A;
2009 const C: *const u8 = B as *const u8;
2011 // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
2014 let foo = &A as *const u8;
2019 assert_eq!(from_utf8_unchecked(&A), "hi");
2020 assert_eq!(*C, A[0]);
2021 assert_eq!(*(&B[0] as *const u8), A[0]);
2027 let yen: char = '¥'; // 0xa5
2028 let c_cedilla: char = 'ç'; // 0xe7
2029 let thorn: char = 'þ'; // 0xfe
2030 let y_diaeresis: char = 'ÿ'; // 0xff
2031 let pi: char = 'Π'; // 0x3a0
2033 assert_eq!(yen as isize, 0xa5);
2034 assert_eq!(c_cedilla as isize, 0xe7);
2035 assert_eq!(thorn as isize, 0xfe);
2036 assert_eq!(y_diaeresis as isize, 0xff);
2037 assert_eq!(pi as isize, 0x3a0);
2039 assert_eq!(pi as isize, '\u{3a0}' as isize);
2040 assert_eq!('\x0a' as isize, '\n' as isize);
2042 let bhutan: String = "འབྲུག་ཡུལ།".to_string();
2043 let japan: String = "日本".to_string();
2044 let uzbekistan: String = "Ўзбекистон".to_string();
2045 let austria: String = "Österreich".to_string();
2047 let bhutan_e: String =
2048 "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string();
2049 let japan_e: String = "\u{65e5}\u{672c}".to_string();
2050 let uzbekistan_e: String =
2051 "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string();
2052 let austria_e: String = "\u{d6}sterreich".to_string();
2055 assert_eq!(oo as isize, 0xd6);
2057 fn check_str_eq(a: String, b: String) {
2058 let mut i: isize = 0;
2059 for ab in a.bytes() {
2062 let bb: u8 = b.as_bytes()[i as usize];
2069 check_str_eq(bhutan, bhutan_e);
2070 check_str_eq(japan, japan_e);
2071 check_str_eq(uzbekistan, uzbekistan_e);
2072 check_str_eq(austria, austria_e);
2077 // Chars of 1, 2, 3, and 4 bytes
2078 let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}'];
2079 let s: String = chs.iter().cloned().collect();
2080 let schs: Vec<char> = s.chars().collect();
2082 assert_eq!(s.len(), 10);
2083 assert_eq!(s.chars().count(), 4);
2084 assert_eq!(schs.len(), 4);
2085 assert_eq!(schs.iter().cloned().collect::<String>(), s);
2087 assert!((from_utf8(s.as_bytes()).is_ok()));
2089 assert!((!from_utf8(&[0x80]).is_ok()));
2090 // invalid 2 byte prefix
2091 assert!((!from_utf8(&[0xc0]).is_ok()));
2092 assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
2093 // invalid 3 byte prefix
2094 assert!((!from_utf8(&[0xe0]).is_ok()));
2095 assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
2096 assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
2097 // invalid 4 byte prefix
2098 assert!((!from_utf8(&[0xf0]).is_ok()));
2099 assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
2100 assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
2101 assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));