about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-10-17 09:56:27 -0700
committerbors <bors@rust-lang.org>2013-10-17 09:56:27 -0700
commitd4a32386f3b61a4997de54ed00c0a80fd07ecc75 (patch)
treed766986b7eed566a705dd6f8fd135cb10614a881 /src/libstd
parent2cb96a4eaf55cdf7f08e3493cf2953278b8acc43 (diff)
parent87a2d032ff6fe74e97348189f95a3a91fd9e228e (diff)
downloadrust-d4a32386f3b61a4997de54ed00c0a80fd07ecc75.tar.gz
rust-d4a32386f3b61a4997de54ed00c0a80fd07ecc75.zip
auto merge of #9907 : kballard/rust/vec_ends_with, r=alexcrichton
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/str.rs25
-rw-r--r--src/libstd/vec.rs50
2 files changed, 54 insertions, 21 deletions
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index decfbb0785c..5c6974de17d 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -828,17 +828,6 @@ pub fn eq(a: &~str, b: &~str) -> bool {
 }
 
 /*
-Section: Searching
-*/
-
-// Utility used by various searching functions
-fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool {
-    let mut i = at;
-    for c in needle.byte_iter() { if haystack[i] != c { return false; } i += 1u; }
-    return true;
-}
-
-/*
 Section: Misc
 */
 
@@ -2018,18 +2007,16 @@ impl<'self> StrSlice<'self> for &'self str {
         }
     }
 
+    #[inline]
     fn starts_with<'a>(&self, needle: &'a str) -> bool {
-        let (self_len, needle_len) = (self.len(), needle.len());
-        if needle_len == 0u { true }
-        else if needle_len > self_len { false }
-        else { match_at(*self, needle, 0u) }
+        let n = needle.len();
+        self.len() >= n && needle == self.slice_to(n)
     }
 
+    #[inline]
     fn ends_with(&self, needle: &str) -> bool {
-        let (self_len, needle_len) = (self.len(), needle.len());
-        if needle_len == 0u { true }
-        else if needle_len > self_len { false }
-        else { match_at(*self, needle, self_len - needle_len) }
+        let (m, n) = (self.len(), needle.len());
+        m >= n && needle == self.slice_from(m - n)
     }
 
     fn escape_default(&self) -> ~str {
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 3962df8e3bd..17dcced9485 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -1173,6 +1173,12 @@ pub trait ImmutableEqVector<T:Eq> {
 
     /// Return true if a vector contains an element with the given value
     fn contains(&self, x: &T) -> bool;
+
+    /// Returns true if `needle` is a prefix of the vector.
+    fn starts_with(&self, needle: &[T]) -> bool;
+
+    /// Returns true if `needle` is a suffix of the vector.
+    fn ends_with(&self, needle: &[T]) -> bool;
 }
 
 impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
@@ -1186,9 +1192,21 @@ impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
         self.iter().rposition(|x| *x == *t)
     }
 
+    #[inline]
     fn contains(&self, x: &T) -> bool {
-        for elt in self.iter() { if *x == *elt { return true; } }
-        false
+        self.iter().any(|elt| *x == *elt)
+    }
+
+    #[inline]
+    fn starts_with(&self, needle: &[T]) -> bool {
+        let n = needle.len();
+        self.len() >= n && needle == self.slice_to(n)
+    }
+
+    #[inline]
+    fn ends_with(&self, needle: &[T]) -> bool {
+        let (m, n) = (self.len(), needle.len());
+        m >= n && needle == self.slice_from(m - n)
     }
 }
 
@@ -3828,6 +3846,34 @@ mod tests {
         assert_eq!(xs.capacity(), 100);
         assert_eq!(xs, range(0, 100).to_owned_vec());
     }
+
+    #[test]
+    fn test_starts_with() {
+        assert!(bytes!("foobar").starts_with(bytes!("foo")));
+        assert!(!bytes!("foobar").starts_with(bytes!("oob")));
+        assert!(!bytes!("foobar").starts_with(bytes!("bar")));
+        assert!(!bytes!("foo").starts_with(bytes!("foobar")));
+        assert!(!bytes!("bar").starts_with(bytes!("foobar")));
+        assert!(bytes!("foobar").starts_with(bytes!("foobar")));
+        let empty: &[u8] = [];
+        assert!(empty.starts_with(empty));
+        assert!(!empty.starts_with(bytes!("foo")));
+        assert!(bytes!("foobar").starts_with(empty));
+    }
+
+    #[test]
+    fn test_ends_with() {
+        assert!(bytes!("foobar").ends_with(bytes!("bar")));
+        assert!(!bytes!("foobar").ends_with(bytes!("oba")));
+        assert!(!bytes!("foobar").ends_with(bytes!("foo")));
+        assert!(!bytes!("foo").ends_with(bytes!("foobar")));
+        assert!(!bytes!("bar").ends_with(bytes!("foobar")));
+        assert!(bytes!("foobar").ends_with(bytes!("foobar")));
+        let empty: &[u8] = [];
+        assert!(empty.ends_with(empty));
+        assert!(!empty.ends_with(bytes!("foo")));
+        assert!(bytes!("foobar").ends_with(empty));
+    }
 }
 
 #[cfg(test)]