File tree 4 files changed +95
-0
lines changed
doc/unstable-book/src/library-features
4 files changed +95
-0
lines changed Original file line number Diff line number Diff line change
1
+ # ` string_retain `
2
+
3
+ The tracking issue for this feature is: [ #43874 ]
4
+
5
+ [ #43874 ] : https://github.com/rust-lang/rust/issues/43874
6
+
7
+ ------------------------
8
+
9
+ Retains only the characters specified by the predicate.
10
+
11
+ In other words, remove all characters ` c ` such that ` f(c) ` returns ` false ` .
12
+ This method operates in place and preserves the order of the retained
13
+ characters.
14
+
15
+ ``` rust
16
+ #![feature(string_retain)]
17
+
18
+ let mut s = String :: from (" f_o_ob_ar" );
19
+
20
+ s . retain (| c | c != '_' );
21
+
22
+ assert_eq! (s , " foobar" );
23
+ ```
Original file line number Diff line number Diff line change @@ -1061,6 +1061,57 @@ impl String {
1061
1061
ch
1062
1062
}
1063
1063
1064
+ /// Retains only the characters specified by the predicate.
1065
+ ///
1066
+ /// In other words, remove all characters `c` such that `f(c)` returns `false`.
1067
+ /// This method operates in place and preserves the order of the retained
1068
+ /// characters.
1069
+ ///
1070
+ /// # Examples
1071
+ ///
1072
+ /// ```
1073
+ /// #![feature(string_retain)]
1074
+ ///
1075
+ /// let mut s = String::from("f_o_ob_ar");
1076
+ ///
1077
+ /// s.retain(|c| c != '_');
1078
+ ///
1079
+ /// assert_eq!(s, "foobar");
1080
+ /// ```
1081
+ #[ inline]
1082
+ #[ unstable( feature = "string_retain" , issue = "43874" ) ]
1083
+ pub fn retain < F > ( & mut self , mut f : F )
1084
+ where F : FnMut ( char ) -> bool
1085
+ {
1086
+ let len = self . len ( ) ;
1087
+ let mut del_bytes = 0 ;
1088
+ let mut idx = 0 ;
1089
+
1090
+ while idx < len {
1091
+ let ch = unsafe {
1092
+ self . slice_unchecked ( idx, len) . chars ( ) . next ( ) . unwrap ( )
1093
+ } ;
1094
+ let ch_len = ch. len_utf8 ( ) ;
1095
+
1096
+ if !f ( ch) {
1097
+ del_bytes += ch_len;
1098
+ } else if del_bytes > 0 {
1099
+ unsafe {
1100
+ ptr:: copy ( self . vec . as_ptr ( ) . offset ( idx as isize ) ,
1101
+ self . vec . as_mut_ptr ( ) . offset ( ( idx - del_bytes) as isize ) ,
1102
+ ch_len) ;
1103
+ }
1104
+ }
1105
+
1106
+ // Point idx to the next char
1107
+ idx += ch_len;
1108
+ }
1109
+
1110
+ if del_bytes > 0 {
1111
+ unsafe { self . vec . set_len ( len - del_bytes) ; }
1112
+ }
1113
+ }
1114
+
1064
1115
/// Inserts a character into this `String` at a byte position.
1065
1116
///
1066
1117
/// This is an `O(n)` operation as it requires copying every element in the
Original file line number Diff line number Diff line change 25
25
#![ feature( slice_rotate) ]
26
26
#![ feature( splice) ]
27
27
#![ feature( str_escape) ]
28
+ #![ feature( string_retain) ]
28
29
#![ feature( test) ]
29
30
#![ feature( unboxed_closures) ]
30
31
#![ feature( unicode) ]
Original file line number Diff line number Diff line change @@ -332,6 +332,26 @@ fn remove_bad() {
332
332
"ศ" . to_string ( ) . remove ( 1 ) ;
333
333
}
334
334
335
+ #[ test]
336
+ fn test_retain ( ) {
337
+ let mut s = String :: from ( "α_β_γ" ) ;
338
+
339
+ s. retain ( |_| true ) ;
340
+ assert_eq ! ( s, "α_β_γ" ) ;
341
+
342
+ s. retain ( |c| c != '_' ) ;
343
+ assert_eq ! ( s, "αβγ" ) ;
344
+
345
+ s. retain ( |c| c != 'β' ) ;
346
+ assert_eq ! ( s, "αγ" ) ;
347
+
348
+ s. retain ( |c| c == 'α' ) ;
349
+ assert_eq ! ( s, "α" ) ;
350
+
351
+ s. retain ( |_| false ) ;
352
+ assert_eq ! ( s, "" ) ;
353
+ }
354
+
335
355
#[ test]
336
356
fn insert ( ) {
337
357
let mut s = "foobar" . to_string ( ) ;
You can’t perform that action at this time.
0 commit comments