--- /dev/null
+# `string_retain`
+
+The tracking issue for this feature is: [#43874]
+
+[#43874]: https://github.com/rust-lang/rust/issues/43874
+
+------------------------
+
+Retains only the characters specified by the predicate.
+
+In other words, remove all characters `c` such that `f(c)` returns `false`.
+This method operates in place and preserves the order of the retained
+characters.
+
+```rust
+#![feature(string_retain)]
+
+let mut s = String::from("f_o_ob_ar");
+
+s.retain(|c| c != '_');
+
+assert_eq!(s, "foobar");
+```
ch
}
+ /// Retains only the characters specified by the predicate.
+ ///
+ /// In other words, remove all characters `c` such that `f(c)` returns `false`.
+ /// This method operates in place and preserves the order of the retained
+ /// characters.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(string_retain)]
+ ///
+ /// let mut s = String::from("f_o_ob_ar");
+ ///
+ /// s.retain(|c| c != '_');
+ ///
+ /// assert_eq!(s, "foobar");
+ /// ```
+ #[inline]
+ #[unstable(feature = "string_retain", issue = "43874")]
+ pub fn retain<F>(&mut self, mut f: F)
+ where F: FnMut(char) -> bool
+ {
+ let len = self.len();
+ let mut del_bytes = 0;
+ let mut idx = 0;
+
+ while idx < len {
+ let ch = unsafe {
+ self.slice_unchecked(idx, len).chars().next().unwrap()
+ };
+ let ch_len = ch.len_utf8();
+
+ if !f(ch) {
+ del_bytes += ch_len;
+ } else if del_bytes > 0 {
+ unsafe {
+ ptr::copy(self.vec.as_ptr().offset(idx as isize),
+ self.vec.as_mut_ptr().offset((idx - del_bytes) as isize),
+ ch_len);
+ }
+ }
+
+ // Point idx to the next char
+ idx += ch_len;
+ }
+
+ if del_bytes > 0 {
+ unsafe { self.vec.set_len(len - del_bytes); }
+ }
+ }
+
/// Inserts a character into this `String` at a byte position.
///
/// This is an `O(n)` operation as it requires copying every element in the
"ศ".to_string().remove(1);
}
+#[test]
+fn test_retain() {
+ let mut s = String::from("α_β_γ");
+
+ s.retain(|_| true);
+ assert_eq!(s, "α_β_γ");
+
+ s.retain(|c| c != '_');
+ assert_eq!(s, "αβγ");
+
+ s.retain(|c| c != 'β');
+ assert_eq!(s, "αγ");
+
+ s.retain(|c| c == 'α');
+ assert_eq!(s, "α");
+
+ s.retain(|_| false);
+ assert_eq!(s, "");
+}
+
#[test]
fn insert() {
let mut s = "foobar".to_string();