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 @@ -1031,6 +1031,57 @@ impl String {
10311031 ch
10321032 }
10331033
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+
10341085 /// Inserts a character into this `String` at a byte position.
10351086 ///
10361087 /// This is an `O(n)` operation as it requires copying every element in the
Original file line number Diff line number Diff line change 2626#![ feature( splice) ]
2727#![ feature( str_checked_slicing) ]
2828#![ feature( str_escape) ]
29+ #![ feature( string_retain) ]
2930#![ feature( test) ]
3031#![ feature( unboxed_closures) ]
3132#![ 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