use core::iter::{FusedIterator, TrustedLen}; use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr}; use crate::alloc::{Allocator, Global}; use super::VecDeque; /// An owning iterator over the elements of a `VecDeque`. /// /// This `struct` is created by the [`into_iter`] method on [`VecDeque`] /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: VecDeque::into_iter /// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { inner: VecDeque, } impl IntoIter { pub(super) fn new(inner: VecDeque) -> Self { IntoIter { inner } } pub(super) fn into_vecdeque(self) -> VecDeque { self.inner } } #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.inner).finish() } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = T; #[inline] fn next(&mut self) -> Option { self.inner.pop_front() } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.inner.len(); (len, Some(len)) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), usize> { if self.inner.len < n { let len = self.inner.len; self.inner.clear(); Err(len) } else { self.inner.drain(..n); Ok(()) } } #[inline] fn count(self) -> usize { self.inner.len } fn try_fold(&mut self, mut init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, R: Try, { struct Guard<'a, T, A: Allocator> { deque: &'a mut VecDeque, // `consumed <= deque.len` always holds. consumed: usize, } impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { fn drop(&mut self) { self.deque.len -= self.consumed; self.deque.head = self.deque.to_physical_idx(self.consumed); } } let mut guard = Guard { deque: &mut self.inner, consumed: 0 }; let (head, tail) = guard.deque.as_slices(); init = head .iter() .map(|elem| { guard.consumed += 1; // SAFETY: Because we incremented `guard.consumed`, the // deque effectively forgot the element, so we can take // ownership unsafe { ptr::read(elem) } }) .try_fold(init, &mut f)?; tail.iter() .map(|elem| { guard.consumed += 1; // SAFETY: Same as above. unsafe { ptr::read(elem) } }) .try_fold(init, &mut f) } #[inline] fn fold(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { match self.try_fold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, Err(e) => match e {}, } } #[inline] fn last(mut self) -> Option { self.inner.pop_back() } fn next_chunk( &mut self, ) -> Result<[Self::Item; N], array::IntoIter> { let mut raw_arr = MaybeUninit::uninit_array(); let raw_arr_ptr = raw_arr.as_mut_ptr().cast(); let (head, tail) = self.inner.as_slices(); if head.len() >= N { // SAFETY: By manually adjusting the head and length of the deque, we effectively // make it forget the first `N` elements, so taking ownership of them is safe. unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) }; self.inner.head = self.inner.to_physical_idx(N); self.inner.len -= N; // SAFETY: We initialized the entire array with items from `head` return Ok(unsafe { raw_arr.transpose().assume_init() }); } // SAFETY: Same argument as above. unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) }; let remaining = N - head.len(); if tail.len() >= remaining { // SAFETY: Same argument as above. unsafe { ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining) }; self.inner.head = self.inner.to_physical_idx(N); self.inner.len -= N; // SAFETY: We initialized the entire array with items from `head` and `tail` Ok(unsafe { raw_arr.transpose().assume_init() }) } else { // SAFETY: Same argument as above. unsafe { ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len()) }; let init = head.len() + tail.len(); // We completely drained all the deques elements. self.inner.head = 0; self.inner.len = 0; // SAFETY: We copied all elements from both slices to the beginning of the array, so // the given range is initialized. Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) }) } } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.inner.pop_back() } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { let len = self.inner.len; if len >= n { self.inner.truncate(len - n); Ok(()) } else { self.inner.clear(); Err(len) } } fn try_rfold(&mut self, mut init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, R: Try, { struct Guard<'a, T, A: Allocator> { deque: &'a mut VecDeque, // `consumed <= deque.len` always holds. consumed: usize, } impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { fn drop(&mut self) { self.deque.len -= self.consumed; } } let mut guard = Guard { deque: &mut self.inner, consumed: 0 }; let (head, tail) = guard.deque.as_slices(); init = tail .iter() .map(|elem| { guard.consumed += 1; // SAFETY: See `try_fold`'s safety comment. unsafe { ptr::read(elem) } }) .try_rfold(init, &mut f)?; head.iter() .map(|elem| { guard.consumed += 1; // SAFETY: Same as above. unsafe { ptr::read(elem) } }) .try_rfold(init, &mut f) } #[inline] fn rfold(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { match self.try_rfold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, Err(e) => match e {}, } } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { #[inline] fn is_empty(&self) -> bool { self.inner.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for IntoIter {}