From 72c8f3772bdca40ff2be2908aaf6b6a73d1c7821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Thu, 18 Dec 2014 02:12:53 +0100 Subject: [PATCH] Prepared most `StrExt` pattern using methods for stabilization Made iterator-returning methods return newtypes Adjusted some docs to be forwards compatible with a generic pattern API --- src/libcollections/str.rs | 179 ++++++++++++--------- src/libcore/{str.rs => str/mod.rs} | 248 +++++++++++++++++++---------- src/librustc/lint/builtin.rs | 6 +- src/libstd/path/windows.rs | 4 +- src/libunicode/u_str.rs | 9 +- 5 files changed, 274 insertions(+), 172 deletions(-) rename src/libcore/{str.rs => str/mod.rs} (88%) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 5feae5e558edf..446438c119f29 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -80,12 +80,14 @@ use vec::Vec; pub use core::str::{from_utf8, CharEq, Chars, CharIndices}; pub use core::str::{Bytes, CharSplits, is_utf8}; -pub use core::str::{CharSplitsN, Lines, LinesAny, MatchIndices, StrSplits}; +pub use core::str::{CharSplitsN, Lines, LinesAny, MatchIndices, StrSplits, SplitStr}; pub use core::str::{CharRange}; pub use core::str::{FromStr, from_str, Utf8Error}; pub use core::str::Str; pub use core::str::{from_utf8_unchecked, from_c_str}; pub use unicode::str::{Words, Graphemes, GraphemeIndices}; +pub use core::str::{Split, SplitTerminator}; +pub use core::str::{SplitN, RSplitN}; // FIXME(conventions): ensure bit/char conventions are followed by str's API @@ -721,7 +723,7 @@ pub trait StrExt for Sized?: ops::Slice { /// // not found, so no change. /// assert_eq!(s.replace("cookie monster", "little lamb"), s); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] + #[stable] fn replace(&self, from: &str, to: &str) -> String { let mut result = String::new(); let mut last_end = 0; @@ -828,36 +830,36 @@ pub trait StrExt for Sized?: ops::Slice { } } - /// Returns true if one string contains another + /// Returns true if a string contains a string pattern. /// /// # Arguments /// - /// - needle - The string to look for + /// - pat - The string pattern to look for /// /// # Example /// /// ```rust /// assert!("bananas".contains("nana")); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn contains(&self, needle: &str) -> bool { - core_str::StrExt::contains(self[], needle) + #[stable] + fn contains(&self, pat: &str) -> bool { + core_str::StrExt::contains(self[], pat) } - /// Returns true if a string contains a char. + /// Returns true if a string contains a char pattern. /// /// # Arguments /// - /// - needle - The char to look for + /// - pat - The char pattern to look for /// /// # Example /// /// ```rust /// assert!("hello".contains_char('e')); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn contains_char(&self, needle: char) -> bool { - core_str::StrExt::contains_char(self[], needle) + #[unstable = "might get removed in favour of a more generic contains()"] + fn contains_char(&self, pat: P) -> bool { + core_str::StrExt::contains_char(self[], pat) } /// An iterator over the characters of `self`. Note, this iterates @@ -894,7 +896,7 @@ pub trait StrExt for Sized?: ops::Slice { } /// An iterator over substrings of `self`, separated by characters - /// matched by `sep`. + /// matched by the pattern `pat`. /// /// # Example /// @@ -911,13 +913,13 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<&str> = "".split('X').collect(); /// assert_eq!(v, vec![""]); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn split(&self, sep: Sep) -> CharSplits { - core_str::StrExt::split(self[], sep) + #[stable] + fn split(&self, pat: P) -> Split

{ + core_str::StrExt::split(self[], pat) } /// An iterator over substrings of `self`, separated by characters - /// matched by `sep`, restricted to splitting at most `count` + /// matched by the pattern `pat`, restricted to splitting at most `count` /// times. /// /// # Example @@ -938,13 +940,13 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<&str> = "".splitn(1, 'X').collect(); /// assert_eq!(v, vec![""]); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn splitn(&self, count: uint, sep: Sep) -> CharSplitsN { - core_str::StrExt::splitn(self[], count, sep) + #[stable] + fn splitn(&self, count: uint, pat: P) -> SplitN

