| @@ -0,0 +1,144 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use super::{Pattern, LeftMatcher, DoubleEndedMatcher, RightMatcher}; | |||
|
|
|||
| use iter::{DoubleEndedIterator, Iterator}; | |||
| use option::Option; | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.matches()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// An iterator over all non-overlapping matches of a string pattern | |||
| /// in a `&str` starting from the front. | |||
| #[deriving(Clone)] | |||
| pub struct Matches<M> { | |||
| matcher: M | |||
| } | |||
|
|
|||
| impl<M> Matches<M> { | |||
| /// Constructor of `Matches` from a `Pattern`. | |||
| /// | |||
| /// Can also be constructed with the `.matches()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> Matches<M> { | |||
| let string_matcher = pat.into_matcher(s); | |||
| Matches { matcher: string_matcher } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> Iterator<&'a str> for Matches<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.matcher.next_match().map(|(_, s)| s) | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: DoubleEndedMatcher<'a>> DoubleEndedIterator<&'a str> for Matches<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| self.matcher.next_match_back().map(|(_, s)| s) | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.rmatches()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// An iterator over all non-overlapping matches of a string pattern | |||
| /// in a `&str` starting from the back. | |||
| #[deriving(Clone)] | |||
| pub struct RMatches<M> { | |||
| matcher: M | |||
| } | |||
|
|
|||
| impl<M> RMatches<M> { | |||
| /// Constructor of `RMatches` from a `Pattern`. | |||
| /// | |||
| /// Can also be constructed with the `.rmatches()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> RMatches<M> { | |||
| let string_matcher = pat.into_matcher(s); | |||
| RMatches { matcher: string_matcher } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> Iterator<&'a str> for RMatches<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.matcher.next_match_back().map(|(_, s)| s) | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.matches_indices()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// An iterator over all non-overlapping matches of a string pattern | |||
| /// in a `&str` with their byte indices starting from the front. | |||
| #[deriving(Clone)] | |||
| pub struct MatchIndices<M> { | |||
| matcher: M | |||
| } | |||
|
|
|||
| impl<M> MatchIndices<M> { | |||
| /// Constructor of `MatchIndices` from a `Pattern`. | |||
| /// | |||
| /// Can also be constructed with the `.match_indices()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> MatchIndices<M> { | |||
| let string_matcher = pat.into_matcher(s); | |||
| MatchIndices { matcher: string_matcher } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> Iterator<(uint, &'a str)> for MatchIndices<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<(uint, &'a str)> { | |||
| self.matcher.next_match() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: DoubleEndedMatcher<'a>> DoubleEndedIterator<(uint, &'a str)> for MatchIndices<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<(uint, &'a str)> { | |||
| self.matcher.next_match_back() | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.rmatches_indices()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// An iterator over all non-overlapping matches of a string pattern | |||
| /// in a `&str` with their byte indices starting from the back. | |||
| #[deriving(Clone)] | |||
| pub struct RMatchIndices<M> { | |||
| matcher: M | |||
| } | |||
|
|
|||
| impl<M> RMatchIndices<M> { | |||
| /// Constructor of `RMatchIndices` from a `Pattern`. | |||
| /// | |||
| /// Can also be constructed with the `.rmatch_indices()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> RMatchIndices<M> { | |||
| let string_matcher = pat.into_matcher(s); | |||
| RMatchIndices { matcher: string_matcher } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> Iterator<(uint, &'a str)> for RMatchIndices<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<(uint, &'a str)> { | |||
| self.matcher.next_match_back() | |||
| } | |||
| } | |||
| @@ -0,0 +1,272 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use super::raw; | |||
| use super::{Pattern, LeftMatcher, Matcher, RightMatcher, DoubleEndedMatcher}; | |||
| use super::{Searcher, Utf8Char, CharOffsets, StrSlice, CharEq}; | |||
|
|
|||
| use char::Char; | |||
| use iter::{DoubleEndedIterator, Iterator}; | |||
| use option::{Option, Some, None}; | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for `&str` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A matcher for `&str`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| #[deriving(Clone)] | |||
| pub struct StrMatcher<'a, 'b> { | |||
| searcher: Searcher<'a, &'b str> | |||
| } | |||
|
|
|||
| impl<'a, 'b> Pattern<'a, StrMatcher<'a, 'b>> for &'b str { | |||
| #[inline] | |||
| fn into_matcher(self, haystack: &'a str) -> StrMatcher<'a, 'b> { | |||
| StrMatcher { | |||
| searcher: Searcher::new(haystack, self) | |||
| } | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, haystack: &str) -> bool { | |||
| self.into_matcher(haystack).next_match().is_some() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, 'b> Matcher<'a> for StrMatcher<'a, 'b> { | |||
| #[inline] | |||
| fn get_haystack(&self) -> &'a str { | |||
| self.searcher.get_haystack() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, 'b> LeftMatcher<'a> for StrMatcher<'a, 'b> { | |||
| #[inline] | |||
| fn next_match(&mut self) -> Option<(uint, &'a str)> { | |||
| self.searcher.find_front() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, 'b> RightMatcher<'a> for StrMatcher<'a, 'b> { | |||
| #[inline] | |||
| fn next_match_back(&mut self) -> Option<(uint, &'a str)> { | |||
| self.searcher.find_back() | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for `char` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A matcher for `char`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| #[deriving(Clone)] | |||
| pub struct CharMatcher<'a> { | |||
| searcher: Searcher<'a, Utf8Char> | |||
| } | |||
|
|
|||
| impl<'a> Pattern<'a, CharMatcher<'a>> for char { | |||
| #[inline] | |||
| fn into_matcher(self, s: &'a str) -> CharMatcher<'a> { | |||
| let utf8char = Utf8Char::new(self); | |||
| CharMatcher { | |||
| searcher: Searcher::new(s, utf8char) | |||
| } | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, s: &str) -> bool { | |||
| self.into_matcher(s).next_match().is_some() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a> Matcher<'a> for CharMatcher<'a> { | |||
| #[inline] | |||
| fn get_haystack(&self) -> &'a str { | |||
| self.searcher.get_haystack() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a> LeftMatcher<'a> for CharMatcher<'a> { | |||
| #[inline] | |||
| fn next_match(&mut self) -> Option<(uint, &'a str)> { | |||
| self.searcher.find_front() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a> RightMatcher<'a> for CharMatcher<'a> { | |||
| #[inline] | |||
| fn next_match_back(&mut self) -> Option<(uint, &'a str)> { | |||
| self.searcher.find_back() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a> DoubleEndedMatcher<'a> for CharMatcher<'a> { } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for `|char| -> bool` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A matcher for `|char| -> bool`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| pub type CharClosureMatcher<'a, 'b> = CharEqMatcher<'a, |char|:'b -> bool>; | |||
|
|
|||
| impl<'a, 'b> Pattern<'a, CharClosureMatcher<'a, 'b>> for |char|:'b -> bool { | |||
| #[inline] | |||
| fn into_matcher(self, s: &'a str) -> CharClosureMatcher<'a, 'b> { | |||
| CharEqPattern(self).into_matcher(s) | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, s: &str) -> bool { | |||
| CharEqPattern(self).is_contained_in(s) | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for `fn(char) -> bool` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A matcher for `fn(char) -> bool`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| pub type CharFnMatcher<'a> = CharEqMatcher<'a, fn(char) -> bool>; | |||
|
|
|||
| impl<'a> Pattern<'a, CharFnMatcher<'a>> for fn(char) -> bool { | |||
| #[inline] | |||
| fn into_matcher(self, s: &'a str) -> CharFnMatcher<'a> { | |||
| CharEqPattern(self).into_matcher(s) | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, s: &str) -> bool { | |||
| CharEqPattern(self).is_contained_in(s) | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for `&[char]` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A matcher for `&[char]`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| pub type CharSliceMatcher<'a, 'b> = CharEqMatcher<'a, &'b [char]>; | |||
|
|
|||
| impl<'a, 'b> Pattern<'a, CharSliceMatcher<'a, 'b>> for &'b [char] { | |||
| #[inline] | |||
| fn into_matcher(self, s: &'a str) -> CharSliceMatcher<'a, 'b> { | |||
| CharEqPattern(self).into_matcher(s) | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, s: &str) -> bool { | |||
| CharEqPattern(self).is_contained_in(s) | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Pattern implementation for types implementing `CharEq` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// A string matching pattern that dispatches to the `CharEq` trait | |||
| pub struct CharEqPattern<T>(pub T); | |||
|
|
|||
| impl<'a, T: CharEq> Pattern<'a, CharEqMatcher<'a, T>> for CharEqPattern<T> { | |||
| #[inline] | |||
| fn into_matcher(self, s: &'a str) -> CharEqMatcher<'a, T> { | |||
| let CharEqPattern(char_eq) = self; | |||
| CharEqMatcher { | |||
| str: s, | |||
| chars: s.char_indices(), | |||
| only_ascii: char_eq.only_ascii(), | |||
| char_eq: char_eq, | |||
| } | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn is_contained_in(self, s: &str) -> bool { | |||
| self.into_matcher(s).next_match().is_some() | |||
| } | |||
| } | |||
|
|
|||
| /// A matcher for types implementing `CharEq`. | |||
| /// | |||
| /// This gets used in combination with `str::Pattern` | |||
| /// and the methods of `&str`. | |||
| #[deriving(Clone)] | |||
| pub struct CharEqMatcher<'a, T> { | |||
| str: &'a str, | |||
| chars: CharOffsets<'a>, | |||
| char_eq: T, | |||
| only_ascii: bool | |||
| } | |||
|
|
|||
| impl<'a, T: CharEq> Matcher<'a> for CharEqMatcher<'a, T> { | |||
| #[inline] | |||
| fn get_haystack(&self) -> &'a str { | |||
| self.str | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, T: CharEq> LeftMatcher<'a> for CharEqMatcher<'a, T> { | |||
| #[inline] | |||
| fn next_match(&mut self) -> Option<(uint, &'a str)> { | |||
| loop { | |||
| match self.chars.next() { | |||
| Some((i, c)) => if self.char_eq.matches(c) { | |||
| let a = i; | |||
| let b = i + c.len_utf8_bytes(); | |||
| let s = unsafe { | |||
| raw::slice_unchecked(self.str, a, b) | |||
| }; | |||
| return Some((a, s)) | |||
| } else { | |||
| continue | |||
| }, | |||
| None => break | |||
| } | |||
| } | |||
| None | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, T: CharEq> RightMatcher<'a> for CharEqMatcher<'a, T> { | |||
| #[inline] | |||
| fn next_match_back(&mut self) -> Option<(uint, &'a str)> { | |||
| loop { | |||
| match self.chars.next_back() { | |||
| Some((i, c)) => if self.char_eq.matches(c) { | |||
| let a = i; | |||
| let b = i + c.len_utf8_bytes(); | |||
| let s = unsafe { | |||
| raw::slice_unchecked(self.str, a, b) | |||
| }; | |||
| return Some((a, s)) | |||
| } else { | |||
| continue | |||
| }, | |||
| None => break, | |||
| } | |||
| } | |||
| None | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, T: CharEq> DoubleEndedMatcher<'a> for CharEqMatcher<'a, T> { } | |||
| @@ -0,0 +1,385 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use super::StrSlice; | |||
| use super::{Pattern, LeftMatcher, Matcher, DoubleEndedMatcher, RightMatcher}; | |||
|
|
|||
| use collections::Collection; | |||
| use iter::{DoubleEndedIterator, Iterator}; | |||
| use option::{Option, Some, None}; | |||
|
|
|||
| fn splits_next<'a, M: LeftMatcher<'a>>(self_: &mut SplitsInternal<M>) -> Option<(uint, uint)> { | |||
| if self_.finished { | |||
| return None; | |||
| } | |||
| // In case of overlapping matches, consider them one big seperator | |||
| loop { | |||
| match self_.matcher.next_match() { | |||
| Some((a, s)) => { | |||
| let b = a + s.len(); | |||
| let current_prev_start = self_.prev_start; | |||
| self_.prev_start = b; | |||
| if current_prev_start <= a { | |||
| return Some((current_prev_start, a)); | |||
| } | |||
| } | |||
| None => { | |||
| self_.finished = true; | |||
| return Some((self_.prev_start, self_.matcher.get_haystack().len())); | |||
| } | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| fn splits_next_back<'a, M: RightMatcher<'a>>(self_: &mut SplitsInternal<M>) | |||
| -> Option<(uint, uint)> { | |||
| if self_.finished { | |||
| return None; | |||
| } | |||
| // In case of overlapping matches, consider them one big seperator | |||
| loop { | |||
| match self_.matcher.next_match_back() { | |||
| Some((a, s)) => { | |||
| let b = a + s.len(); | |||
| let current_prev_end = self_.prev_end; | |||
| self_.prev_end = a; | |||
| if b <= current_prev_end { | |||
| return Some((b, current_prev_end)); | |||
| } | |||
| } | |||
| None => { | |||
| self_.finished = true; | |||
| return Some((0, self_.prev_end)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.split()` and `.rsplit()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| #[deriving(Clone)] | |||
| struct SplitsInternal<M> { | |||
| matcher: M, | |||
| finished: bool, | |||
| prev_start: uint, | |||
| prev_end: uint, | |||
| } | |||
|
|
|||
| impl<M> SplitsInternal<M> { | |||
| #[inline] | |||
| fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> SplitsInternal<M> { | |||
| SplitsInternal { | |||
| matcher: pat.into_matcher(s), | |||
| finished: false, | |||
| prev_start: 0, | |||
| prev_end: s.len() | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> SplitsInternal<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| let string = self.matcher.get_haystack(); | |||
| splits_next(self).map(|(a, b)| { | |||
| string.slice(a, b) | |||
| }) | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> SplitsInternal<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| let string = self.matcher.get_haystack(); | |||
| splits_next_back(self).map(|(a, b)| { | |||
| string.slice(a, b) | |||
| }) | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all substrings of a `&str` split at the | |||
| /// non-overlapping match of a string pattern matched from the left. | |||
| #[deriving(Clone)] | |||
| pub struct Splits<M> { | |||
| splits: SplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> Splits<M> { | |||
| /// Constructor for `Splits`. | |||
| /// | |||
| /// Can also be constructed with the `.split()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(haystack: &'a str, pat: P) -> Splits<M> { | |||
| Splits { | |||
| splits: SplitsInternal::new(haystack, pat) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> Iterator<&'a str> for Splits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: DoubleEndedMatcher<'a>> DoubleEndedIterator<&'a str> for Splits<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all substrings of a `&str` split at the | |||
| /// non-overlapping match of a string pattern matched from the right. | |||
| #[deriving(Clone)] | |||
| pub struct RSplits<M> { | |||
| splits: SplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> RSplits<M> { | |||
| /// Constructor for `RSplits`. | |||
| /// | |||
| /// Can also be constructed with the `.rsplit()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(haystack: &'a str, pat: P) -> RSplits<M> { | |||
| RSplits { | |||
| splits: SplitsInternal::new(haystack, pat) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> Iterator<&'a str> for RSplits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.splitn()` and `.rsplitn()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| #[deriving(Clone)] | |||
| struct NSplitsInternal<M> { | |||
| splits: SplitsInternal<M>, | |||
| count: uint | |||
| } | |||
|
|
|||
| impl<M> NSplitsInternal<M> { | |||
| #[inline] | |||
| fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P, n: uint) -> NSplitsInternal<M> { | |||
| NSplitsInternal { | |||
| splits: SplitsInternal::new(s, pat), | |||
| count: n | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> NSplitsInternal<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| if self.count == 0 { | |||
| let start = self.splits.prev_start; | |||
| let s = self.splits.matcher.get_haystack(); | |||
| if self.splits.finished { | |||
| None | |||
| } else { | |||
| self.splits.finished = true; | |||
| Some(s.slice_from(start)) | |||
| } | |||
| } else { | |||
| self.count -= 1; | |||
| self.splits.next() | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> NSplitsInternal<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| if self.count == 0 { | |||
| let end = self.splits.prev_end; | |||
| let s = self.splits.matcher.get_haystack(); | |||
| if self.splits.finished { | |||
| None | |||
| } else { | |||
| self.splits.finished = true; | |||
| Some(s.slice_to(end)) | |||
| } | |||
| } else { | |||
| self.count -= 1; | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all substrings of a `&str` split at the first `N` | |||
| /// non-overlapping matches of a string pattern matched from the front. | |||
| #[deriving(Clone)] | |||
| pub struct NSplits<M> { | |||
| splits: NSplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> NSplits<M> { | |||
| /// Constructor for `NSplits`. | |||
| /// | |||
| /// Can also be constructed with the `.splitn()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, n: uint, pat: P) -> NSplits<M> { | |||
| NSplits { | |||
| splits: NSplitsInternal::new(s, pat, n) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> Iterator<&'a str> for NSplits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next() | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all substrings of a `&str` split at the last `N` | |||
| /// non-overlapping matches of a string pattern matched from the back. | |||
| #[deriving(Clone)] | |||
| pub struct RNSplits<M> { | |||
| splits: NSplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> RNSplits<M> { | |||
| /// Constructor for `RNSplits`. | |||
| /// | |||
| /// Can also be constructed with the `.rsplitn()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, n: uint, pat: P) -> RNSplits<M> { | |||
| RNSplits { | |||
| splits: NSplitsInternal::new(s, pat, n) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> Iterator<&'a str> for RNSplits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
|
|
|||
| //////////////////////////////////////////////////////////////////////////// | |||
| // Implementation for `.split_terminator()` and `.rsplit_terminator()` | |||
| //////////////////////////////////////////////////////////////////////////// | |||
|
|
|||
| /// An iterator over all non-overlapping substrings of a `&str` split | |||
| /// at the match of a string pattern, not including a trailing empty string. | |||
| #[deriving(Clone)] | |||
| struct TermSplitsInternal<M> { | |||
| splits: SplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> TermSplitsInternal<M> { | |||
| #[inline] | |||
| fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> TermSplitsInternal<M> { | |||
| TermSplitsInternal { | |||
| splits: SplitsInternal::new(s, pat) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> TermSplitsInternal<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| let string = self.splits.matcher.get_haystack(); | |||
| loop { | |||
| match splits_next(&mut self.splits) { | |||
| Some((a, b)) if a == b && b == string.len() => continue, | |||
| Some((a, b)) => return Some(string.slice(a, b)), | |||
| None => return None | |||
| } | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> TermSplitsInternal<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| let string = self.splits.matcher.get_haystack(); | |||
| loop { | |||
| match splits_next_back(&mut self.splits) { | |||
| Some((a, b)) if a == b && b == string.len() => continue, | |||
| Some((a, b)) => return Some(string.slice(a, b)), | |||
| None => return None | |||
| } | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all non-overlapping substrings of a `&str` split | |||
| /// at the match of a string pattern from the front, | |||
| /// not including a trailing empty string. | |||
| #[deriving(Clone)] | |||
| pub struct TermSplits<M> { | |||
| splits: TermSplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> TermSplits<M> { | |||
| /// Constructor of `TermSplits` | |||
| /// | |||
| /// Can also be constructed with the `.split_terminator()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> TermSplits<M> { | |||
| TermSplits { | |||
| splits: TermSplitsInternal::new(s, pat) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: LeftMatcher<'a>> Iterator<&'a str> for TermSplits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next() | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: DoubleEndedMatcher<'a>> DoubleEndedIterator<&'a str> for TermSplits<M> { | |||
| #[inline] | |||
| fn next_back(&mut self) -> Option<&'a str> { | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
|
|
|||
| /// An iterator over all non-overlapping substrings of a `&str` split | |||
| /// at the match of a string pattern from the back, | |||
| /// not including a trailing empty string. | |||
| #[deriving(Clone)] | |||
| pub struct RTermSplits<M> { | |||
| splits: TermSplitsInternal<M> | |||
| } | |||
|
|
|||
| impl<M> RTermSplits<M> { | |||
| /// Constructor of `RTermSplits` | |||
| /// | |||
| /// Can also be constructed with the `.split_terminator()` method of `&str`. | |||
| #[inline] | |||
| pub fn new<'a, P: Pattern<'a, M>>(s: &'a str, pat: P) -> RTermSplits<M> { | |||
| RTermSplits { | |||
| splits: TermSplitsInternal::new(s, pat) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| impl<'a, M: RightMatcher<'a>> Iterator<&'a str> for RTermSplits<M> { | |||
| #[inline] | |||
| fn next(&mut self) -> Option<&'a str> { | |||
| self.splits.next_back() | |||
| } | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| #[test] | |||
| fn test1() { | |||
| let s = "abcbdef"; | |||
| let f = |c: char| c == 'c'; | |||
| iter_eq!(s.match_indices(f), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2() { | |||
| let s = "abcbdef"; | |||
| let f = |c: char| c == 'b'; | |||
| iter_eq!(s.match_indices(f), [(1u, "b"), (3, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| let f = |c: char| c == 'm' || c == 'r' || c == 'd'; | |||
| iter_eq!(s.match_indices(f), | |||
| [(27, "m"), (32, "r"), (37, "d"), (50u, "m"), (63, "m")]); | |||
|
|
|||
| let f = |c: char| c == 'm' || c == 'r' || c == 'd'; | |||
| iter_eq!(s.matches(f), ["m", "r", "d", "m", "m"]); | |||
|
|
|||
| let f = |c: char| c == '中'; | |||
| iter_eq!(s.match_indices(f), [(12u, "中")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test1_rev() { | |||
| let s = "abcbdef"; | |||
| let f = |c: char| c == 'c'; | |||
| iter_eq!(s.match_indices(f).rev(), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2_rev() { | |||
| let s = "abcbdef"; | |||
| let f = |c: char| c == 'b'; | |||
| iter_eq!(s.match_indices(f).rev(), [(3u, "b"), (1, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3_rev() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| let f = |c: char| c == 'm' || c == 'r' || c == 'd'; | |||
| iter_eq!(s.match_indices(f).rev(), | |||
| [(63, "m"), (50u, "m"), (37, "d"), (32, "r"), (27, "m")]); | |||
|
|
|||
| let f = |c: char| c == 'm' || c == 'r' || c == 'd'; | |||
| iter_eq!(s.matches(f).rev(), ["m", "m", "d", "r", "m"]); | |||
|
|
|||
| let f = |c: char| c == '中'; | |||
| iter_eq!(s.match_indices(f).rev(), [(12u, "中")]); | |||
| } | |||
| @@ -0,0 +1,63 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| #[test] | |||
| fn test1() { | |||
| let s = "abcbdef"; | |||
| fn f(c: char) -> bool { c == 'c' } | |||
| iter_eq!(s.match_indices(f), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2() { | |||
| let s = "abcbdef"; | |||
| fn f(c: char) -> bool { c == 'b' } | |||
| iter_eq!(s.match_indices(f), [(1u, "b"), (3, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| fn f(c: char) -> bool { c == 'm' || c == 'r' || c == 'd' } | |||
| iter_eq!(s.match_indices(f), | |||
| [(27, "m"), (32, "r"), (37, "d"), (50u, "m"), (63, "m")]); | |||
|
|
|||
| iter_eq!(s.matches(f), ["m", "r", "d", "m", "m"]); | |||
|
|
|||
| fn g(c: char) -> bool { c == '中' } | |||
| iter_eq!(s.match_indices(g), [(12u, "中")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test1_rev() { | |||
| let s = "abcbdef"; | |||
| fn f(c: char) -> bool { c == 'c' } | |||
| iter_eq!(s.match_indices(f).rev(), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2_rev() { | |||
| let s = "abcbdef"; | |||
| fn f(c: char) -> bool { c == 'b' } | |||
| iter_eq!(s.match_indices(f).rev(), [(3u, "b"), (1, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3_rev() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| fn f(c: char) -> bool { c == 'm' || c == 'r' || c == 'd' } | |||
| iter_eq!(s.match_indices(f).rev(), | |||
| [(63, "m"), (50u, "m"), (37, "d"), (32, "r"), (27, "m")]); | |||
|
|
|||
| iter_eq!(s.matches(f).rev(), ["m", "m", "d", "r", "m"]); | |||
|
|
|||
| fn g(c: char) -> bool { c == '中' } | |||
| iter_eq!(s.match_indices(g).rev(), [(12u, "中")]); | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| #[test] | |||
| fn test1() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices('c'), [(2u, "c")]); | |||
| iter_eq!(s.match_indices('c').rev(), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices('b'), [(1u, "b"), (3, "b")]); | |||
| iter_eq!(s.match_indices('b').rev(), [(3, "b"), (1u, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| iter_eq!(s.match_indices('a'), | |||
| [(26, "a"), (31, "a"), (36, "a"), (39, "a"), (49u, "a"), (62, "a")]); | |||
| iter_eq!(s.match_indices('a').rev(), | |||
| [(62, "a"), (49u, "a"), (39, "a"), (36, "a"), (31, "a"), (26, "a")]); | |||
|
|
|||
| iter_eq!(s.match_indices('中'), [(12u, "中")]); | |||
| iter_eq!(s.match_indices('中').rev(), [(12u, "中")]); | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| #[test] | |||
| fn test1() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices(['c'].as_slice()), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices(['b'].as_slice()), [(1u, "b"), (3, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| iter_eq!(s.match_indices(['m', 'r', 'd'].as_slice()), | |||
| [(27, "m"), (32, "r"), (37, "d"), (50u, "m"), (63, "m")]); | |||
|
|
|||
| iter_eq!(s.matches(['m', 'r', 'd'].as_slice()), ["m", "r", "d", "m", "m"]); | |||
| iter_eq!(s.match_indices(['中'].as_slice()), [(12u, "中")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test1_rev() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices(['c'].as_slice()).rev(), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2_rev() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices(['b'].as_slice()).rev(), [(3u, "b"), (1, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3_rev() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| iter_eq!(s.match_indices(['m', 'r', 'd'].as_slice()).rev(), | |||
| [(63, "m"), (50u, "m"), (37, "d"), (32, "r"), (27, "m")]); | |||
|
|
|||
| iter_eq!(s.matches(['m', 'r', 'd'].as_slice()).rev(), ["m", "m", "d", "r", "m"]); | |||
| iter_eq!(s.match_indices(['中'].as_slice()).rev(), [(12u, "中")]); | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| mod char_impl; | |||
| mod str_impl; | |||
| mod char_closure_impl; | |||
| mod char_fn_impl; | |||
| mod char_slice_impl; | |||
| @@ -0,0 +1,33 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| #[test] | |||
| fn test1() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices("c"), [(2u, "c")]); | |||
| iter_eq!(s.rmatch_indices("c"), [(2u, "c")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test2() { | |||
| let s = "abcbdef"; | |||
| iter_eq!(s.match_indices("b"), [(1u, "b"), (3, "b")]); | |||
| iter_eq!(s.rmatch_indices("b"), [(3, "b"), (1u, "b")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test3() { | |||
| let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; | |||
| iter_eq!(s.match_indices("am"), [(26, "am"), (49u, "am"), (62, "am")]); | |||
| iter_eq!(s.rmatch_indices("am"), [(62, "am"), (49u, "am"), (26, "am")]); | |||
|
|
|||
| iter_eq!(s.match_indices("中"), [(12u, "中")]); | |||
| iter_eq!(s.rmatch_indices("中"), [(12u, "中")]); | |||
| } | |||
| @@ -0,0 +1,288 @@ | |||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| macro_rules! iter_eq { | |||
| ($i:expr, $s:expr) => { | |||
| { | |||
| let i: Vec<_> = $i.collect(); | |||
| let s = $s; | |||
| assert_eq!(i.as_slice(), s.as_slice()); | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| mod impls; | |||
|
|
|||
| #[test] | |||
| fn test_starts_with() { | |||
| assert!("foobar".starts_with("foo")); | |||
| assert!("foobar".starts_with('f')); | |||
|
|
|||
| assert!(!"foobar".starts_with("oba")); | |||
| assert!(!"foobar".starts_with('o')); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_end_with() { | |||
| assert!("foobar".ends_with("bar")); | |||
| assert!("foobar".ends_with('r')); | |||
|
|
|||
| assert!(!"foobar".ends_with("oob")); | |||
| assert!(!"foobar".ends_with('b')); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_trim_left() { | |||
| assert_eq!(" ajklasd ".trim_left_matches(" "), "ajklasd "); | |||
| assert_eq!(" ajklasd ".trim_left_matches(' '), "ajklasd "); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_trim_right() { | |||
| assert_eq!(" ajklasd ".trim_right_matches(" "), " ajklasd"); | |||
| assert_eq!(" ajklasd ".trim_right_matches(' '), " ajklasd"); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_trim() { | |||
| assert_eq!(" ajklasd ".trim_matches(' '), "ajklasd"); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_find() { | |||
| assert_eq!("abaaaba".find("b"), Some(1)); | |||
| assert_eq!("abaaaba".find("a"), Some(0)); | |||
| assert_eq!("abaaaba".find("c"), None); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rfind() { | |||
| assert_eq!("abaaaba".rfind("b"), Some(5)); | |||
| assert_eq!("abaaaba".rfind("a"), Some(6)); | |||
| assert_eq!("abaaaba".rfind("c"), None); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_split_terminator() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.split_terminator("a"), ["", "sädf", "dfsdf"]); | |||
| iter_eq!(s.rsplit_terminator("a"), ["dfsdf", "sädf", ""]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.split_terminator("a"), ["", "sädf", "", "", "", "", "dfsdf"]); | |||
| iter_eq!(s.rsplit_terminator("a"), ["dfsdf", "", "", "", "", "sädf", ""]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.split_terminator("ab"), ["fff", "", "afff"]); | |||
| iter_eq!(s.rsplit_terminator("ab"), ["afff", "", "fff"]); | |||
|
|
|||
| let s = "a"; | |||
| iter_eq!(s.split_terminator("a"), [""]); | |||
| iter_eq!(s.rsplit_terminator("a"), [""]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_split_terminator_overlapping() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.split_terminator("aa"), ["asädf", "", "adfsdfa"]); | |||
| iter_eq!(s.rsplit_terminator("aa"), ["dfsdfa", "", "asädfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.split_terminator("aba"), ["fff", "bafff"]); | |||
| iter_eq!(s.rsplit_terminator("aba"), ["fff", "fffab"]); | |||
| } | |||
|
|
|||
|
|
|||
| #[test] | |||
| fn test_rsplitn100() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 100), ["", "dfsdf", "sädf", ""]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 100), ["", "dfsdf", "", "", "", "", "sädf", ""]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("ab", 100), ["afff", "", "fff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rsplitn_overlapping100() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("aa", 100), ["dfsdfa", "", "asädfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("aba", 100), ["fff", "fffab"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rsplitn2() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 2), ["", "dfsdf", "asädf"]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 2), ["", "dfsdf", "asädfaaaa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("ab", 2), ["afff", "", "fff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rsplitn_overlapping2() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("aa", 2), ["dfsdfa", "", "asädfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("aba", 2), ["fff", "fffab"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rsplitn0() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 0), [s]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("a", 0), [s]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("ab", 0), [s]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_rsplitn_overlapping0() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.rsplitn("aa", 0), [s]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.rsplitn("aba", 0), [s]); | |||
| } | |||
|
|
|||
|
|
|||
| #[test] | |||
| fn test_splitn100() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.splitn("a", 100), ["", "sädf", "dfsdf", ""]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn("a", 100), ["", "sädf", "", "", "", "", "dfsdf", ""]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("ab", 100), ["fff", "", "afff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_splitn_overlapping100() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn("aa", 100), ["asädf", "", "adfsdfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("aba", 100), ["fff", "bafff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_splitn2() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.splitn("a", 2), ["", "sädf", "dfsdfa"]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn('a', 2), ["", "sädf", "aaaadfsdfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("ab", 2), ["fff", "", "afff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_splitn_overlapping2() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn("aa", 2), ["asädf", "", "adfsdfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("aba", 2), ["fff", "bafff"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_splitn0() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.splitn("a", 0), [s]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn("a", 0), [s]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("ab", 0), [s]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_splitn_overlapping0() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.splitn("aa", 0), [s]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.splitn("aba", 0), [s]); | |||
| } | |||
|
|
|||
|
|
|||
| #[test] | |||
| fn test_split() { | |||
| let s = "asädfadfsdfa"; | |||
| iter_eq!(s.split("a"), ["", "sädf", "dfsdf", ""]); | |||
| iter_eq!(s.rsplit("a"), ["", "dfsdf", "sädf", ""]); | |||
|
|
|||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.split("a"), ["", "sädf", "", "", "", "", "dfsdf", ""]); | |||
| iter_eq!(s.rsplit("a"), ["", "dfsdf", "", "", "", "", "sädf", ""]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.split("ab"), ["fff", "", "afff"]); | |||
| iter_eq!(s.rsplit("ab"), ["afff", "", "fff"]); | |||
|
|
|||
| let s = "a"; | |||
| iter_eq!(s.split("a"), ["", ""]); | |||
| iter_eq!(s.rsplit("a"), ["", ""]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_split_overlapping() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.split("aa"), ["asädf", "", "adfsdfa"]); | |||
| iter_eq!(s.rsplit("aa"), ["dfsdfa", "", "asädfa"]); | |||
|
|
|||
| let s = "fffababafff"; | |||
| iter_eq!(s.split("aba"), ["fff", "bafff"]); | |||
| iter_eq!(s.rsplit("aba"), ["fff", "fffab"]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_double_ended_match_indices() { | |||
| let s = "asädfaaaaadfsdfa"; | |||
| iter_eq!(s.match_indices("aa"), [(6u, "aa"), (8, "aa")]); | |||
| iter_eq!(s.rmatch_indices("aa"), [(9u, "aa"), (7, "aa")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_empty_haystack() { | |||
| let haystack = ""; | |||
| let needle = "asädf"; | |||
| let arr: [(uint, &str), ..0] = []; | |||
| iter_eq!(haystack.match_indices(needle), arr); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_empty_needle() { | |||
| let haystack = "asädf"; | |||
| let needle = ""; | |||
| iter_eq!(haystack.match_indices(needle), [(0u, ""), (1, ""), (2, ""), (4, ""), (5, "")]); | |||
| } | |||
|
|
|||
| #[test] | |||
| fn test_empty_haystack_needle() { | |||
| let haystack = ""; | |||
| let needle = ""; | |||
| iter_eq!(haystack.match_indices(needle), [(0u, "")]); | |||
| } | |||