@@ -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()
}
}

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -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> { }

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -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()
}
}
@@ -51,61 +51,61 @@ fn any_owning() {
}

#[test]
fn any_as_ref() {
fn any_downcast_ref() {
let a = &5u as &Any;

match a.as_ref::<uint>() {
match a.downcast_ref::<uint>() {
Some(&5) => {}
x => fail!("Unexpected value {}", x)
}

match a.as_ref::<Test>() {
match a.downcast_ref::<Test>() {
None => {}
x => fail!("Unexpected value {}", x)
}
}

#[test]
fn any_as_mut() {
fn any_downcast_mut() {
let mut a = 5u;
let mut b = box 7u;

let a_r = &mut a as &mut Any;
let tmp: &mut uint = &mut *b;
let b_r = tmp as &mut Any;

match a_r.as_mut::<uint>() {
match a_r.downcast_mut::<uint>() {
Some(x) => {
assert_eq!(*x, 5u);
*x = 612;
}
x => fail!("Unexpected value {}", x)
}

match b_r.as_mut::<uint>() {
match b_r.downcast_mut::<uint>() {
Some(x) => {
assert_eq!(*x, 7u);
*x = 413;
}
x => fail!("Unexpected value {}", x)
}

match a_r.as_mut::<Test>() {
match a_r.downcast_mut::<Test>() {
None => (),
x => fail!("Unexpected value {}", x)
}

match b_r.as_mut::<Test>() {
match b_r.downcast_mut::<Test>() {
None => (),
x => fail!("Unexpected value {}", x)
}

match a_r.as_mut::<uint>() {
match a_r.downcast_mut::<uint>() {
Some(&612) => {}
x => fail!("Unexpected value {}", x)
}

match b_r.as_mut::<uint>() {
match b_r.downcast_mut::<uint>() {
Some(&413) => {}
x => fail!("Unexpected value {}", x)
}
@@ -121,11 +121,11 @@ fn any_fixed_vec() {


#[bench]
fn bench_as_ref(b: &mut Bencher) {
fn bench_downcast_ref(b: &mut Bencher) {
b.iter(|| {
let mut x = 0i;
let mut y = &mut x as &mut Any;
test::black_box(&mut y);
test::black_box(y.as_ref::<int>() == Some(&0));
test::black_box(y.downcast_ref::<int>() == Some(&0));
});
}
@@ -30,3 +30,4 @@ mod raw;
mod result;
mod slice;
mod tuple;
mod str;
@@ -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, "")]);
}
@@ -446,7 +446,7 @@ impl<'a> LabelText<'a> {
fn pre_escaped_content(self) -> str::MaybeOwned<'a> {
match self {
EscStr(s) => s,
LabelStr(s) => if s.as_slice().contains_char('\\') {
LabelStr(s) => if s.as_slice().contains('\\') {
str::Owned(s.as_slice().escape_default())
} else {
s
@@ -384,6 +384,7 @@ extern crate regex;
// unicode tables for character classes are defined in libunicode
extern crate unicode;

use std::str::{Pattern, Matcher, LeftMatcher};
pub use parse::Error;
pub use re::{Regex, Captures, SubCaptures, SubCapturesPos};
pub use re::{FindCaptures, FindMatches};
@@ -432,3 +433,102 @@ pub mod native {
CharReader, find_prefix,
};
}

/// String pattern implementation for a regular expression
pub struct RegexMatcher<'t, 'r> {
str: &'t str,
regex: FindMatches<'r, 't>
}

impl<'t, 'r> Pattern<'t, RegexMatcher<'t, 'r>> for &'r Regex {
fn into_matcher(self, s: &'t str) -> RegexMatcher<'t, 'r> {
RegexMatcher {
str: s,
regex: self.find_iter(s)
}
}
fn is_contained_in(self, s: &str) -> bool {
self.is_match(s)
}
}

impl<'t, 'r> Matcher<'t> for RegexMatcher<'t, 'r> {
fn get_haystack(&self) -> &'t str {
self.str
}
}

impl<'t, 'r> LeftMatcher<'t> for RegexMatcher<'t, 'r> {
fn next_match(&mut self) -> Option<(uint, &'t str)> {
// FIXME: Maybe replace slice() call with unchecked variant
self.regex.next().map(|(a, b)| (a, self.str.slice(a, b)))
}
}

#[cfg(test)]
mod str_matcher_tests {
use super::Regex;

macro_rules! iter_eq {
($i:expr, $s:expr) => {
{
let i: Vec<_> = $i.collect();
let s = $s;
assert_eq!(i.as_slice(), s.as_slice());
}
}
}

#[test]
fn test1() {
let s = "abcbdef";
let r = Regex::new("c").unwrap();
iter_eq!(s.match_indices(&r), [(2u, "c")]);
}

#[test]
fn test2() {
let s = "abcbdef";
let r = Regex::new("b").unwrap();
iter_eq!(s.match_indices(&r), [(1u, "b"), (3, "b")]);
}

#[test]
fn test3() {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let r = Regex::new("a[mrd]").unwrap();
iter_eq!(s.match_indices(&r),
[(26, "am"), (31, "ar"), (36, "ad"), (49u, "am"), (62, "am")]);
iter_eq!(s.matches(&r), ["am", "ar", "ad", "am", "am"]);

let r = Regex::new("中").unwrap();
iter_eq!(s.match_indices(&r), [(12u, "中")]);
}

#[test]
fn splitn() {
let re = Regex::new(r"\d+").unwrap();
let s = "cauchy123plato456tyler789binx";
iter_eq!(s.splitn(&re, 2), ["cauchy", "plato", "tyler789binx"]);
}

#[test]
fn split() {
let re = Regex::new(r"\d+").unwrap();
let s = "cauchy123plato456tyler789binx";
iter_eq!(s.split(&re), ["cauchy", "plato", "tyler", "binx"]);
}

#[test]
fn split2() {
let s = "abcaaaaabdef";
let r = Regex::new("aa").unwrap();
iter_eq!(s.split(&r), ["abc", "", "abdef"]);
}

#[test]
fn test_starts_with() {
assert!("foobar".starts_with(&{Regex::new("fo+").unwrap()}));
assert!(!"foobar".starts_with(&{Regex::new("[ob]").unwrap()}));
}
}
@@ -1410,7 +1410,7 @@ fn blank<'a>(s: Option<&'a str>) -> &'a str {

fn shorter<'a>(s: Option<&'a str>) -> &'a str {
match s {
Some(s) => match s.find_str("\n\n") {
Some(s) => match s.find("\n\n") {
Some(pos) => s.slice_to(pos),
None => s,
},
@@ -24,7 +24,7 @@ use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
use mem;
use option::{Option, Some, None};
use slice::{Slice, ImmutableSlice};
use str::{CharSplits, Str, StrAllocating, StrVector, StrSlice};
use str::{TermSplits, Str, StrAllocating, StrVector, StrSlice, CharMatcher};
use string::String;
use unicode::char::UnicodeChar;
use vec::Vec;
@@ -36,7 +36,7 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
/// Each component is yielded as Option<&str> for compatibility with PosixPath, but
/// every component in WindowsPath is guaranteed to be Some.
pub type StrComponents<'a> = Map<'a, &'a str, Option<&'a str>,
CharSplits<'a, char>>;
TermSplits<CharMatcher<'a>>>;

/// Iterator that yields successive components of a Path as &[u8]
pub type Components<'a> = Map<'a, Option<&'a str>, &'a [u8],
@@ -22,15 +22,14 @@ use core::cmp;
use core::collections::Collection;
use core::iter::{Filter, AdditiveIterator, Iterator, DoubleEndedIterator};
use core::option::{Option, None, Some};
use core::str::{CharSplits, StrSlice};
use core::str::{StrSlice, Splits, CharFnMatcher};
use u_char;
use u_char::UnicodeChar;
use tables::grapheme::GraphemeCat;

/// An iterator over the words of a string, separated by a sequence of whitespace
pub type Words<'a> =
Filter<'a, &'a str, CharSplits<'a, extern "Rust" fn(char) -> bool>>;

Filter<'a, &'a str, Splits<CharFnMatcher<'a>>>;
/// Methods for Unicode string slices
pub trait UnicodeStrSlice<'a> {
/// Returns an iterator over the
@@ -155,17 +154,17 @@ impl<'a> UnicodeStrSlice<'a> for &'a str {

#[inline]
fn trim(&self) -> &'a str {
self.trim_left().trim_right()
self.trim_matches(u_char::is_whitespace)
}

#[inline]
fn trim_left(&self) -> &'a str {
self.trim_left_chars(u_char::is_whitespace)
self.trim_left_matches(u_char::is_whitespace)
}

#[inline]
fn trim_right(&self) -> &'a str {
self.trim_right_chars(u_char::is_whitespace)
self.trim_right_matches(u_char::is_whitespace)
}
}

@@ -393,7 +393,7 @@ impl Uuid {
}

// Split string up by hyphens into groups
let hex_groups: Vec<&str> = us.split_str("-").collect();
let hex_groups: Vec<&str> = us.split("-").collect();

// Get the length of each group
let group_lens: Vec<uint> = hex_groups.iter().map(|&v| v.len()).collect();