{ + core_str::StrExt::splitn(self[], count, pat) } /// An iterator over substrings of `self`, separated by characters - /// matched by `sep`. + /// matched by the pattern `pat`. /// /// Equivalent to `split`, except that the trailing substring /// is skipped if empty (terminator semantics). @@ -967,13 +969,13 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect(); /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn split_terminator(&self, sep: Sep) -> CharSplits { - core_str::StrExt::split_terminator(self[], sep) + #[unstable = "might get removed"] + fn split_terminator(&self, pat: P) -> SplitTerminator

{ + core_str::StrExt::split_terminator(self[], pat) } /// An iterator over substrings of `self`, separated by characters - /// matched by `sep`, starting from the end of the string. + /// matched by the pattern `pat`, starting from the end of the string. /// Restricted to splitting at most `count` times. /// /// # Example @@ -988,13 +990,13 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn rsplitn(&self, count: uint, sep: Sep) -> CharSplitsN { - core_str::StrExt::rsplitn(self[], count, sep) + #[stable] + fn rsplitn(&self, count: uint, pat: P) -> RSplitN

{ + core_str::StrExt::rsplitn(self[], count, pat) } /// An iterator over the start and end indices of the disjoint - /// matches of `sep` within `self`. + /// matches of the pattern `pat` within `self`. /// /// That is, each returned value `(start, end)` satisfies /// `self.slice(start, end) == sep`. For matches of `sep` within @@ -1013,12 +1015,12 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<(uint, uint)> = "ababa".match_indices("aba").collect(); /// assert_eq!(v, vec![(0, 3)]); // only the first `aba` /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> { - core_str::StrExt::match_indices(self[], sep) + #[unstable = "might have its iterator type changed"] + fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> { + core_str::StrExt::match_indices(self[], pat) } - /// An iterator over the substrings of `self` separated by `sep`. + /// An iterator over the substrings of `self` separated by the pattern `sep`. /// /// # Example /// @@ -1029,9 +1031,9 @@ pub trait StrExt for Sized?: ops::Slice { /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); /// assert_eq!(v, vec!["1", "", "2"]); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn split_str<'a>(&'a self, s: &'a str) -> StrSplits<'a> { - core_str::StrExt::split_str(self[], s) + #[unstable = "might get removed in the future in favor of a more generic split()"] + fn split_str<'a>(&'a self, pat: &'a str) -> StrSplits<'a> { + core_str::StrExt::split_str(self[], pat) } /// An iterator over the lines of a string (subsequences separated @@ -1204,85 +1206,106 @@ pub trait StrExt for Sized?: ops::Slice { core_str::StrExt::slice_unchecked(self[], begin, end) } - /// Returns true if `needle` is a prefix of the string. + /// Returns true if the pattern `pat` is a prefix of the string. /// /// # Example /// /// ```rust /// assert!("banana".starts_with("ba")); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn starts_with(&self, needle: &str) -> bool { - core_str::StrExt::starts_with(self[], needle) + #[stable] + fn starts_with(&self, pat: &str) -> bool { + core_str::StrExt::starts_with(self[], pat) } - /// Returns true if `needle` is a suffix of the string. + /// Returns true if the pattern `pat` is a suffix of the string. /// /// # Example /// /// ```rust /// assert!("banana".ends_with("nana")); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn ends_with(&self, needle: &str) -> bool { - core_str::StrExt::ends_with(self[], needle) + #[stable] + fn ends_with(&self, pat: &str) -> bool { + core_str::StrExt::ends_with(self[], pat) } - /// Returns a string with characters that match `to_trim` removed from the left and the right. + /// Returns a string with all pre- and suffixes that match + /// the pattern `pat` repeatedly removed. /// /// # Arguments /// - /// * to_trim - a character matcher + /// * pat - a string pattern /// /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar"); + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar"); - /// assert_eq!("123foo1bar123".trim_chars(|&: c: char| c.is_numeric()), "foo1bar"); + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_matches(|&: c: char| c.is_numeric()), "foo1bar"); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn trim_chars(&self, to_trim: C) -> &str { - core_str::StrExt::trim_chars(self[], to_trim) + #[stable] + fn trim_matches(&self, pat: P) -> &str { + core_str::StrExt::trim_matches(self[], pat) } - /// Returns a string with leading `chars_to_trim` removed. + /// Deprecated + #[deprecated = "Replaced by `trim_matches`"] + fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str { + self.trim_matches(to_trim) + } + + /// Returns a string with all prefixes that match + /// the pattern `pat` repeatedly removed. /// /// # Arguments /// - /// * to_trim - a character matcher + /// * pat - a string pattern /// /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11"); + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12"); - /// assert_eq!("123foo1bar123".trim_left_chars(|&: c: char| c.is_numeric()), "foo1bar123"); + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// assert_eq!("123foo1bar123".trim_left_matches(|&: c: char| c.is_numeric()), "foo1bar123"); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn trim_left_chars(&self, to_trim: C) -> &str { - core_str::StrExt::trim_left_chars(self[], to_trim) + #[stable] + fn trim_left_matches(&self, pat: P) -> &str { + core_str::StrExt::trim_left_matches(self[], pat) + } + + /// Deprecated + #[deprecated = "Replaced by `trim_left_matches`"] + fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str { + self.trim_left_matches(to_trim) } - /// Returns a string with trailing `chars_to_trim` removed. + /// Returns a string with all suffixes that match + /// the pattern `pat` repeatedly removed. /// /// # Arguments /// - /// * to_trim - a character matcher + /// * pat - a string pattern /// /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar"); + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar"); - /// assert_eq!("123foo1bar123".trim_right_chars(|&: c: char| c.is_numeric()), "123foo1bar"); + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(|&: c: char| c.is_numeric()), "123foo1bar"); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn trim_right_chars(&self, to_trim: C) -> &str { - core_str::StrExt::trim_right_chars(self[], to_trim) + #[stable] + fn trim_right_matches(&self, pat: P) -> &str { + core_str::StrExt::trim_right_matches(self[], pat) + } + + /// Deprecated + #[deprecated = "Replaced by `trim_right_matches`"] + fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str { + self.trim_right_matches(to_trim) } /// Check that `index`-th byte lies at the start and/or end of a @@ -1430,7 +1453,7 @@ pub trait StrExt for Sized?: ops::Slice { } /// Returns the byte index of the first character of `self` that - /// matches `search`. + /// matches the pattern `pat`. /// /// # Return value /// @@ -1452,13 +1475,13 @@ pub trait StrExt for Sized?: ops::Slice { /// let x: &[_] = &['1', '2']; /// assert_eq!(s.find(x), None); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn find(&self, search: C) -> Option { - core_str::StrExt::find(self[], search) + #[unstable = "might be superseded by match_indices"] + fn find(&self, pat: P) -> Option { + core_str::StrExt::find(self[], pat) } /// Returns the byte index of the last character of `self` that - /// matches `search`. + /// matches the pattern `pat`. /// /// # Return value /// @@ -1480,9 +1503,9 @@ pub trait StrExt for Sized?: ops::Slice { /// let x: &[_] = &['1', '2']; /// assert_eq!(s.rfind(x), None); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] - fn rfind(&self, search: C) -> Option { - core_str::StrExt::rfind(self[], search) + #[unstable = "might be superseded by match_indices"] + fn rfind(&self, pat: P) -> Option { + core_str::StrExt::rfind(self[], pat) } /// Returns the byte index of the first matching substring @@ -1504,7 +1527,7 @@ pub trait StrExt for Sized?: ops::Slice { /// assert_eq!(s.find_str("老虎 L"), Some(6)); /// assert_eq!(s.find_str("muffin man"), None); /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] + #[unstable = "might get removed in favor of a more generic find in the future"] fn find_str(&self, needle: &str) -> Option { core_str::StrExt::find_str(self[], needle) } @@ -1546,7 +1569,7 @@ pub trait StrExt for Sized?: ops::Slice { /// assert!(string.subslice_offset(lines[1]) == 2); // &"b" /// assert!(string.subslice_offset(lines[2]) == 4); // &"c" /// ``` - #[unstable = "awaiting pattern/matcher stabilization"] + #[unstable = "awaiting convention about comparability of arbitrary slices"] fn subslice_offset(&self, inner: &str) -> uint { core_str::StrExt::subslice_offset(self[], inner) } diff --git a/src/libcore/str.rs b/src/libcore/str/mod.rs similarity index 88% rename from src/libcore/str.rs rename to src/libcore/str/mod.rs index 204ffae6cbd54..1e7fe8f060c3e 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str/mod.rs @@ -18,7 +18,6 @@ use self::Searcher::{Naive, TwoWay, TwoWayLong}; -use clone::Clone; use cmp::{mod, Eq}; use default::Default; use iter::range; @@ -35,6 +34,70 @@ use result::Result::{mod, Ok, Err}; use slice::{mod, SliceExt}; use uint; +macro_rules! delegate_iter { + (exact $te:ty in $ti:ty) => { + delegate_iter!{$te in $ti} + impl<'a> ExactSizeIterator<$te> for $ti { + #[inline] + fn rposition

