1use crate::iter::FusedIterator;
2use crate::mem::{MaybeUninit, SizedTypeProperties};
3use crate::{fmt, ptr};
4
5#[must_use = "iterators are lazy and do nothing unless consumed"]
10#[unstable(feature = "iter_map_windows", issue = "87155")]
11pub struct MapWindows<I: Iterator, F, const N: usize> {
12 f: F,
13 inner: MapWindowsInner<I, N>,
14}
15
16struct MapWindowsInner<I: Iterator, const N: usize> {
17 iter: I,
18 buffer: Option<Buffer<I::Item, N>>,
31}
32
33struct Buffer<T, const N: usize> {
38 buffer: [[MaybeUninit<T>; N]; 2],
42 start: usize,
43}
44
45impl<I: Iterator, F, const N: usize> MapWindows<I, F, N> {
46 pub(in crate::iter) const fn new(iter: I, f: F) -> Self {
47 assert!(N != 0, "array in `Iterator::map_windows` must contain more than 0 elements");
48
49 if I::Item::IS_ZST {
51 assert!(
52 N.checked_mul(2).is_some(),
53 "array size of `Iterator::map_windows` is too large"
54 );
55 }
56
57 Self { inner: MapWindowsInner::new(iter), f }
58 }
59}
60
61impl<I: Iterator, const N: usize> MapWindowsInner<I, N> {
62 #[inline]
63 const fn new(iter: I) -> Self {
64 Self { iter, buffer: None }
65 }
66
67 fn next_window(&mut self) -> Option<&[I::Item; N]> {
68 match self.buffer {
69 None => self.buffer = Buffer::try_from_iter(&mut self.iter),
72 Some(ref mut buffer) => match self.iter.next() {
73 None => {
74 self.buffer.take();
75 }
76 Some(item) => buffer.push(item),
80 },
81 }
82 self.buffer.as_ref().map(Buffer::as_array_ref)
83 }
84
85 fn size_hint(&self) -> (usize, Option<usize>) {
86 let (lo, hi) = self.iter.size_hint();
87 if self.buffer.is_some() {
88 (lo, hi)
91 } else {
92 (lo.saturating_sub(N - 1), hi.map(|hi| hi.saturating_sub(N - 1)))
96 }
97 }
98}
99
100impl<T, const N: usize> Buffer<T, N> {
101 fn try_from_iter(iter: &mut impl Iterator<Item = T>) -> Option<Self> {
102 let first_half = crate::array::iter_next_chunk(iter).ok()?;
103 let buffer =
104 [MaybeUninit::new(first_half).transpose(), [const { MaybeUninit::uninit() }; N]];
105 Some(Self { buffer, start: 0 })
106 }
107
108 #[inline]
109 fn buffer_ptr(&self) -> *const MaybeUninit<T> {
110 self.buffer.as_ptr().cast()
111 }
112
113 #[inline]
114 fn buffer_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
115 self.buffer.as_mut_ptr().cast()
116 }
117
118 #[inline]
119 fn as_array_ref(&self) -> &[T; N] {
120 debug_assert!(self.start + N <= 2 * N);
121
122 unsafe { &*self.buffer_ptr().add(self.start).cast() }
124 }
125
126 #[inline]
127 fn as_uninit_array_mut(&mut self) -> &mut MaybeUninit<[T; N]> {
128 debug_assert!(self.start + N <= 2 * N);
129
130 unsafe { &mut *self.buffer_mut_ptr().add(self.start).cast() }
132 }
133
134 fn push(&mut self, next: T) {
139 let buffer_mut_ptr = self.buffer_mut_ptr();
140 debug_assert!(self.start + N <= 2 * N);
141
142 let to_drop = if self.start == N {
143 let to_drop = unsafe {
161 ptr::copy_nonoverlapping(buffer_mut_ptr.add(self.start + 1), buffer_mut_ptr, N - 1);
162 (*buffer_mut_ptr.add(N - 1)).write(next);
163 buffer_mut_ptr.add(self.start)
164 };
165 self.start = 0;
166 to_drop
167 } else {
168 let to_drop = unsafe {
182 (*buffer_mut_ptr.add(self.start + N)).write(next);
183 buffer_mut_ptr.add(self.start)
184 };
185 self.start += 1;
186 to_drop
187 };
188
189 unsafe { ptr::drop_in_place(to_drop.cast_init()) };
192 }
193}
194
195impl<T: Clone, const N: usize> Clone for Buffer<T, N> {
196 fn clone(&self) -> Self {
197 let mut buffer = Buffer {
198 buffer: [[const { MaybeUninit::uninit() }; N], [const { MaybeUninit::uninit() }; N]],
199 start: self.start,
200 };
201 buffer.as_uninit_array_mut().write(self.as_array_ref().clone());
202 buffer
203 }
204}
205
206impl<I, const N: usize> Clone for MapWindowsInner<I, N>
207where
208 I: Iterator + Clone,
209 I::Item: Clone,
210{
211 fn clone(&self) -> Self {
212 Self { iter: self.iter.clone(), buffer: self.buffer.clone() }
213 }
214}
215
216impl<T, const N: usize> Drop for Buffer<T, N> {
217 fn drop(&mut self) {
218 unsafe {
221 let initialized_part: *mut [T] =
222 self.buffer_mut_ptr().add(self.start).cast::<T>().cast_slice(N);
223 ptr::drop_in_place(initialized_part);
224 }
225 }
226}
227
228#[unstable(feature = "iter_map_windows", issue = "87155")]
229impl<I, F, R, const N: usize> Iterator for MapWindows<I, F, N>
230where
231 I: Iterator,
232 F: FnMut(&[I::Item; N]) -> R,
233{
234 type Item = R;
235
236 fn next(&mut self) -> Option<Self::Item> {
237 let window = self.inner.next_window()?;
238 let out = (self.f)(window);
239 Some(out)
240 }
241
242 fn size_hint(&self) -> (usize, Option<usize>) {
243 self.inner.size_hint()
244 }
245}
246
247#[unstable(feature = "iter_map_windows", issue = "87155")]
248impl<I, F, R, const N: usize> FusedIterator for MapWindows<I, F, N>
249where
250 I: FusedIterator,
251 F: FnMut(&[I::Item; N]) -> R,
252{
253}
254
255#[unstable(feature = "iter_map_windows", issue = "87155")]
256impl<I, F, R, const N: usize> ExactSizeIterator for MapWindows<I, F, N>
257where
258 I: ExactSizeIterator,
259 F: FnMut(&[I::Item; N]) -> R,
260{
261}
262
263#[unstable(feature = "iter_map_windows", issue = "87155")]
264impl<I: Iterator + fmt::Debug, F, const N: usize> fmt::Debug for MapWindows<I, F, N> {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 f.debug_struct("MapWindows").field("iter", &self.inner.iter).finish()
267 }
268}
269
270#[unstable(feature = "iter_map_windows", issue = "87155")]
271impl<I, F, const N: usize> Clone for MapWindows<I, F, N>
272where
273 I: Iterator + Clone,
274 F: Clone,
275 I::Item: Clone,
276{
277 fn clone(&self) -> Self {
278 Self { f: self.f.clone(), inner: self.inner.clone() }
279 }
280}