1use alloc::vec::Vec;
2use core as std;
3
4#[derive(Debug)]
60pub struct Remover<'a, T> {
61 vec: &'a mut Vec<T>,
73 unfiltered_start: usize,
74 unfiltered_end: usize,
75}
76
77impl<'a, T> Remover<'a, T> {
78 #[inline]
80 pub fn new(vec: &'a mut Vec<T>) -> Remover<'a, T> {
81 let unfiltered_end = vec.len();
82
83 unsafe {
84 vec.set_len(0);
85 }
86
87 Remover {
88 vec,
89 unfiltered_start: 0,
90 unfiltered_end,
91 }
92 }
93
94 #[inline]
96 pub fn index(&self) -> usize {
97 self.unfiltered_start
98 }
99
100 #[inline]
103 pub fn current(&self) -> Option<&T> {
104 if self.unfiltered_start < self.unfiltered_end {
105 unsafe { Some(&*self.vec.as_ptr().add(self.unfiltered_start)) }
106 } else {
107 None
108 }
109 }
110
111 #[inline]
114 pub fn current_mut(&mut self) -> Option<&mut T> {
115 if self.unfiltered_start < self.unfiltered_end {
116 unsafe { Some(&mut *self.vec.as_mut_ptr().add(self.unfiltered_start)) }
117 } else {
118 None
119 }
120 }
121
122 #[inline]
127 pub fn as_slices(&self) -> (&[T], &[T]) {
128 unsafe {
129 (
130 &self.vec[..],
131 std::slice::from_raw_parts(
132 self.vec.as_ptr().add(self.unfiltered_start),
133 self.unfiltered_end - self.unfiltered_start,
134 ),
135 )
136 }
137 }
138
139 #[inline]
145 pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
146 unsafe {
147 (
148 std::slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.vec.len()),
149 std::slice::from_raw_parts_mut(
150 self.vec.as_mut_ptr().add(self.unfiltered_start),
151 self.unfiltered_end - self.unfiltered_start,
152 ),
153 )
154 }
155 }
156
157 #[inline]
163 pub fn move_to(&mut self, index: usize) {
164 assert!(index <= self.unfiltered_end, "Index out of bounds");
165
166 let copy_len = index
167 .checked_sub(self.unfiltered_start)
168 .expect("Index must be larger than previous index");
169
170 unsafe {
171 let ptr = self.vec.as_mut_ptr();
172
173 ptr.add(self.unfiltered_start)
174 .copy_to(ptr.add(self.vec.len()), copy_len);
175
176 self.vec.set_len(self.vec.len() + copy_len);
177 self.unfiltered_start = index;
178 }
179 }
180
181 #[inline]
189 pub fn remove(&mut self) -> T {
190 assert!(
191 self.unfiltered_start < self.unfiltered_end,
192 "Removing out of bounds"
193 );
194
195 unsafe {
196 let item = self.vec.as_mut_ptr().add(self.unfiltered_start).read();
197 self.unfiltered_start += 1;
198 item
199 }
200 }
201}
202
203impl<'a, T> Drop for Remover<'a, T> {
204 #[inline]
205 fn drop(&mut self) {
206 let ptr = self.vec.as_mut_ptr();
207 let unfiltered_len = self.unfiltered_end - self.unfiltered_start;
208
209 unsafe {
210 ptr.add(self.unfiltered_start)
211 .copy_to(ptr.add(self.vec.len()), unfiltered_len);
212
213 self.vec.set_len(self.vec.len() + unfiltered_len)
214 }
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::Remover;
221 use crate::proputils::prop_eq;
222 use alloc::{format, vec};
223 use proptest::prelude::*;
224 use std::fmt::Debug;
225 use std::vec::Vec;
226
227 #[test]
228 fn remover_empty() {
229 let mut items: Vec<usize> = Vec::new();
230 Remover::new(&mut items);
231 assert_eq!(items, vec![]);
232 }
233
234 #[test]
235 fn remover_single() {
236 let mut items = vec![1];
237 assert_eq!(Remover::new(&mut items).remove(), 1);
238 assert_eq!(items, vec![]);
239 }
240
241 #[test]
242 fn remover_two_first() {
243 let mut items = vec![1, 2];
244 assert_eq!(Remover::new(&mut items).remove(), 1);
245 assert_eq!(items, vec![2]);
246 }
247
248 #[test]
249 fn remover_two_second() {
250 let mut items = vec![1, 2];
251 let mut rem = Remover::new(&mut items);
252 rem.move_to(1);
253 assert_eq!(rem.remove(), 2);
254 drop(rem);
255 assert_eq!(items, vec![1]);
256 }
257
258 #[test]
259 fn remover_two_both() {
260 let mut items = vec![1, 2];
261 let mut rem = Remover::new(&mut items);
262 rem.move_to(0);
263 assert_eq!(rem.remove(), 1);
264 rem.move_to(1);
265 assert_eq!(rem.remove(), 2);
266 drop(rem);
267 assert_eq!(items, vec![]);
268 }
269
270 #[test]
271 #[should_panic]
272 fn remover_two_out_of_order() {
273 let mut items = vec![1, 2];
274 let mut remover = Remover::new(&mut items);
275 remover.move_to(1);
276 assert_eq!(remover.remove(), 2);
277 remover.move_to(0)
278 }
279
280 #[test]
281 #[should_panic]
282 fn remover_out_of_bounds() {
283 drop(Remover::new(&mut vec![1, 2]).move_to(3));
284 }
285
286 #[test]
287 #[should_panic]
288 fn remover_advance_out_of_bounds() {
289 Remover::new(&mut vec![1, 2]).move_to(4);
290 }
291
292 #[test]
293 fn remover_advance_one_past() {
294 let mut items = vec![1, 2];
295 let mut rem = Remover::new(&mut items);
296 rem.move_to(2);
297 assert_eq!(rem.index(), 2);
298 }
299
300 #[test]
301 fn remover_slices() {
302 let mut items = vec![1, 2, 3, 4];
303 let mut rem = Remover::new(&mut items);
304 rem.move_to(2);
305 assert_eq!(rem.remove(), 3);
306 assert_eq!(rem.as_slices(), (&[1, 2][..], &[4][..]));
307 assert_eq!(rem.as_mut_slices(), (&mut [1, 2][..], &mut [4][..]));
308 }
309
310 #[test]
311 fn remover_index() {
312 let mut items = vec![1, 2, 3, 4];
313 let mut remover = Remover::new(&mut items);
314 assert_eq!(remover.index(), 0);
315 remover.move_to(1);
316 assert_eq!(remover.remove(), 2);
317 assert_eq!(remover.index(), 2);
318 remover.move_to(3);
319 assert_eq!(remover.index(), 3);
320 }
321
322 struct NaiveRemover<'a, T> {
323 vec: &'a mut Vec<T>,
324 old_index: usize,
325 new_index: usize,
326 }
327
328 impl<'a, T> NaiveRemover<'a, T> {
329 fn new(vec: &mut Vec<T>) -> NaiveRemover<T> {
330 NaiveRemover {
331 vec,
332 old_index: 0,
333 new_index: 0,
334 }
335 }
336
337 fn index(&self) -> usize {
338 self.old_index
339 }
340
341 fn current(&self) -> Option<&T> {
342 self.vec.get(self.new_index)
343 }
344
345 fn remove(&mut self) -> T {
346 let item = self.vec.remove(self.new_index);
347 self.old_index += 1;
348 item
349 }
350
351 fn move_to(&mut self, index: usize) {
352 self.new_index += index.checked_sub(self.old_index).unwrap();
353 self.old_index = index;
354 }
355
356 fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
357 self.vec.split_at_mut(self.new_index)
358 }
359
360 fn as_slices(&self) -> (&[T], &[T]) {
361 self.vec.split_at(self.new_index)
362 }
363 }
364
365 #[derive(Debug, Clone)]
366 enum Op {
367 MoveTo(usize),
368 Remove,
369 }
370
371 fn prop_strategy() -> impl Strategy<Value = (Vec<u8>, Vec<Op>)> {
372 proptest::collection::vec(any::<u8>(), 0..100).prop_flat_map(|base| {
373 proptest::collection::vec(
374 prop_oneof![(0..base.len() + 1).prop_map(Op::MoveTo), Just(Op::Remove)],
375 0..100,
376 )
377 .prop_map(move |ops| (base.clone(), ops))
378 })
379 }
380
381 fn check_equals_naive_remover<T: Eq + Clone + Debug>(
382 base: Vec<T>,
383 ops: &[Op],
384 ) -> Result<(), TestCaseError> {
385 let mut model_vec = base.clone();
386 let mut model = NaiveRemover::new(&mut model_vec);
387 let mut tested_vec = base;
388 let mut tested = Remover::new(&mut tested_vec);
389
390 ops.iter().try_for_each(|op| {
391 match op {
392 &Op::MoveTo(index) => {
393 prop_eq(|| model.move_to(index), || tested.move_to(index))
394 }
395 Op::Remove => prop_eq(|| model.remove(), || tested.remove()),
396 }?;
397
398 prop_assert_eq!(model.current(), tested.current());
399 prop_assert_eq!(model.index(), tested.index());
400 prop_assert_eq!(model.as_slices(), tested.as_slices());
401 prop_assert_eq!(model.as_mut_slices(), tested.as_mut_slices());
402
403 Ok(())
404 })?;
405
406 drop(tested);
407 prop_assert_eq!(model_vec, tested_vec);
408
409 Ok(())
410 }
411
412 proptest! {
413 #[test]
414 fn equals_naive_remover((base, ops) in prop_strategy()) {
415 check_equals_naive_remover(base, &ops[..])?
416 }
417 }
418}