(&mut self, predicate: P) -> Option where P: FnMut($te) -> bool{ + self.0.rposition(predicate) + } + #[inline] + fn len(&self) -> uint { + self.0.len() + } + } + }; + ($te:ty in $ti:ty) => { + impl<'a> Iterator<$te> for $ti { + #[inline] + fn next(&mut self) -> Option<$te> { + self.0.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.0.size_hint() + } + } + impl<'a> DoubleEndedIterator<$te> for $ti { + #[inline] + fn next_back(&mut self) -> Option<$te> { + self.0.next_back() + } + } + }; + (pattern $te:ty in $ti:ty) => { + impl<'a, P: CharEq> Iterator<$te> for $ti { + #[inline] + fn next(&mut self) -> Option<$te> { + self.0.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.0.size_hint() + } + } + impl<'a, P: CharEq> DoubleEndedIterator<$te> for $ti { + #[inline] + fn next_back(&mut self) -> Option<$te> { + self.0.next_back() + } + } + }; + (pattern forward $te:ty in $ti:ty) => { + impl<'a, P: CharEq> Iterator<$te> for $ti { + #[inline] + fn next(&mut self) -> Option<$te> { + self.0.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.0.size_hint() + } + } + } +} + /// A trait to abstract the idea of creating a new instance of a type from a /// string. // FIXME(#17307): there should be an `E` associated type for a `Result` return @@ -333,29 +396,28 @@ impl<'a> DoubleEndedIterator<(uint, char)> for CharIndices<'a> { /// External iterator for a string's bytes. /// Use with the `std::iter` module. +/// +/// Created with `StrExt::bytes` #[stable] #[deriving(Clone)] -pub struct Bytes<'a> { - inner: Map<&'a u8, u8, slice::Iter<'a, u8>, BytesFn>, -} +pub struct Bytes<'a>(Map<&'a u8, u8, slice::Iter<'a, u8>, BytesDeref>); +delegate_iter!{exact u8 in Bytes<'a>} -/// A temporary new type wrapper that ensures that the `Bytes` iterator +/// A temporary fn new type that ensures that the `Bytes` iterator /// is cloneable. -#[deriving(Copy)] -struct BytesFn(fn(&u8) -> u8); +#[deriving(Copy, Clone)] +struct BytesDeref; -impl<'a> Fn(&'a u8) -> u8 for BytesFn { +impl<'a> Fn(&'a u8) -> u8 for BytesDeref { + #[inline] extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 { - (self.0)(ptr) + *ptr } } -impl Clone for BytesFn { - fn clone(&self) -> BytesFn { *self } -} - /// An iterator over the substrings of a string, separated by `sep`. #[deriving(Clone)] +#[deprecated = "Type is now named `Split` or `SplitTerminator`"] pub struct CharSplits<'a, Sep> { /// The slice remaining to be iterated string: &'a str, @@ -369,6 +431,7 @@ pub struct CharSplits<'a, Sep> { /// An iterator over the substrings of a string, separated by `sep`, /// splitting at most `count` times. #[deriving(Clone)] +#[deprecated = "Type is now named `SplitN` or `RSplitN`"] pub struct CharSplitsN<'a, Sep> { iter: CharSplits<'a, Sep>, /// The number of splits remaining @@ -790,12 +853,17 @@ pub struct MatchIndices<'a> { /// An iterator over the substrings of a string separated by a given /// search string #[deriving(Clone)] -pub struct StrSplits<'a> { +#[unstable = "Type might get removed"] +pub struct SplitStr<'a> { it: MatchIndices<'a>, last_end: uint, finished: bool } +/// Deprecated +#[deprecated = "Type is now named `SplitStr`"] +pub type StrSplits<'a> = SplitStr<'a>; + impl<'a> Iterator<(uint, uint)> for MatchIndices<'a> { #[inline] fn next(&mut self) -> Option<(uint, uint)> { @@ -810,7 +878,7 @@ impl<'a> Iterator<(uint, uint)> for MatchIndices<'a> { } } -impl<'a> Iterator<&'a str> for StrSplits<'a> { +impl<'a> Iterator<&'a str> for SplitStr<'a> { #[inline] fn next(&mut self) -> Option<&'a str> { if self.finished { return None; } @@ -1158,23 +1226,47 @@ impl<'a, Sized? S> Str for &'a S where S: Str { fn as_slice(&self) -> &str { Str::as_slice(*self) } } +/// Return type of `StrExt::split` +#[deriving(Clone)] +#[stable] +pub struct Split<'a, P>(CharSplits<'a, P>); +delegate_iter!{pattern &'a str in Split<'a, P>} + +/// Return type of `StrExt::split_terminator` +#[deriving(Clone)] +#[unstable = "might get removed in favour of a constructor method on Split"] +pub struct SplitTerminator<'a, P>(CharSplits<'a, P>); +delegate_iter!{pattern &'a str in SplitTerminator<'a, P>} + +/// Return type of `StrExt::splitn` +#[deriving(Clone)] +#[stable] +pub struct SplitN<'a, P>(CharSplitsN<'a, P>); +delegate_iter!{pattern forward &'a str in SplitN<'a, P>} + +/// Return type of `StrExt::rsplitn` +#[deriving(Clone)] +#[stable] +pub struct RSplitN<'a, P>(CharSplitsN<'a, P>); +delegate_iter!{pattern forward &'a str in RSplitN<'a, P>} + /// Methods for string slices #[allow(missing_docs)] pub trait StrExt for Sized? { // NB there are no docs here are they're all located on the StrExt trait in // libcollections, not here. - fn contains(&self, needle: &str) -> bool; - fn contains_char(&self, needle: char) -> bool; + fn contains(&self, pat: &str) -> bool; + fn contains_char(&self, pat: P) -> bool; fn chars<'a>(&'a self) -> Chars<'a>; fn bytes<'a>(&'a self) -> Bytes<'a>; fn char_indices<'a>(&'a self) -> CharIndices<'a>; - fn split<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>; - fn splitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>; - fn split_terminator<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>; - fn rsplitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>; + fn split<'a, P: CharEq>(&'a self, pat: P) -> Split<'a, P>; + fn splitn<'a, P: CharEq>(&'a self, count: uint, pat: P) -> SplitN<'a, P>; + fn split_terminator<'a, P: CharEq>(&'a self, pat: P) -> SplitTerminator<'a, P>; + fn rsplitn<'a, P: CharEq>(&'a self, count: uint, pat: P) -> RSplitN<'a, P>; fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a>; - fn split_str<'a>(&'a self, &'a str) -> StrSplits<'a>; + fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a>; fn lines<'a>(&'a self) -> Lines<'a>; fn lines_any<'a>(&'a self) -> LinesAny<'a>; fn char_len(&self) -> uint; @@ -1183,20 +1275,20 @@ pub trait StrExt for Sized? { fn slice_to<'a>(&'a self, end: uint) -> &'a str; fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str; unsafe fn slice_unchecked<'a>(&'a self, begin: uint, end: uint) -> &'a str; - fn starts_with(&self, needle: &str) -> bool; - fn ends_with(&self, needle: &str) -> bool; - fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str; - fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str; - fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str; + fn starts_with(&self, pat: &str) -> bool; + fn ends_with(&self, pat: &str) -> bool; + fn trim_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; + fn trim_left_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; + fn trim_right_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; fn is_char_boundary(&self, index: uint) -> bool; fn char_range_at(&self, start: uint) -> CharRange; fn char_range_at_reverse(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; fn char_at_reverse(&self, i: uint) -> char; fn as_bytes<'a>(&'a self) -> &'a [u8]; - fn find(&self, search: C) -> Option; - fn rfind(&self, search: C) -> Option; - fn find_str(&self, &str) -> Option; + fn find(&self, pat: P) -> Option; + fn rfind(&self, pat: P) -> Option; + fn find_str(&self, pat: &str) -> Option; fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>; fn subslice_offset(&self, inner: &str) -> uint; fn as_ptr(&self) -> *const u8; @@ -1218,8 +1310,8 @@ impl StrExt for str { } #[inline] - fn contains_char(&self, needle: char) -> bool { - self.find(needle).is_some() + fn contains_char(&self, pat: P) -> bool { + self.find(pat).is_some() } #[inline] @@ -1229,9 +1321,7 @@ impl StrExt for str { #[inline] fn bytes(&self) -> Bytes { - fn deref(&x: &u8) -> u8 { x } - - Bytes { inner: self.as_bytes().iter().map(BytesFn(deref)) } + Bytes(self.as_bytes().iter().map(BytesDeref)) } #[inline] @@ -1240,43 +1330,44 @@ impl StrExt for str { } #[inline] - fn split(&self, sep: Sep) -> CharSplits { - CharSplits { + #[allow(deprecated)] // For using CharSplits + fn split(&self, pat: P) -> Split

