about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-14 20:29:15 -0700
committerGitHub <noreply@github.com>2016-09-14 20:29:15 -0700
commit16ff9e22cdb552fd10e6cee2eb22f0c5da6d7e79 (patch)
tree3d42f5b6742c237ff7a6a7157f67c616080cb015
parent6ffdda1ba183c981d57e63b59c88184be449eee4 (diff)
parentebda77072a56a43d33d5723196a5ae37544a1ab9 (diff)
downloadrust-16ff9e22cdb552fd10e6cee2eb22f0c5da6d7e79.tar.gz
rust-16ff9e22cdb552fd10e6cee2eb22f0c5da6d7e79.zip
Auto merge of #36347 - knight42:str-replacen, r=alexcrichton
Implement std::str::replacen

Replaces first N matches of a pattern with another string.

```
assert_eq!("acaaa".replacen(a, "b", 3), "bcbba")
```
-rw-r--r--src/libcollections/str.rs43
-rw-r--r--src/libcollectionstest/lib.rs1
-rw-r--r--src/libcollectionstest/str.rs14
3 files changed, 58 insertions, 0 deletions
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 999c84ba705..6a6b450e518 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -1594,6 +1594,49 @@ impl str {
         result
     }
 
+    /// Replaces first N matches of a pattern with another string.
+    ///
+    /// `replacen` creates a new [`String`], and copies the data from this string slice into it.
+    /// While doing so, it attempts to find matches of a pattern. If it finds any, it
+    /// replaces them with the replacement string slice at most `N` times.
+    ///
+    /// [`String`]: string/struct.String.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # #![feature(str_replacen)]
+    /// let s = "foo foo 123 foo";
+    /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
+    /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
+    /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
+    /// ```
+    ///
+    /// When the pattern doesn't match:
+    ///
+    /// ```
+    /// # #![feature(str_replacen)]
+    /// let s = "this is old";
+    /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
+    /// ```
+    #[unstable(feature = "str_replacen",
+               issue = "36436",
+               reason = "only need to replace first N matches")]
+    pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
+        // Hope to reduce the times of re-allocation
+        let mut result = String::with_capacity(32);
+        let mut last_end = 0;
+        for (start, part) in self.match_indices(pat).take(count) {
+            result.push_str(unsafe { self.slice_unchecked(last_end, start) });
+            result.push_str(to);
+            last_end = start + part.len();
+        }
+        result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
+        result
+    }
+
     /// Returns the lowercase equivalent of this string slice, as a new [`String`].
     ///
     /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs
index 32a07e3e7e6..878581a4f29 100644
--- a/src/libcollectionstest/lib.rs
+++ b/src/libcollectionstest/lib.rs
@@ -21,6 +21,7 @@
 #![feature(rand)]
 #![feature(step_by)]
 #![feature(str_escape)]
+#![feature(str_replacen)]
 #![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index a61925cd3be..62e164a569a 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -219,6 +219,20 @@ fn test_is_empty() {
 }
 
 #[test]
+fn test_replacen() {
+    assert_eq!("".replacen('a', "b", 5), "");
+    assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
+    assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
+
+    let test = "test";
+    assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
+    assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
+    assert_eq!(" test test ".replacen(test, "", 5), "   ");
+
+    assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
+}
+
+#[test]
 fn test_replace() {
     let a = "a";
     assert_eq!("".replace(a, "b"), "");