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 fn test_to_lowercase_rev_iterator() {
1130 let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ";
1131 let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a'];
1134 let it = s.chars().flat_map(|c| c.to_lowercase()).rev();
1137 assert_eq!(c, v[pos]);
1140 assert_eq!(pos, v.len());
1144 fn test_to_uppercase_rev_iterator() {
1145 let s = "aößü💩στιγμαςDžfiᾀ";
1147 ['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A'];
1150 let it = s.chars().flat_map(|c| c.to_uppercase()).rev();
1153 assert_eq!(c, v[pos]);
1156 assert_eq!(pos, v.len());
1160 #[cfg_attr(miri, ignore)] // Miri is too slow
1161 fn test_chars_decoding() {
1162 let mut bytes = [0; 4];
1163 for c in (0..0x110000).filter_map(std::char::from_u32) {
1164 let s = c.encode_utf8(&mut bytes);
1165 if Some(c) != s.chars().next() {
1166 panic!("character {:x}={} does not decode correctly", c as u32, c);
1172 #[cfg_attr(miri, ignore)] // Miri is too slow
1173 fn test_chars_rev_decoding() {
1174 let mut bytes = [0; 4];
1175 for c in (0..0x110000).filter_map(std::char::from_u32) {
1176 let s = c.encode_utf8(&mut bytes);
1177 if Some(c) != s.chars().rev().next() {
1178 panic!("character {:x}={} does not decode correctly", c as u32, c);
1184 fn test_iterator_clone() {
1185 let s = "ศไทย中华Việt Nam";
1186 let mut it = s.chars();
1188 assert!(it.clone().zip(it).all(|(x, y)| x == y));
1192 fn test_iterator_last() {
1193 let s = "ศไทย中华Việt Nam";
1194 let mut it = s.chars();
1196 assert_eq!(it.last(), Some('m'));
1200 fn test_chars_debug() {
1201 let s = "ศไทย中华Việt Nam";
1205 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1210 fn test_bytesator() {
1211 let s = "ศไทย中华Việt Nam";
1213 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1214 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1218 for b in s.bytes() {
1219 assert_eq!(b, v[pos]);
1225 fn test_bytes_revator() {
1226 let s = "ศไทย中华Việt Nam";
1228 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1229 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1231 let mut pos = v.len();
1233 for b in s.bytes().rev() {
1235 assert_eq!(b, v[pos]);
1240 fn test_bytesator_nth() {
1241 let s = "ศไทย中华Việt Nam";
1243 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1244 86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1247 let mut b = s.bytes();
1248 assert_eq!(b.nth(2).unwrap(), v[2]);
1249 assert_eq!(b.nth(10).unwrap(), v[10]);
1250 assert_eq!(b.nth(200), None);
1254 fn test_bytesator_count() {
1255 let s = "ศไทย中华Việt Nam";
1258 assert_eq!(b.count(), 28)
1262 fn test_bytesator_last() {
1263 let s = "ศไทย中华Việt Nam";
1266 assert_eq!(b.last().unwrap(), 109)
1270 fn test_char_indicesator() {
1271 let s = "ศไทย中华Việt Nam";
1272 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1273 let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1276 let it = s.char_indices();
1279 assert_eq!(c, (p[pos], v[pos]));
1282 assert_eq!(pos, v.len());
1283 assert_eq!(pos, p.len());
1287 fn test_char_indices_revator() {
1288 let s = "ศไทย中华Việt Nam";
1289 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1290 let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1293 let it = s.char_indices().rev();
1296 assert_eq!(c, (p[pos], v[pos]));
1299 assert_eq!(pos, v.len());
1300 assert_eq!(pos, p.len());
1304 fn test_char_indices_last() {
1305 let s = "ศไทย中华Việt Nam";
1306 let mut it = s.char_indices();
1308 assert_eq!(it.last(), Some((27, 'm')));
1312 fn test_splitn_char_iterator() {
1313 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1315 let split: Vec<&str> = data.splitn(4, ' ').collect();
1316 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1318 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1319 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1322 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1323 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1325 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1326 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1330 fn test_split_char_iterator_no_trailing() {
1331 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1333 let split: Vec<&str> = data.split('\n').collect();
1334 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1336 let split: Vec<&str> = data.split_terminator('\n').collect();
1337 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1341 fn test_split_char_iterator_inclusive() {
1342 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1344 let split: Vec<&str> = data.split_inclusive('\n').collect();
1345 assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1347 let uppercase_separated = "SheePSharKTurtlECaT";
1348 let mut first_char = true;
1349 let split: Vec<&str> = uppercase_separated
1350 .split_inclusive(|c: char| {
1351 let split = !first_char && c.is_uppercase();
1356 assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1360 fn test_split_char_iterator_inclusive_rev() {
1361 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1363 let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1364 assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1366 // Note that the predicate is stateful and thus dependent
1367 // on the iteration order.
1368 // (A different predicate is needed for reverse iterator vs normal iterator.)
1369 // Not sure if anything can be done though.
1370 let uppercase_separated = "SheePSharKTurtlECaT";
1371 let mut term_char = true;
1372 let split: Vec<&str> = uppercase_separated
1373 .split_inclusive(|c: char| {
1374 let split = term_char && c.is_uppercase();
1375 term_char = c.is_uppercase();
1380 assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1385 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1387 let split: Vec<&str> = data.rsplit(' ').collect();
1388 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1390 let split: Vec<&str> = data.rsplit("lämb").collect();
1391 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1393 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1394 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1399 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1401 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1402 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1404 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1405 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1407 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1408 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1412 fn test_split_once() {
1413 assert_eq!("".split_once("->"), None);
1414 assert_eq!("-".split_once("->"), None);
1415 assert_eq!("->".split_once("->"), Some(("", "")));
1416 assert_eq!("a->".split_once("->"), Some(("a", "")));
1417 assert_eq!("->b".split_once("->"), Some(("", "b")));
1418 assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1419 assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1420 assert_eq!("---".split_once("--"), Some(("", "-")));
1424 fn test_rsplit_once() {
1425 assert_eq!("".rsplit_once("->"), None);
1426 assert_eq!("-".rsplit_once("->"), None);
1427 assert_eq!("->".rsplit_once("->"), Some(("", "")));
1428 assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1429 assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1430 assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1431 assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1432 assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1436 fn test_split_whitespace() {
1437 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1438 let words: Vec<&str> = data.split_whitespace().collect();
1439 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1444 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1445 let lines: Vec<&str> = data.lines().collect();
1446 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1448 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1449 let lines: Vec<&str> = data.lines().collect();
1450 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1454 fn test_splitator() {
1455 fn t(s: &str, sep: &str, u: &[&str]) {
1456 let v: Vec<&str> = s.split(sep).collect();
1459 t("--1233345--", "12345", &["--1233345--"]);
1460 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1461 t("::hello::there", "::", &["", "hello", "there"]);
1462 t("hello::there::", "::", &["hello", "there", ""]);
1463 t("::hello::there::", "::", &["", "hello", "there", ""]);
1464 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1465 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1466 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1467 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1469 t("zz", "zz", &["", ""]);
1470 t("ok", "z", &["ok"]);
1471 t("zzz", "zz", &["", "z"]);
1472 t("zzzzz", "zz", &["", "", "z"]);
1476 fn test_str_default() {
1477 use std::default::Default;
1479 fn t<S: Default + AsRef<str>>() {
1480 let s: S = Default::default();
1481 assert_eq!(s.as_ref(), "");
1490 fn test_str_container() {
1491 fn sum_len(v: &[&str]) -> usize {
1492 v.iter().map(|x| x.len()).sum()
1496 assert_eq!(5, sum_len(&["012", "", "34"]));
1497 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1498 assert_eq!(5, sum_len(&[s]));
1502 fn test_str_from_utf8() {
1504 assert_eq!(from_utf8(xs), Ok("hello"));
1506 let xs = "ศไทย中华Việt Nam".as_bytes();
1507 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1509 let xs = b"hello\xFF";
1510 assert!(from_utf8(xs).is_err());
1514 fn test_pattern_deref_forward() {
1515 let data = "aabcdaa";
1516 assert!(data.contains("bcd"));
1517 assert!(data.contains(&"bcd"));
1518 assert!(data.contains(&"bcd".to_string()));
1522 fn test_empty_match_indices() {
1524 let vec: Vec<_> = data.match_indices("").collect();
1525 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1529 fn test_bool_from_str() {
1530 assert_eq!("true".parse().ok(), Some(true));
1531 assert_eq!("false".parse().ok(), Some(false));
1532 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1535 fn check_contains_all_substrings(s: &str) {
1536 assert!(s.contains(""));
1537 for i in 0..s.len() {
1538 for j in i + 1..=s.len() {
1539 assert!(s.contains(&s[i..j]));
1545 #[cfg_attr(miri, ignore)] // Miri is too slow
1546 fn strslice_issue_16589() {
1547 assert!("bananas".contains("nana"));
1549 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1550 // test all substrings for good measure
1551 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1555 fn strslice_issue_16878() {
1556 assert!(!"1234567ah012345678901ah".contains("hah"));
1557 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1561 #[cfg_attr(miri, ignore)] // Miri is too slow
1562 fn test_strslice_contains() {
1563 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1564 check_contains_all_substrings(x);
1568 fn test_rsplitn_char_iterator() {
1569 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1571 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1573 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1575 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1577 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1580 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1582 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1584 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1586 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1590 fn test_split_char_iterator() {
1591 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1593 let split: Vec<&str> = data.split(' ').collect();
1594 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1596 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1598 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1600 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1601 assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1603 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1605 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1608 let split: Vec<&str> = data.split('ä').collect();
1609 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1611 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1613 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1615 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1616 assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1618 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1620 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1624 fn test_rev_split_char_iterator_no_trailing() {
1625 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1627 let mut split: Vec<&str> = data.split('\n').rev().collect();
1629 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1631 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1633 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1637 fn test_utf16_code_units() {
1638 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1642 fn starts_with_in_unicode() {
1643 assert!(!"├── Cargo.toml".starts_with("# "));
1647 fn starts_short_long() {
1648 assert!(!"".starts_with("##"));
1649 assert!(!"##".starts_with("####"));
1650 assert!("####".starts_with("##"));
1651 assert!(!"##ä".starts_with("####"));
1652 assert!("####ä".starts_with("##"));
1653 assert!(!"##".starts_with("####ä"));
1654 assert!("##ä##".starts_with("##ä"));
1656 assert!("".starts_with(""));
1657 assert!("ä".starts_with(""));
1658 assert!("#ä".starts_with(""));
1659 assert!("##ä".starts_with(""));
1660 assert!("ä###".starts_with(""));
1661 assert!("#ä##".starts_with(""));
1662 assert!("##ä#".starts_with(""));
1666 fn contains_weird_cases() {
1667 assert!("* \t".contains(' '));
1668 assert!(!"* \t".contains('?'));
1669 assert!(!"* \t".contains('\u{1F4A9}'));
1674 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1675 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1676 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t ");
1677 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a");
1678 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a");
1679 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1680 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1681 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), "");
1682 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), "");
1683 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), "");
1688 assert_eq!("".to_lowercase(), "");
1689 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1691 // https://github.com/rust-lang/rust/issues/26035
1692 assert_eq!("ΑΣ".to_lowercase(), "ας");
1693 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1694 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1696 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1697 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1698 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1700 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1701 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1703 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1704 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1706 assert_eq!("Α Σ".to_lowercase(), "α σ");
1707 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1708 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1710 assert_eq!("Σ".to_lowercase(), "σ");
1711 assert_eq!("'Σ".to_lowercase(), "'σ");
1712 assert_eq!("''Σ".to_lowercase(), "''σ");
1714 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1715 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1716 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1721 assert_eq!("".to_uppercase(), "");
1722 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1726 fn test_into_string() {
1727 // The only way to acquire a Box<str> in the first place is through a String, so just
1728 // test that we can round-trip between Box<str> and String.
1729 let string = String::from("Some text goes here");
1730 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1734 fn test_box_slice_clone() {
1735 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1736 let data2 = data.clone().into_boxed_str().clone().into_string();
1738 assert_eq!(data, data2);
1742 fn test_cow_from() {
1743 let borrowed = "borrowed";
1744 let owned = String::from("owned");
1745 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1746 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1747 _ => panic!("invalid `Cow::from`"),
1753 assert_eq!("".repeat(3), "");
1754 assert_eq!("abc".repeat(0), "");
1755 assert_eq!("α".repeat(3), "ααα");
1759 use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1760 use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1762 macro_rules! make_test {
1763 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1764 #[allow(unused_imports)]
1766 use std::str::pattern::SearchStep::{Match, Reject};
1767 use super::{cmp_search_to_vec};
1770 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1774 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1780 fn cmp_search_to_vec<'a>(
1782 pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1784 right: Vec<SearchStep>,
1786 let mut searcher = pat.into_searcher(haystack);
1789 match if !rev { searcher.next() } else { searcher.next_back() } {
1790 Match(a, b) => v.push(Match(a, b)),
1791 Reject(a, b) => v.push(Reject(a, b)),
1799 let mut first_index = 0;
1802 for (i, e) in right.iter().enumerate() {
1804 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1814 if let Some(err) = err {
1815 panic!("Input skipped range at {}", err);
1818 if first_index != haystack.len() {
1819 panic!("Did not cover whole input");
1822 assert_eq!(v, right);
1826 str_searcher_ascii_haystack,
1829 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1832 str_searcher_ascii_haystack_seq,
1835 [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1838 str_searcher_empty_needle_ascii_haystack,
1860 str_searcher_multibyte_haystack,
1863 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1866 str_searcher_empty_needle_multibyte_haystack,
1879 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1880 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1882 char_searcher_ascii_haystack,
1896 char_searcher_multibyte_haystack,
1899 [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1902 char_searcher_short_haystack,
1905 [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1910 fn str_searcher_empty_needle_after_done() {
1911 // Empty needle and haystack
1913 let mut searcher = "".into_searcher("");
1915 assert_eq!(searcher.next(), SearchStep::Match(0, 0));
1916 assert_eq!(searcher.next(), SearchStep::Done);
1917 assert_eq!(searcher.next(), SearchStep::Done);
1918 assert_eq!(searcher.next(), SearchStep::Done);
1920 let mut searcher = "".into_searcher("");
1922 assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
1923 assert_eq!(searcher.next_back(), SearchStep::Done);
1924 assert_eq!(searcher.next_back(), SearchStep::Done);
1925 assert_eq!(searcher.next_back(), SearchStep::Done);
1927 // Empty needle and non-empty haystack
1929 let mut searcher = "".into_searcher("a");
1931 assert_eq!(searcher.next(), SearchStep::Match(0, 0));
1932 assert_eq!(searcher.next(), SearchStep::Reject(0, 1));
1933 assert_eq!(searcher.next(), SearchStep::Match(1, 1));
1934 assert_eq!(searcher.next(), SearchStep::Done);
1935 assert_eq!(searcher.next(), SearchStep::Done);
1936 assert_eq!(searcher.next(), SearchStep::Done);
1938 let mut searcher = "".into_searcher("a");
1940 assert_eq!(searcher.next_back(), SearchStep::Match(1, 1));
1941 assert_eq!(searcher.next_back(), SearchStep::Reject(0, 1));
1942 assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
1943 assert_eq!(searcher.next_back(), SearchStep::Done);
1944 assert_eq!(searcher.next_back(), SearchStep::Done);
1945 assert_eq!(searcher.next_back(), SearchStep::Done);
1950 macro_rules! generate_iterator_test {
1954 ($($arg:expr),*) -> [$($t:tt)*];
1957 with $fwd:expr, $bwd:expr;
1963 let res = vec![$($t)*];
1965 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1966 assert_eq!(fwd_vec, res);
1968 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1970 assert_eq!(bwd_vec, res);
1978 ($($arg:expr),*) -> [$($t:tt)*];
1987 let res = vec![$($t)*];
1989 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1990 assert_eq!(fwd_vec, res);
1997 generate_iterator_test! {
1998 double_ended_split {
1999 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
2000 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
2002 with str::split, str::rsplit;
2005 generate_iterator_test! {
2006 double_ended_split_terminator {
2007 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
2009 with str::split_terminator, str::rsplit_terminator;
2012 generate_iterator_test! {
2013 double_ended_matches {
2014 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
2016 with str::matches, str::rmatches;
2019 generate_iterator_test! {
2020 double_ended_match_indices {
2021 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
2023 with str::match_indices, str::rmatch_indices;
2026 generate_iterator_test! {
2027 not_double_ended_splitn {
2028 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
2033 generate_iterator_test! {
2034 not_double_ended_rsplitn {
2035 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
2041 fn different_str_pattern_forwarding_lifetimes() {
2042 use std::str::pattern::Pattern;
2046 for<'b> &'b P: Pattern<'a>,
2057 fn test_str_multiline() {
2058 let a: String = "this \
2061 let b: String = "this \
2066 assert_eq!(a, "this is a test".to_string());
2067 assert_eq!(b, "this is another test".to_string());
2071 fn test_str_escapes() {
2074 assert_eq!(x, r"\\"); // extraneous whitespace stripped
2078 fn const_str_ptr() {
2079 const A: [u8; 2] = ['h' as u8, 'i' as u8];
2080 const B: &'static [u8; 2] = &A;
2081 const C: *const u8 = B as *const u8;
2083 // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
2086 let foo = &A as *const u8;
2091 assert_eq!(from_utf8_unchecked(&A), "hi");
2092 assert_eq!(*C, A[0]);
2093 assert_eq!(*(&B[0] as *const u8), A[0]);
2099 let yen: char = '¥'; // 0xa5
2100 let c_cedilla: char = 'ç'; // 0xe7
2101 let thorn: char = 'þ'; // 0xfe
2102 let y_diaeresis: char = 'ÿ'; // 0xff
2103 let pi: char = 'Π'; // 0x3a0
2105 assert_eq!(yen as isize, 0xa5);
2106 assert_eq!(c_cedilla as isize, 0xe7);
2107 assert_eq!(thorn as isize, 0xfe);
2108 assert_eq!(y_diaeresis as isize, 0xff);
2109 assert_eq!(pi as isize, 0x3a0);
2111 assert_eq!(pi as isize, '\u{3a0}' as isize);
2112 assert_eq!('\x0a' as isize, '\n' as isize);
2114 let bhutan: String = "འབྲུག་ཡུལ།".to_string();
2115 let japan: String = "日本".to_string();
2116 let uzbekistan: String = "Ўзбекистон".to_string();
2117 let austria: String = "Österreich".to_string();
2119 let bhutan_e: String =
2120 "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string();
2121 let japan_e: String = "\u{65e5}\u{672c}".to_string();
2122 let uzbekistan_e: String =
2123 "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string();
2124 let austria_e: String = "\u{d6}sterreich".to_string();
2127 assert_eq!(oo as isize, 0xd6);
2129 fn check_str_eq(a: String, b: String) {
2130 let mut i: isize = 0;
2131 for ab in a.bytes() {
2134 let bb: u8 = b.as_bytes()[i as usize];
2141 check_str_eq(bhutan, bhutan_e);
2142 check_str_eq(japan, japan_e);
2143 check_str_eq(uzbekistan, uzbekistan_e);
2144 check_str_eq(austria, austria_e);
2149 // Chars of 1, 2, 3, and 4 bytes
2150 let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}'];
2151 let s: String = chs.iter().cloned().collect();
2152 let schs: Vec<char> = s.chars().collect();
2154 assert_eq!(s.len(), 10);
2155 assert_eq!(s.chars().count(), 4);
2156 assert_eq!(schs.len(), 4);
2157 assert_eq!(schs.iter().cloned().collect::<String>(), s);
2159 assert!((from_utf8(s.as_bytes()).is_ok()));
2161 assert!((!from_utf8(&[0x80]).is_ok()));
2162 // invalid 2 byte prefix
2163 assert!((!from_utf8(&[0xc0]).is_ok()));
2164 assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
2165 // invalid 3 byte prefix
2166 assert!((!from_utf8(&[0xe0]).is_ok()));
2167 assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
2168 assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
2169 // invalid 4 byte prefix
2170 assert!((!from_utf8(&[0xf0]).is_ok()));
2171 assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
2172 assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
2173 assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));