{ + Split(CharSplits { string: self, - only_ascii: sep.only_ascii(), - sep: sep, + only_ascii: pat.only_ascii(), + sep: pat, allow_trailing_empty: true, finished: false, - } + }) } #[inline] - fn splitn(&self, count: uint, sep: Sep) - -> CharSplitsN { - CharSplitsN { - iter: self.split(sep), + #[allow(deprecated)] // For using CharSplitsN + fn splitn(&self, count: uint, pat: P) -> SplitN

{ + SplitN(CharSplitsN { + iter: self.split(pat).0, count: count, invert: false, - } + }) } #[inline] - fn split_terminator(&self, sep: Sep) - -> CharSplits { - CharSplits { + #[allow(deprecated)] // For using CharSplits + fn split_terminator(&self, pat: P) -> SplitTerminator

{ + SplitTerminator(CharSplits { allow_trailing_empty: false, - ..self.split(sep) - } + ..self.split(pat).0 + }) } #[inline] - fn rsplitn(&self, count: uint, sep: Sep) - -> CharSplitsN { - CharSplitsN { - iter: self.split(sep), + #[allow(deprecated)] // For using CharSplitsN + fn rsplitn(&self, count: uint, pat: P) -> RSplitN

{ + RSplitN(CharSplitsN { + iter: self.split(pat).0, count: count, invert: true, - } + }) } #[inline] @@ -1290,8 +1381,8 @@ impl StrExt for str { } #[inline] - fn split_str<'a>(&'a self, sep: &'a str) -> StrSplits<'a> { - StrSplits { + fn split_str<'a>(&'a self, sep: &'a str) -> SplitStr<'a> { + SplitStr { it: self.match_indices(sep), last_end: 0, finished: false @@ -1300,7 +1391,7 @@ impl StrExt for str { #[inline] fn lines(&self) -> Lines { - Lines { inner: self.split_terminator('\n') } + Lines { inner: self.split_terminator('\n').0 } } fn lines_any(&self) -> LinesAny { @@ -1393,12 +1484,12 @@ impl StrExt for str { } #[inline] - fn trim_chars(&self, mut to_trim: C) -> &str { - let cur = match self.find(|&mut: c: char| !to_trim.matches(c)) { + fn trim_matches(&self, mut pat: P) -> &str { + let cur = match self.find(|&mut: c: char| !pat.matches(c)) { None => "", Some(i) => unsafe { self.slice_unchecked(i, self.len()) } }; - match cur.rfind(|&mut: c: char| !to_trim.matches(c)) { + match cur.rfind(|&mut: c: char| !pat.matches(c)) { None => "", Some(i) => { let right = cur.char_range_at(i).next; @@ -1408,16 +1499,16 @@ impl StrExt for str { } #[inline] - fn trim_left_chars(&self, mut to_trim: C) -> &str { - match self.find(|&mut: c: char| !to_trim.matches(c)) { + fn trim_left_matches(&self, mut pat: P) -> &str { + match self.find(|&mut: c: char| !pat.matches(c)) { None => "", Some(first) => unsafe { self.slice_unchecked(first, self.len()) } } } #[inline] - fn trim_right_chars(&self, mut to_trim: C) -> &str { - match self.rfind(|&mut: c: char| !to_trim.matches(c)) { + fn trim_right_matches(&self, mut pat: P) -> &str { + match self.rfind(|&mut: c: char| !pat.matches(c)) { None => "", Some(last) => { let next = self.char_range_at(last).next; @@ -1504,23 +1595,23 @@ impl StrExt for str { unsafe { mem::transmute(self) } } - fn find(&self, mut search: C) -> Option { - if search.only_ascii() { - self.bytes().position(|b| search.matches(b as char)) + fn find(&self, mut pat: P) -> Option { + if pat.only_ascii() { + self.bytes().position(|b| pat.matches(b as char)) } else { for (index, c) in self.char_indices() { - if search.matches(c) { return Some(index); } + if pat.matches(c) { return Some(index); } } None } } - fn rfind(&self, mut search: C) -> Option { - if search.only_ascii() { - self.bytes().rposition(|b| search.matches(b as char)) + fn rfind(&self, mut pat: P) -> Option { + if pat.only_ascii() { + self.bytes().rposition(|b| pat.matches(b as char)) } else { for (index, c) in self.char_indices().rev() { - if search.matches(c) { return Some(index); } + if pat.matches(c) { return Some(index); } } None } @@ -1596,14 +1687,3 @@ impl<'a> DoubleEndedIterator<&'a str> for LinesAny<'a> { #[inline] fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() } } -impl<'a> Iterator for Bytes<'a> { - #[inline] - fn next(&mut self) -> Option { self.inner.next() } - #[inline] - fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } -} -impl<'a> DoubleEndedIterator for Bytes<'a> { - #[inline] - fn next_back(&mut self) -> Option { self.inner.next_back() } -} -impl<'a> ExactSizeIterator for Bytes<'a> {} diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 0fd69ea25bc0d..1d998567b6ea3 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -817,7 +817,7 @@ impl NonCamelCaseTypes { fn is_camel_case(ident: ast::Ident) -> bool { let ident = token::get_ident(ident); if ident.get().is_empty() { return true; } - let ident = ident.get().trim_chars('_'); + let ident = ident.get().trim_matches('_'); // start with a non-lowercase letter rather than non-uppercase // ones (some scripts don't have a concept of upper/lowercase) @@ -940,8 +940,8 @@ impl NonSnakeCase { fn is_snake_case(ident: ast::Ident) -> bool { let ident = token::get_ident(ident); if ident.get().is_empty() { return true; } - let ident = ident.get().trim_left_chars('\''); - let ident = ident.trim_chars('_'); + let ident = ident.get().trim_left_matches('\''); + let ident = ident.trim_matches('_'); let mut allow_underscore = true; ident.chars().all(|c| { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 7d10188c437e2..4cb2e496d92c0 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -26,7 +26,7 @@ use mem; use option::Option; use option::Option::{Some, None}; use slice::SliceExt; -use str::{CharSplits, FromStr, StrVector, StrExt}; +use str::{SplitTerminator, FromStr, StrVector, StrExt}; use string::{String, ToString}; use unicode::char::UnicodeChar; use vec::Vec; @@ -38,7 +38,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 str, Option<&'a str>, CharSplits<'a, char>, fn(&'a str) -> Option<&'a str>>; + Map<&'a str, Option<&'a str>, SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>; /// Iterator that yields successive components of a Path as &[u8] pub type Components<'a> = diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index a3d4dd057d002..3b0cc1443f0c7 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -24,16 +24,15 @@ use core::iter::{Filter, AdditiveIterator}; use core::mem; use core::num::Int; use core::slice; -use core::str::CharSplits; +use core::str::Split; use u_char::UnicodeChar; use tables::grapheme::GraphemeCat; /// An iterator over the words of a string, separated by a sequence of whitespace -/// FIXME: This should be opaque #[stable] pub struct Words<'a> { - inner: Filter<&'a str, CharSplits<'a, fn(char) -> bool>, fn(&&str) -> bool>, + inner: Filter<&'a str, Split<'a, fn(char) -> bool>, fn(&&str) -> bool>, } /// Methods for Unicode string slices @@ -90,12 +89,12 @@ impl UnicodeStr for str { #[inline] fn trim_left(&self) -> &str { - self.trim_left_chars(|&: c: char| c.is_whitespace()) + self.trim_left_matches(|&: c: char| c.is_whitespace()) } #[inline] fn trim_right(&self) -> &str { - self.trim_right_chars(|&: c: char| c.is_whitespace()) + self.trim_right_matches(|&: c: char| c.is_whitespace()) } }