• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::iter::{FusedIterator, TrustedLen};
2 use core::num::NonZeroUsize;
3 use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
4 
5 use crate::alloc::{Allocator, Global};
6 
7 use super::VecDeque;
8 
9 /// An owning iterator over the elements of a `VecDeque`.
10 ///
11 /// This `struct` is created by the [`into_iter`] method on [`VecDeque`]
12 /// (provided by the [`IntoIterator`] trait). See its documentation for more.
13 ///
14 /// [`into_iter`]: VecDeque::into_iter
15 #[derive(Clone)]
16 #[stable(feature = "rust1", since = "1.0.0")]
17 pub struct IntoIter<
18     T,
19     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
20 > {
21     inner: VecDeque<T, A>,
22 }
23 
24 impl<T, A: Allocator> IntoIter<T, A> {
new(inner: VecDeque<T, A>) -> Self25     pub(super) fn new(inner: VecDeque<T, A>) -> Self {
26         IntoIter { inner }
27     }
28 
into_vecdeque(self) -> VecDeque<T, A>29     pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
30         self.inner
31     }
32 }
33 
34 #[stable(feature = "collection_debug", since = "1.17.0")]
35 impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result36     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37         f.debug_tuple("IntoIter").field(&self.inner).finish()
38     }
39 }
40 
41 #[stable(feature = "rust1", since = "1.0.0")]
42 impl<T, A: Allocator> Iterator for IntoIter<T, A> {
43     type Item = T;
44 
45     #[inline]
next(&mut self) -> Option<T>46     fn next(&mut self) -> Option<T> {
47         self.inner.pop_front()
48     }
49 
50     #[inline]
size_hint(&self) -> (usize, Option<usize>)51     fn size_hint(&self) -> (usize, Option<usize>) {
52         let len = self.inner.len();
53         (len, Some(len))
54     }
55 
56     #[inline]
advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>57     fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
58         let len = self.inner.len;
59         let rem = if len < n {
60             self.inner.clear();
61             n - len
62         } else {
63             self.inner.drain(..n);
64             0
65         };
66         NonZeroUsize::new(rem).map_or(Ok(()), Err)
67     }
68 
69     #[inline]
count(self) -> usize70     fn count(self) -> usize {
71         self.inner.len
72     }
73 
try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, R: Try<Output = B>,74     fn try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
75     where
76         F: FnMut(B, Self::Item) -> R,
77         R: Try<Output = B>,
78     {
79         struct Guard<'a, T, A: Allocator> {
80             deque: &'a mut VecDeque<T, A>,
81             // `consumed <= deque.len` always holds.
82             consumed: usize,
83         }
84 
85         impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
86             fn drop(&mut self) {
87                 self.deque.len -= self.consumed;
88                 self.deque.head = self.deque.to_physical_idx(self.consumed);
89             }
90         }
91 
92         let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
93 
94         let (head, tail) = guard.deque.as_slices();
95 
96         init = head
97             .iter()
98             .map(|elem| {
99                 guard.consumed += 1;
100                 // SAFETY: Because we incremented `guard.consumed`, the
101                 // deque effectively forgot the element, so we can take
102                 // ownership
103                 unsafe { ptr::read(elem) }
104             })
105             .try_fold(init, &mut f)?;
106 
107         tail.iter()
108             .map(|elem| {
109                 guard.consumed += 1;
110                 // SAFETY: Same as above.
111                 unsafe { ptr::read(elem) }
112             })
113             .try_fold(init, &mut f)
114     }
115 
116     #[inline]
fold<B, F>(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,117     fn fold<B, F>(mut self, init: B, mut f: F) -> B
118     where
119         F: FnMut(B, Self::Item) -> B,
120     {
121         match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
122             Ok(b) => b,
123             Err(e) => match e {},
124         }
125     }
126 
127     #[inline]
last(mut self) -> Option<Self::Item>128     fn last(mut self) -> Option<Self::Item> {
129         self.inner.pop_back()
130     }
131 
next_chunk<const N: usize>( &mut self, ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>132     fn next_chunk<const N: usize>(
133         &mut self,
134     ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
135         let mut raw_arr = MaybeUninit::uninit_array();
136         let raw_arr_ptr = raw_arr.as_mut_ptr().cast();
137         let (head, tail) = self.inner.as_slices();
138 
139         if head.len() >= N {
140             // SAFETY: By manually adjusting the head and length of the deque, we effectively
141             // make it forget the first `N` elements, so taking ownership of them is safe.
142             unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) };
143             self.inner.head = self.inner.to_physical_idx(N);
144             self.inner.len -= N;
145             // SAFETY: We initialized the entire array with items from `head`
146             return Ok(unsafe { raw_arr.transpose().assume_init() });
147         }
148 
149         // SAFETY: Same argument as above.
150         unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) };
151         let remaining = N - head.len();
152 
153         if tail.len() >= remaining {
154             // SAFETY: Same argument as above.
155             unsafe {
156                 ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining)
157             };
158             self.inner.head = self.inner.to_physical_idx(N);
159             self.inner.len -= N;
160             // SAFETY: We initialized the entire array with items from `head` and `tail`
161             Ok(unsafe { raw_arr.transpose().assume_init() })
162         } else {
163             // SAFETY: Same argument as above.
164             unsafe {
165                 ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len())
166             };
167             let init = head.len() + tail.len();
168             // We completely drained all the deques elements.
169             self.inner.head = 0;
170             self.inner.len = 0;
171             // SAFETY: We copied all elements from both slices to the beginning of the array, so
172             // the given range is initialized.
173             Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) })
174         }
175     }
176 }
177 
178 #[stable(feature = "rust1", since = "1.0.0")]
179 impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
180     #[inline]
next_back(&mut self) -> Option<T>181     fn next_back(&mut self) -> Option<T> {
182         self.inner.pop_back()
183     }
184 
185     #[inline]
advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>186     fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
187         let len = self.inner.len;
188         let rem = if len < n {
189             self.inner.clear();
190             n - len
191         } else {
192             self.inner.truncate(len - n);
193             0
194         };
195         NonZeroUsize::new(rem).map_or(Ok(()), Err)
196     }
197 
try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R where F: FnMut(B, Self::Item) -> R, R: Try<Output = B>,198     fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
199     where
200         F: FnMut(B, Self::Item) -> R,
201         R: Try<Output = B>,
202     {
203         struct Guard<'a, T, A: Allocator> {
204             deque: &'a mut VecDeque<T, A>,
205             // `consumed <= deque.len` always holds.
206             consumed: usize,
207         }
208 
209         impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
210             fn drop(&mut self) {
211                 self.deque.len -= self.consumed;
212             }
213         }
214 
215         let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
216 
217         let (head, tail) = guard.deque.as_slices();
218 
219         init = tail
220             .iter()
221             .map(|elem| {
222                 guard.consumed += 1;
223                 // SAFETY: See `try_fold`'s safety comment.
224                 unsafe { ptr::read(elem) }
225             })
226             .try_rfold(init, &mut f)?;
227 
228         head.iter()
229             .map(|elem| {
230                 guard.consumed += 1;
231                 // SAFETY: Same as above.
232                 unsafe { ptr::read(elem) }
233             })
234             .try_rfold(init, &mut f)
235     }
236 
237     #[inline]
rfold<B, F>(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,238     fn rfold<B, F>(mut self, init: B, mut f: F) -> B
239     where
240         F: FnMut(B, Self::Item) -> B,
241     {
242         match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
243             Ok(b) => b,
244             Err(e) => match e {},
245         }
246     }
247 }
248 
249 #[stable(feature = "rust1", since = "1.0.0")]
250 impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
251     #[inline]
is_empty(&self) -> bool252     fn is_empty(&self) -> bool {
253         self.inner.is_empty()
254     }
255 }
256 
257 #[stable(feature = "fused", since = "1.26.0")]
258 impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {}
259 
260 #[unstable(feature = "trusted_len", issue = "37572")]
261 unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {}
262