about summary refs log tree commit diff
path: root/src/libcore/str
diff options
context:
space:
mode:
authorMarvin Löbel <loebel.marvin@gmail.com>2015-02-17 22:57:14 +0100
committerMarvin Löbel <loebel.marvin@gmail.com>2015-02-20 00:58:06 +0100
commitc1de0a0f9ea9863407363ce31bb698e9988215ee (patch)
treeee58e9afdedaddd01673998442a0916d0b801e35 /src/libcore/str
parentee930b0262520e25c5b66b037c65dab538ce5e64 (diff)
downloadrust-c1de0a0f9ea9863407363ce31bb698e9988215ee.tar.gz
rust-c1de0a0f9ea9863407363ce31bb698e9988215ee.zip
Added a Pattern impl that delegates to the dereference of a type.
This allows to match with a `&String` or `&&str`, for example.
Diffstat (limited to 'src/libcore/str')
-rw-r--r--src/libcore/str/mod.rs25
-rw-r--r--src/libcore/str/pattern.rs86
2 files changed, 89 insertions, 22 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index bdb3b854fe2..a9308302033 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -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> {
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 2b77d877cf4..501fc27b376 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -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));
+}