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 @@ -1031,6 +1031,57 @@ impl String {
1031
1031
ch
1032
1032
}
1033
1033
1034
+ /// Retains only the characters specified by the predicate.
1035
+ ///
1036
+ /// In other words, remove all characters `c` such that `f(c)` returns `false`.
1037
+ /// This method operates in place and preserves the order of the retained
1038
+ /// characters.
1039
+ ///
1040
+ /// # Examples
1041
+ ///
1042
+ /// ```
1043
+ /// #![feature(string_retain)]
1044
+ ///
1045
+ /// let mut s = String::from("f_o_ob_ar");
1046
+ ///
1047
+ /// s.retain(|c| c != '_');
1048
+ ///
1049
+ /// assert_eq!(s, "foobar");
1050
+ /// ```
1051
+ #[ inline]
1052
+ #[ unstable( feature = "string_retain" , issue = "43874" ) ]
1053
+ pub fn retain < F > ( & mut self , mut f : F )
1054
+ where F : FnMut ( char ) -> bool
1055
+ {
1056
+ let len = self . len ( ) ;
1057
+ let mut del_bytes = 0 ;
1058
+ let mut idx = 0 ;
1059
+
1060
+ while idx < len {
1061
+ let ch = unsafe {
1062
+ self . slice_unchecked ( idx, len) . chars ( ) . next ( ) . unwrap ( )
1063
+ } ;
1064
+ let ch_len = ch. len_utf8 ( ) ;
1065
+
1066
+ if !f ( ch) {
1067
+ del_bytes += ch_len;
1068
+ } else if del_bytes > 0 {
1069
+ unsafe {
1070
+ ptr:: copy ( self . vec . as_ptr ( ) . offset ( idx as isize ) ,
1071
+ self . vec . as_mut_ptr ( ) . offset ( ( idx - del_bytes) as isize ) ,
1072
+ ch_len) ;
1073
+ }
1074
+ }
1075
+
1076
+ // Point idx to the next char
1077
+ idx += ch_len;
1078
+ }
1079
+
1080
+ if del_bytes > 0 {
1081
+ unsafe { self . vec . set_len ( len - del_bytes) ; }
1082
+ }
1083
+ }
1084
+
1034
1085
/// Inserts a character into this `String` at a byte position.
1035
1086
///
1036
1087
/// This is an `O(n)` operation as it requires copying every element in the
Original file line number Diff line number Diff line change 26
26
#![ feature( splice) ]
27
27
#![ feature( str_checked_slicing) ]
28
28
#![ feature( str_escape) ]
29
+ #![ feature( string_retain) ]
29
30
#![ feature( test) ]
30
31
#![ feature( unboxed_closures) ]
31
32
#![ 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