162306a36Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 OR MIT 262306a36Sopenharmony_ci 362306a36Sopenharmony_ciuse crate::alloc::{Allocator, Global}; 462306a36Sopenharmony_ciuse core::ptr; 562306a36Sopenharmony_ciuse core::slice; 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciuse super::Vec; 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/// An iterator which uses a closure to determine if an element should be removed. 1062306a36Sopenharmony_ci/// 1162306a36Sopenharmony_ci/// This struct is created by [`Vec::extract_if`]. 1262306a36Sopenharmony_ci/// See its documentation for more. 1362306a36Sopenharmony_ci/// 1462306a36Sopenharmony_ci/// # Example 1562306a36Sopenharmony_ci/// 1662306a36Sopenharmony_ci/// ``` 1762306a36Sopenharmony_ci/// #![feature(extract_if)] 1862306a36Sopenharmony_ci/// 1962306a36Sopenharmony_ci/// let mut v = vec![0, 1, 2]; 2062306a36Sopenharmony_ci/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0); 2162306a36Sopenharmony_ci/// ``` 2262306a36Sopenharmony_ci#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] 2362306a36Sopenharmony_ci#[derive(Debug)] 2462306a36Sopenharmony_ci#[must_use = "iterators are lazy and do nothing unless consumed"] 2562306a36Sopenharmony_cipub struct ExtractIf< 2662306a36Sopenharmony_ci 'a, 2762306a36Sopenharmony_ci T, 2862306a36Sopenharmony_ci F, 2962306a36Sopenharmony_ci #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, 3062306a36Sopenharmony_ci> where 3162306a36Sopenharmony_ci F: FnMut(&mut T) -> bool, 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci pub(super) vec: &'a mut Vec<T, A>, 3462306a36Sopenharmony_ci /// The index of the item that will be inspected by the next call to `next`. 3562306a36Sopenharmony_ci pub(super) idx: usize, 3662306a36Sopenharmony_ci /// The number of items that have been drained (removed) thus far. 3762306a36Sopenharmony_ci pub(super) del: usize, 3862306a36Sopenharmony_ci /// The original length of `vec` prior to draining. 3962306a36Sopenharmony_ci pub(super) old_len: usize, 4062306a36Sopenharmony_ci /// The filter test predicate. 4162306a36Sopenharmony_ci pub(super) pred: F, 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciimpl<T, F, A: Allocator> ExtractIf<'_, T, F, A> 4562306a36Sopenharmony_ciwhere 4662306a36Sopenharmony_ci F: FnMut(&mut T) -> bool, 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci /// Returns a reference to the underlying allocator. 4962306a36Sopenharmony_ci #[unstable(feature = "allocator_api", issue = "32838")] 5062306a36Sopenharmony_ci #[inline] 5162306a36Sopenharmony_ci pub fn allocator(&self) -> &A { 5262306a36Sopenharmony_ci self.vec.allocator() 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] 5762306a36Sopenharmony_ciimpl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A> 5862306a36Sopenharmony_ciwhere 5962306a36Sopenharmony_ci F: FnMut(&mut T) -> bool, 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci type Item = T; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci fn next(&mut self) -> Option<T> { 6462306a36Sopenharmony_ci unsafe { 6562306a36Sopenharmony_ci while self.idx < self.old_len { 6662306a36Sopenharmony_ci let i = self.idx; 6762306a36Sopenharmony_ci let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); 6862306a36Sopenharmony_ci let drained = (self.pred)(&mut v[i]); 6962306a36Sopenharmony_ci // Update the index *after* the predicate is called. If the index 7062306a36Sopenharmony_ci // is updated prior and the predicate panics, the element at this 7162306a36Sopenharmony_ci // index would be leaked. 7262306a36Sopenharmony_ci self.idx += 1; 7362306a36Sopenharmony_ci if drained { 7462306a36Sopenharmony_ci self.del += 1; 7562306a36Sopenharmony_ci return Some(ptr::read(&v[i])); 7662306a36Sopenharmony_ci } else if self.del > 0 { 7762306a36Sopenharmony_ci let del = self.del; 7862306a36Sopenharmony_ci let src: *const T = &v[i]; 7962306a36Sopenharmony_ci let dst: *mut T = &mut v[i - del]; 8062306a36Sopenharmony_ci ptr::copy_nonoverlapping(src, dst, 1); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci None 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci fn size_hint(&self) -> (usize, Option<usize>) { 8862306a36Sopenharmony_ci (0, Some(self.old_len - self.idx)) 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] 9362306a36Sopenharmony_ciimpl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A> 9462306a36Sopenharmony_ciwhere 9562306a36Sopenharmony_ci F: FnMut(&mut T) -> bool, 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci fn drop(&mut self) { 9862306a36Sopenharmony_ci unsafe { 9962306a36Sopenharmony_ci if self.idx < self.old_len && self.del > 0 { 10062306a36Sopenharmony_ci // This is a pretty messed up state, and there isn't really an 10162306a36Sopenharmony_ci // obviously right thing to do. We don't want to keep trying 10262306a36Sopenharmony_ci // to execute `pred`, so we just backshift all the unprocessed 10362306a36Sopenharmony_ci // elements and tell the vec that they still exist. The backshift 10462306a36Sopenharmony_ci // is required to prevent a double-drop of the last successfully 10562306a36Sopenharmony_ci // drained item prior to a panic in the predicate. 10662306a36Sopenharmony_ci let ptr = self.vec.as_mut_ptr(); 10762306a36Sopenharmony_ci let src = ptr.add(self.idx); 10862306a36Sopenharmony_ci let dst = src.sub(self.del); 10962306a36Sopenharmony_ci let tail_len = self.old_len - self.idx; 11062306a36Sopenharmony_ci src.copy_to(dst, tail_len); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci self.vec.set_len(self.old_len - self.del); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci} 116