From d8f82c8e431472e9a1742a6923790b1f32e6e248 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 16 Oct 2013 21:56:31 -0700 Subject: [PATCH 1/3] Rewrite vec.contains() to be simpler --- src/libstd/vec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 3962df8e3bd8d..694f3344cc217 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1186,9 +1186,9 @@ impl<'self,T:Eq> ImmutableEqVector 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) } } From 2fcb53493dc80469acf86797c53dacc331629d50 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 16 Oct 2013 22:01:20 -0700 Subject: [PATCH 2/3] Implement new methods vec.starts_with()/vec.ends_with() --- src/librustc/back/rpath.rs | 7 ++---- src/librustpkg/tests.rs | 8 ++---- src/libstd/vec.rs | 46 +++++++++++++++++++++++++++++++++++ src/test/run-pass/tempfile.rs | 5 +--- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 0626ec0ece0a0..faf8dd25186f2 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -189,12 +189,9 @@ mod test { let mut d = Path::new(env!("CFG_PREFIX")); d.push("lib/rustc/triple/lib"); debug2!("test_prefix_path: {} vs. {}", - res.to_str(), + res, d.display()); - assert!(ends_with(res.as_bytes(), d.as_vec())); - fn ends_with(v: &[u8], needle: &[u8]) -> bool { - v.len() >= needle.len() && v.slice_from(v.len()-needle.len()) == needle - } + assert!(res.as_bytes().ends_with(d.as_vec())); } #[test] diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index d367399c0bf28..0fe168625187a 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -217,10 +217,6 @@ fn is_read_only(p: &Path) -> bool { } } -fn ends_with(v: &[u8], needle: &[u8]) -> bool { - v.len() >= needle.len() && v.slice_from(v.len() - needle.len()) == needle -} - fn test_sysroot() -> Path { // Totally gross hack but it's just for test cases. // Infer the sysroot from the exe name and pray that it's right. @@ -747,7 +743,7 @@ fn test_package_version() { &ws) { Some(p) => { let suffix = format!("0.4{}", os::consts::DLL_SUFFIX); - ends_with(p.as_vec(), suffix.as_bytes()) + p.as_vec().ends_with(suffix.as_bytes()) } None => false }); @@ -785,7 +781,7 @@ fn test_package_request_version() { Some(p) => { debug2!("installed: {}", p.display()); let suffix = format!("0.3{}", os::consts::DLL_SUFFIX); - ends_with(p.as_vec(), suffix.as_bytes()) + p.as_vec().ends_with(suffix.as_bytes()) } None => false }); diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 694f3344cc217..17dcced94859b 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1173,6 +1173,12 @@ pub trait ImmutableEqVector { /// 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 for &'self [T] { @@ -1190,6 +1196,18 @@ impl<'self,T:Eq> ImmutableEqVector for &'self [T] { fn contains(&self, x: &T) -> bool { 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) + } } /// Extension methods for vectors containing `TotalOrd` elements. @@ -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)] diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 837194fcf9f07..5d12f4e88177c 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -30,13 +30,10 @@ fn test_tempdir() { let path = { let p = TempDir::new_in(&Path::new("."), "foobar").unwrap(); let p = p.path(); - assert!(ends_with(p.as_vec(), bytes!("foobar"))); + assert!(p.as_vec().ends_with(bytes!("foobar"))); p.clone() }; assert!(!os::path_exists(&path)); - fn ends_with(v: &[u8], needle: &[u8]) -> bool { - v.len() >= needle.len() && v.slice_from(v.len()-needle.len()) == needle - } } fn test_rm_tempdir() { From 87a2d032ff6fe74e97348189f95a3a91fd9e228e Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Wed, 16 Oct 2013 23:02:46 -0700 Subject: [PATCH 3/3] Rewrite str.starts_with()/ends_with() to be simpler --- src/libstd/str.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/libstd/str.rs b/src/libstd/str.rs index decfbb0785c38..5c6974de17dae 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -827,17 +827,6 @@ pub fn eq(a: &~str, b: &~str) -> bool { eq_slice(*a, *b) } -/* -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 {