Added a Pattern impl that delegates to the dereference of a type.
This allows to match with a `&String` or `&&str`, for example.
This commit is contained in:
parent
ee930b0262
commit
c1de0a0f9e
@ -75,7 +75,7 @@ macro_rules! delegate_iter {
|
||||
};
|
||||
(pattern $te:ty : $ti:ty) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, P: CharEq> Iterator for $ti {
|
||||
impl<'a, P: Pattern<'a>> Iterator for $ti {
|
||||
type Item = $te;
|
||||
|
||||
#[inline]
|
||||
@ -88,7 +88,8 @@ macro_rules! delegate_iter {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, P: CharEq> DoubleEndedIterator for $ti {
|
||||
impl<'a, P: Pattern<'a>> DoubleEndedIterator for $ti
|
||||
where P::Searcher: DoubleEndedSearcher<'a> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<$te> {
|
||||
self.0.next_back()
|
||||
@ -97,7 +98,8 @@ macro_rules! delegate_iter {
|
||||
};
|
||||
(pattern forward $te:ty : $ti:ty) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, P: CharEq> Iterator for $ti {
|
||||
impl<'a, P: Pattern<'a>> Iterator for $ti
|
||||
where P::Searcher: DoubleEndedSearcher<'a> {
|
||||
type Item = $te;
|
||||
|
||||
#[inline]
|
||||
@ -610,7 +612,8 @@ where P::Searcher: DoubleEndedSearcher<'a> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> {
|
||||
impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P>
|
||||
where P::Searcher: DoubleEndedSearcher<'a> {
|
||||
type Item = &'a str;
|
||||
|
||||
#[inline]
|
||||
@ -1379,7 +1382,7 @@ impl StrExt for str {
|
||||
Split(CharSplits {
|
||||
start: 0,
|
||||
end: self.len(),
|
||||
matcher: pat.into_matcher(self),
|
||||
matcher: pat.into_searcher(self),
|
||||
allow_trailing_empty: true,
|
||||
finished: false,
|
||||
})
|
||||
@ -1413,7 +1416,7 @@ impl StrExt for str {
|
||||
|
||||
#[inline]
|
||||
fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
|
||||
MatchIndices(pat.into_matcher(self))
|
||||
MatchIndices(pat.into_searcher(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1487,7 +1490,7 @@ impl StrExt for str {
|
||||
where P::Searcher: DoubleEndedSearcher<'a> {
|
||||
let mut i = 0;
|
||||
let mut j = self.len();
|
||||
let mut matcher = pat.into_matcher(self);
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((a, b)) = matcher.next_reject() {
|
||||
i = a;
|
||||
j = b; // Rember earliest known match, correct it below if
|
||||
@ -1505,7 +1508,7 @@ impl StrExt for str {
|
||||
#[inline]
|
||||
fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
let mut i = 0;
|
||||
let mut matcher = pat.into_matcher(self);
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((a, _)) = matcher.next_reject() {
|
||||
i = a;
|
||||
}
|
||||
@ -1519,7 +1522,7 @@ impl StrExt for str {
|
||||
fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
|
||||
where P::Searcher: ReverseSearcher<'a> {
|
||||
let mut j = self.len();
|
||||
let mut matcher = pat.into_matcher(self);
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((_, b)) = matcher.next_reject_back() {
|
||||
j = b;
|
||||
}
|
||||
@ -1591,12 +1594,12 @@ impl StrExt for str {
|
||||
}
|
||||
|
||||
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
|
||||
pat.into_matcher(self).next_match().map(|(i, _)| i)
|
||||
pat.into_searcher(self).next_match().map(|(i, _)| i)
|
||||
}
|
||||
|
||||
fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
|
||||
where P::Searcher: ReverseSearcher<'a> {
|
||||
pat.into_matcher(self).next_match_back().map(|(i, _)| i)
|
||||
pat.into_searcher(self).next_match_back().map(|(i, _)| i)
|
||||
}
|
||||
|
||||
fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
|
||||
|
@ -17,16 +17,16 @@ use super::CharEq;
|
||||
|
||||
pub trait Pattern<'a>: Sized {
|
||||
type Searcher: Searcher<'a>;
|
||||
fn into_matcher(self, haystack: &'a str) -> Self::Searcher;
|
||||
fn into_searcher(self, haystack: &'a str) -> Self::Searcher;
|
||||
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
self.into_matcher(haystack).next_match().is_some()
|
||||
self.into_searcher(haystack).next_match().is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn match_starts_at(self, haystack: &'a str, idx: usize) -> bool {
|
||||
let mut matcher = self.into_matcher(haystack);
|
||||
let mut matcher = self.into_searcher(haystack);
|
||||
loop {
|
||||
match matcher.next() {
|
||||
SearchStep::Match(i, _) if i == idx => return true,
|
||||
@ -42,7 +42,7 @@ pub trait Pattern<'a>: Sized {
|
||||
#[inline]
|
||||
fn match_ends_at(self, haystack: &'a str, idx: usize) -> bool
|
||||
where Self::Searcher: ReverseSearcher<'a> {
|
||||
let mut matcher = self.into_matcher(haystack);
|
||||
let mut matcher = self.into_searcher(haystack);
|
||||
loop {
|
||||
match matcher.next_back() {
|
||||
SearchStep::Match(_, j) if idx == j => return true,
|
||||
@ -115,9 +115,11 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
|
||||
|
||||
pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
|
||||
|
||||
// Impl for CharEq
|
||||
// Impl for a CharEq wrapper
|
||||
|
||||
pub struct CharEqSearcher<'a, C> {
|
||||
struct CharEqPattern<C: CharEq>(C);
|
||||
|
||||
pub struct CharEqSearcher<'a, C: CharEq> {
|
||||
char_eq: C,
|
||||
haystack: &'a str,
|
||||
char_indices: super::CharIndices<'a>,
|
||||
@ -125,15 +127,15 @@ pub struct CharEqSearcher<'a, C> {
|
||||
ascii_only: bool,
|
||||
}
|
||||
|
||||
impl<'a, C: CharEq> Pattern<'a> for C {
|
||||
impl<'a, C: CharEq> Pattern<'a> for CharEqPattern<C> {
|
||||
type Searcher = CharEqSearcher<'a, C>;
|
||||
|
||||
#[inline]
|
||||
fn into_matcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> {
|
||||
fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> {
|
||||
CharEqSearcher {
|
||||
ascii_only: self.only_ascii(),
|
||||
ascii_only: self.0.only_ascii(),
|
||||
haystack: haystack,
|
||||
char_eq: self,
|
||||
char_eq: self.0,
|
||||
char_indices: haystack.char_indices(),
|
||||
}
|
||||
}
|
||||
@ -203,7 +205,7 @@ impl<'a, 'b> Pattern<'a> for &'b str {
|
||||
type Searcher = StrSearcher<'a, 'b>;
|
||||
|
||||
#[inline]
|
||||
fn into_matcher(self, haystack: &'a str) -> StrSearcher<'a, 'b> {
|
||||
fn into_searcher(self, haystack: &'a str) -> StrSearcher<'a, 'b> {
|
||||
StrSearcher {
|
||||
haystack: haystack,
|
||||
needle: self,
|
||||
@ -293,3 +295,65 @@ where F: FnOnce(&mut StrSearcher) -> SearchStep,
|
||||
SearchStep::Done
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! associated_items {
|
||||
($t:ty, $s:ident, $e:expr) => {
|
||||
// FIXME: #22463
|
||||
//type Searcher = $t;
|
||||
|
||||
fn into_searcher(self, haystack: &'a str) -> $t {
|
||||
let $s = self;
|
||||
$e.into_searcher(haystack)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
let $s = self;
|
||||
$e.is_contained_in(haystack)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn match_starts_at(self, haystack: &'a str, idx: usize) -> bool {
|
||||
let $s = self;
|
||||
$e.match_starts_at(haystack, idx)
|
||||
}
|
||||
|
||||
// FIXME: #21750
|
||||
/*#[inline]
|
||||
fn match_ends_at(self, haystack: &'a str, idx: usize) -> bool
|
||||
where $t: ReverseSearcher<'a> {
|
||||
let $s = self;
|
||||
$e.match_ends_at(haystack, idx)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// CharEq delegation impls
|
||||
|
||||
impl<'a, 'b> Pattern<'a> for &'b [char] {
|
||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
||||
s, CharEqPattern(s));
|
||||
}
|
||||
|
||||
impl<'a> Pattern<'a> for char {
|
||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
||||
s, CharEqPattern(s));
|
||||
}
|
||||
|
||||
impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
|
||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
||||
s, CharEqPattern(s));
|
||||
}
|
||||
|
||||
// Deref-forward impl
|
||||
|
||||
use ops::Deref;
|
||||
|
||||
impl<'a, 'b, P: 'b + ?Sized, T: Deref<Target = P> + ?Sized> Pattern<'a> for &'b T where &'b P: Pattern<'a> {
|
||||
type Searcher = <&'b P as Pattern<'a>>::Searcher;
|
||||
associated_items!(<&'b P as Pattern<'a>>::Searcher,
|
||||
s, (&**s));
|
||||
}
|
||||
|
@ -8,6 +8,16 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[test]
|
||||
fn test_pattern_deref_forward() {
|
||||
let data = "aabcdaa";
|
||||
assert!(data.contains("bcd"));
|
||||
assert!(data.contains(&"bcd"));
|
||||
assert!(data.contains(&&"bcd"));
|
||||
assert!(data.contains(&"bcd".to_string()));
|
||||
assert!(data.contains(&&"bcd".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_match_indices() {
|
||||
let data = "aä中!";
|
||||
|
Loading…
x
Reference in New Issue
Block a user