1
1
use crate :: alloc:: { Allocator , Global } ;
2
- use core:: mem:: { ManuallyDrop , SizedTypeProperties } ;
3
2
use core:: ptr;
4
3
use core:: slice;
5
4
@@ -20,6 +19,7 @@ use super::Vec;
20
19
/// ```
21
20
#[ unstable( feature = "drain_filter" , reason = "recently added" , issue = "43244" ) ]
22
21
#[ derive( Debug ) ]
22
+ #[ must_use = "iterators are lazy and do nothing unless consumed" ]
23
23
pub struct DrainFilter <
24
24
' a ,
25
25
T ,
55
55
pub fn allocator ( & self ) -> & A {
56
56
self . vec . allocator ( )
57
57
}
58
-
59
- /// Keep unyielded elements in the source `Vec`.
60
- ///
61
- /// # Examples
62
- ///
63
- /// ```
64
- /// #![feature(drain_filter)]
65
- /// #![feature(drain_keep_rest)]
66
- ///
67
- /// let mut vec = vec!['a', 'b', 'c'];
68
- /// let mut drain = vec.drain_filter(|_| true);
69
- ///
70
- /// assert_eq!(drain.next().unwrap(), 'a');
71
- ///
72
- /// // This call keeps 'b' and 'c' in the vec.
73
- /// drain.keep_rest();
74
- ///
75
- /// // If we wouldn't call `keep_rest()`,
76
- /// // `vec` would be empty.
77
- /// assert_eq!(vec, ['b', 'c']);
78
- /// ```
79
- #[ unstable( feature = "drain_keep_rest" , issue = "101122" ) ]
80
- pub fn keep_rest ( self ) {
81
- // At this moment layout looks like this:
82
- //
83
- // _____________________/-- old_len
84
- // / \
85
- // [kept] [yielded] [tail]
86
- // \_______/ ^-- idx
87
- // \-- del
88
- //
89
- // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`)
90
- //
91
- // 1. Move [tail] after [kept]
92
- // 2. Update length of the original vec to `old_len - del`
93
- // a. In case of ZST, this is the only thing we want to do
94
- // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do
95
- let mut this = ManuallyDrop :: new ( self ) ;
96
-
97
- unsafe {
98
- // ZSTs have no identity, so we don't need to move them around.
99
- if !T :: IS_ZST && this. idx < this. old_len && this. del > 0 {
100
- let ptr = this. vec . as_mut_ptr ( ) ;
101
- let src = ptr. add ( this. idx ) ;
102
- let dst = src. sub ( this. del ) ;
103
- let tail_len = this. old_len - this. idx ;
104
- src. copy_to ( dst, tail_len) ;
105
- }
106
-
107
- let new_len = this. old_len - this. del ;
108
- this. vec . set_len ( new_len) ;
109
- }
110
- }
111
58
}
112
59
113
60
#[ unstable( feature = "drain_filter" , reason = "recently added" , issue = "43244" ) ]
@@ -154,44 +101,21 @@ where
154
101
F : FnMut ( & mut T ) -> bool ,
155
102
{
156
103
fn drop ( & mut self ) {
157
- struct BackshiftOnDrop < ' a , ' b , T , F , A : Allocator >
158
- where
159
- F : FnMut ( & mut T ) -> bool ,
160
- {
161
- drain : & ' b mut DrainFilter < ' a , T , F , A > ,
162
- }
163
-
164
- impl < ' a , ' b , T , F , A : Allocator > Drop for BackshiftOnDrop < ' a , ' b , T , F , A >
165
- where
166
- F : FnMut ( & mut T ) -> bool ,
167
- {
168
- fn drop ( & mut self ) {
169
- unsafe {
170
- if self . drain . idx < self . drain . old_len && self . drain . del > 0 {
171
- // This is a pretty messed up state, and there isn't really an
172
- // obviously right thing to do. We don't want to keep trying
173
- // to execute `pred`, so we just backshift all the unprocessed
174
- // elements and tell the vec that they still exist. The backshift
175
- // is required to prevent a double-drop of the last successfully
176
- // drained item prior to a panic in the predicate.
177
- let ptr = self . drain . vec . as_mut_ptr ( ) ;
178
- let src = ptr. add ( self . drain . idx ) ;
179
- let dst = src. sub ( self . drain . del ) ;
180
- let tail_len = self . drain . old_len - self . drain . idx ;
181
- src. copy_to ( dst, tail_len) ;
182
- }
183
- self . drain . vec . set_len ( self . drain . old_len - self . drain . del ) ;
184
- }
104
+ unsafe {
105
+ if self . idx < self . old_len && self . del > 0 {
106
+ // This is a pretty messed up state, and there isn't really an
107
+ // obviously right thing to do. We don't want to keep trying
108
+ // to execute `pred`, so we just backshift all the unprocessed
109
+ // elements and tell the vec that they still exist. The backshift
110
+ // is required to prevent a double-drop of the last successfully
111
+ // drained item prior to a panic in the predicate.
112
+ let ptr = self . vec . as_mut_ptr ( ) ;
113
+ let src = ptr. add ( self . idx ) ;
114
+ let dst = src. sub ( self . del ) ;
115
+ let tail_len = self . old_len - self . idx ;
116
+ src. copy_to ( dst, tail_len) ;
185
117
}
186
- }
187
-
188
- let backshift = BackshiftOnDrop { drain : self } ;
189
-
190
- // Attempt to consume any remaining elements if the filter predicate
191
- // has not yet panicked. We'll backshift any remaining elements
192
- // whether we've already panicked or if the consumption here panics.
193
- if !backshift. drain . panic_flag {
194
- backshift. drain . for_each ( drop) ;
118
+ self . vec . set_len ( self . old_len - self . del ) ;
195
119
}
196
120
}
197
121
}
0 commit comments