File tree Expand file tree Collapse file tree 4 files changed +95
-0
lines changed
doc/unstable-book/src/library-features Expand file tree Collapse file tree 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 {
10611061 ch
10621062 }
10631063
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+
10641115 /// Inserts a character into this `String` at a byte position.
10651116 ///
10661117 /// This is an `O(n)` operation as it requires copying every element in the
Original file line number Diff line number Diff line change 2525#![ feature( slice_rotate) ]
2626#![ feature( splice) ]
2727#![ feature( str_escape) ]
28+ #![ feature( string_retain) ]
2829#![ feature( test) ]
2930#![ feature( unboxed_closures) ]
3031#![ feature( unicode) ]
Original file line number Diff line number Diff line change @@ -332,6 +332,26 @@ fn remove_bad() {
332332 "ศ" . to_string ( ) . remove ( 1 ) ;
333333}
334334
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+
335355#[ test]
336356fn insert ( ) {
337357 let mut s = "foobar" . to_string ( ) ;
You can’t perform that action at this time.
0 commit comments