about summary refs log tree commit diff
path: root/library/alloc/src/string.rs
diff options
context:
space:
mode:
authorJosh Cotton <jcotton42@outlook.com>2021-03-05 11:27:58 -0500
committerJosh Cotton <jcotton42@outlook.com>2021-03-05 11:27:58 -0500
commita2571cfc8b6f5cf5d8d2e7075ac4809aceae9541 (patch)
treef314d496a14b03b818e2594831771d1c35a1b191 /library/alloc/src/string.rs
parent8ccc89bc312caa65ca46b55b47492abdd5b6910a (diff)
downloadrust-a2571cfc8b6f5cf5d8d2e7075ac4809aceae9541.tar.gz
rust-a2571cfc8b6f5cf5d8d2e7075ac4809aceae9541.zip
Implement String::remove_matches
Diffstat (limited to 'library/alloc/src/string.rs')
-rw-r--r--library/alloc/src/string.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index b567d0a2fe2..45adebf77cb 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1202,6 +1202,62 @@ impl String {
         ch
     }
 
+    /// Remove all matches of pattern `pat` in the `String`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(string_remove_matches)]
+    /// let mut s = String::from("Trees are not green, the sky is not blue.");
+    /// s.remove_matches("not ");
+    /// assert_eq!("Trees are green, the sky is blue.", s);
+    /// ```
+    ///
+    /// Matches will be detected and removed iteratively, so in cases where
+    /// patterns overlap, only the first pattern will be removed:
+    ///
+    /// ```
+    /// #![feature(string_remove_matches)]
+    /// let mut s = String::from("banana");
+    /// s.remove_matches("ana");
+    /// assert_eq!("bna", s);
+    /// ```
+    #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")]
+    pub fn remove_matches<'a, P>(&'a mut self, pat: P)
+    where
+        P: for<'x> Pattern<'x>,
+    {
+        use core::str::pattern::Searcher;
+
+        let matches = {
+            let mut searcher = pat.into_searcher(self);
+            let mut matches = Vec::new();
+
+            while let Some(m) = searcher.next_match() {
+                matches.push(m);
+            }
+
+            matches
+        };
+
+        let len = self.len();
+        let mut shrunk_by = 0;
+
+        // SAFETY: start and end will be on utf8 byte boundaries per
+        // the Searcher docs
+        unsafe {
+            for (start, end) in matches {
+                ptr::copy(
+                    self.vec.as_mut_ptr().add(end - shrunk_by),
+                    self.vec.as_mut_ptr().add(start - shrunk_by),
+                    len - end,
+                );
+                shrunk_by += end - start;
+            }
+            self.vec.set_len(len - shrunk_by);
+        }
+    }
+
     /// Retains only the characters specified by the predicate.
     ///
     /// In other words, remove all characters `c` such that `f(c)` returns `false`.