1use core::{fmt, num::NonZero};
2
3use crate::{DoubleEndedLender, ExactSizeLender, FusedLender, Lend, Lender, Lending};
4
5#[inline]
31pub fn windows_mut<T>(slice: &mut [T], size: usize) -> WindowsMut<'_, T> {
32 let size = NonZero::new(size).expect("window size must be non-zero");
33 WindowsMut {
34 slice,
35 size,
36 position: WindowPosition::Init,
37 }
38}
39
40#[must_use = "lenders are lazy and do nothing unless consumed"]
44pub struct WindowsMut<'a, T> {
45 slice: &'a mut [T],
46 size: NonZero<usize>,
47 position: WindowPosition,
48}
49
50impl<T: fmt::Debug> fmt::Debug for WindowsMut<'_, T> {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 f.debug_struct("WindowsMut")
53 .field("slice", &self.slice)
54 .field("size", &self.size)
55 .finish_non_exhaustive()
56 }
57}
58
59#[derive(Clone, Copy)]
61enum WindowPosition {
62 Init,
63 Front,
64 Back,
65}
66
67impl WindowPosition {
68 #[inline]
70 fn update_slice<T>(self, slice: &mut &mut [T]) {
71 match self {
72 WindowPosition::Init => {}
73 WindowPosition::Front => {
74 if let [_, tail @ ..] = core::mem::take(slice) {
76 *slice = tail;
77 }
78 }
79 WindowPosition::Back => {
80 if let [init @ .., _] = core::mem::take(slice) {
82 *slice = init;
83 }
84 }
85 }
86 }
87}
88
89impl<'any, T> Lending<'any> for WindowsMut<'_, T> {
90 type Lend = &'any mut [T];
91}
92
93impl<T> Lender for WindowsMut<'_, T> {
94 crate::check_covariance!();
95 #[inline]
96 fn next(&mut self) -> Option<Lend<'_, Self>> {
97 self.position.update_slice(&mut self.slice);
98 self.position = WindowPosition::Front;
99 self.slice.get_mut(..self.size.get())
100 }
101
102 #[inline(always)]
103 fn size_hint(&self) -> (usize, Option<usize>) {
104 let len = self.len();
105 (len, Some(len))
106 }
107}
108
109impl<T> DoubleEndedLender for WindowsMut<'_, T> {
110 #[inline]
111 fn next_back(&mut self) -> Option<Lend<'_, Self>> {
112 self.position.update_slice(&mut self.slice);
113 self.position = WindowPosition::Back;
114 let index = self.slice.len().checked_sub(self.size.get())?;
115 self.slice.get_mut(index..)
116 }
117}
118
119impl<T> ExactSizeLender for WindowsMut<'_, T> {
120 #[inline]
121 fn len(&self) -> usize {
122 let base = self.slice.len().saturating_sub(self.size.get() - 1);
123 match self.position {
127 WindowPosition::Init => base,
128 WindowPosition::Front | WindowPosition::Back => base.saturating_sub(1),
129 }
130 }
131}
132
133impl<T> FusedLender for WindowsMut<'_, T> {}
134
135#[inline]
167pub fn array_windows_mut<T, const WINDOW_SIZE: usize>(
168 slice: &mut [T],
169) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
170 assert!(WINDOW_SIZE != 0, "window size must be non-zero");
171 ArrayWindowsMut {
172 slice,
173 position: WindowPosition::Init,
174 }
175}
176
177#[must_use = "lenders are lazy and do nothing unless consumed"]
183pub struct ArrayWindowsMut<'a, T, const WINDOW_SIZE: usize> {
184 slice: &'a mut [T],
185 position: WindowPosition,
186}
187
188impl<T: fmt::Debug, const WINDOW_SIZE: usize> fmt::Debug for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_struct("ArrayWindowsMut")
191 .field("slice", &self.slice)
192 .finish_non_exhaustive()
193 }
194}
195
196impl<'any, T, const WINDOW_SIZE: usize> Lending<'any> for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
197 type Lend = &'any mut [T; WINDOW_SIZE];
198}
199
200impl<T, const WINDOW_SIZE: usize> Lender for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
201 crate::check_covariance!();
202 #[inline]
203 fn next(&mut self) -> Option<Lend<'_, Self>> {
204 self.position.update_slice(&mut self.slice);
205 self.position = WindowPosition::Front;
206 self.slice.first_chunk_mut()
207 }
208
209 #[inline(always)]
210 fn size_hint(&self) -> (usize, Option<usize>) {
211 let len = self.len();
212 (len, Some(len))
213 }
214}
215
216impl<T, const WINDOW_SIZE: usize> DoubleEndedLender for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
217 #[inline]
218 fn next_back(&mut self) -> Option<Lend<'_, Self>> {
219 self.position.update_slice(&mut self.slice);
220 self.position = WindowPosition::Back;
221 self.slice.last_chunk_mut()
222 }
223}
224
225impl<T, const WINDOW_SIZE: usize> ExactSizeLender for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
226 #[inline]
227 fn len(&self) -> usize {
228 let base = self.slice.len().saturating_sub(WINDOW_SIZE - 1);
229 match self.position {
233 WindowPosition::Init => base,
234 WindowPosition::Front | WindowPosition::Back => base.saturating_sub(1),
235 }
236 }
237}
238
239impl<T, const WINDOW_SIZE: usize> FusedLender for ArrayWindowsMut<'_, T, WINDOW_SIZE> {}
240
241pub trait WindowsMutExt<T> {
245 fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T>;
253 fn array_windows_mut<const WINDOW_SIZE: usize>(
262 &mut self,
263 ) -> ArrayWindowsMut<'_, T, WINDOW_SIZE>;
264}
265
266impl<T> WindowsMutExt<T> for [T] {
267 #[inline(always)]
273 fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T> {
274 windows_mut(self, size)
275 }
276 #[inline(always)]
282 fn array_windows_mut<const WINDOW_SIZE: usize>(
283 &mut self,
284 ) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
285 array_windows_mut(self)
286 }
287}
288
289impl<T, const N: usize> WindowsMutExt<T> for [T; N] {
290 #[inline(always)]
296 fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T> {
297 windows_mut(self, size)
298 }
299 #[inline(always)]
305 fn array_windows_mut<const WINDOW_SIZE: usize>(
306 &mut self,
307 ) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
308 array_windows_mut(self)
309 }
310}
311
312#[test]
313fn test_array_windows_mut() {
314 let mut s = [0, 1, 2, 3];
315 let mut lender = array_windows_mut::<_, 2>(&mut s);
316 assert_eq!(lender.next(), Some(&mut [0, 1]));
317 assert_eq!(lender.next(), Some(&mut [1, 2]));
318 assert_eq!(lender.next(), Some(&mut [2, 3]));
319 assert_eq!(lender.next(), None);
320}
321
322#[test]
323fn test_array_windows_mut_rev() {
324 let mut s = [0, 1, 2, 3];
325 let mut lender = array_windows_mut::<_, 2>(&mut s).rev();
326 assert_eq!(lender.next(), Some(&mut [2, 3]));
327 assert_eq!(lender.next(), Some(&mut [1, 2]));
328 assert_eq!(lender.next(), Some(&mut [0, 1]));
329 assert_eq!(lender.next(), None);
330}
331
332#[test]
333fn test_array_windows_mut_mixed() {
334 let mut s = [0, 1, 2, 3, 4];
335 let mut lender = array_windows_mut::<_, 2>(&mut s);
336 assert_eq!(lender.next_back(), Some(&mut [3, 4]));
337 assert_eq!(lender.next(), Some(&mut [0, 1]));
338 assert_eq!(lender.next_back(), Some(&mut [2, 3]));
339 assert_eq!(lender.next(), Some(&mut [1, 2]));
340 assert_eq!(lender.next_back(), None);
341 assert_eq!(lender.next(), None);
342}
343
344#[test]
345fn test_windows_mut() {
346 let mut s = [0, 1, 2, 3];
347 let mut lender = windows_mut(&mut s, 2);
348 assert_eq!(lender.next(), Some(&mut [0, 1][..]));
349 assert_eq!(lender.next(), Some(&mut [1, 2][..]));
350 assert_eq!(lender.next(), Some(&mut [2, 3][..]));
351 assert_eq!(lender.next(), None);
352}
353
354#[test]
355fn test_windows_mut_rev() {
356 let mut s = [0, 1, 2, 3];
357 let mut lender = windows_mut(&mut s, 2).rev();
358 assert_eq!(lender.next(), Some(&mut [2, 3][..]));
359 assert_eq!(lender.next(), Some(&mut [1, 2][..]));
360 assert_eq!(lender.next(), Some(&mut [0, 1][..]));
361 assert_eq!(lender.next(), None);
362}
363
364#[test]
365fn test_windows_mut_back() {
366 let mut s = [0, 1, 2, 3, 4];
367 let mut lender = windows_mut(&mut s, 2);
368 assert_eq!(lender.next_back(), Some(&mut [3, 4][..]));
369 assert_eq!(lender.next(), Some(&mut [0, 1][..]));
370 assert_eq!(lender.next_back(), Some(&mut [2, 3][..]));
371 assert_eq!(lender.next(), Some(&mut [1, 2][..]));
372 assert_eq!(lender.next_back(), None);
373 assert_eq!(lender.next(), None);
374}
375
376#[test]
377fn test_windows_mut_exact_size() {
378 use crate::ExactSizeLender;
379
380 let mut s = [0, 1, 2, 3, 4];
381 let mut lender = windows_mut(&mut s, 2);
382 assert_eq!(lender.len(), 4);
383 lender.next();
384 assert_eq!(lender.len(), 3);
385 lender.next();
386 assert_eq!(lender.len(), 2);
387 lender.next();
388 assert_eq!(lender.len(), 1);
389 lender.next();
390 assert_eq!(lender.len(), 0);
391 lender.next(); assert_eq!(lender.len(), 0);
393
394 let mut empty: [i32; 0] = [];
396 assert_eq!(windows_mut(&mut empty, 2).len(), 0);
397
398 let mut single = [1];
399 assert_eq!(windows_mut(&mut single, 2).len(), 0);
400 assert_eq!(windows_mut(&mut single, 1).len(), 1);
401}
402
403#[test]
404#[should_panic(expected = "window size must be non-zero")]
405fn test_windows_mut_zero_size_panics() {
406 let mut arr = [1, 2, 3];
407 let _ = windows_mut(&mut arr, 0);
408}
409
410#[test]
411fn test_array_windows_mut_exact_size() {
412 use crate::ExactSizeLender;
413
414 let mut s = [0, 1, 2, 3, 4];
415 let mut lender = array_windows_mut::<_, 2>(&mut s);
416 assert_eq!(lender.len(), 4);
417 lender.next();
418 assert_eq!(lender.len(), 3);
419 lender.next();
420 assert_eq!(lender.len(), 2);
421
422 let mut single = [1];
424 assert_eq!(array_windows_mut::<_, 2>(&mut single).len(), 0);
425 assert_eq!(array_windows_mut::<_, 1>(&mut single).len(), 1);
426}
427
428#[test]
429fn test_windows_mut_exact_size_mixed() {
430 use crate::ExactSizeLender;
431
432 let mut s = [0, 1, 2, 3, 4];
433 let mut lender = windows_mut(&mut s, 2);
434 assert_eq!(lender.len(), 4);
435 lender.next_back();
436 assert_eq!(lender.len(), 3);
437 lender.next();
438 assert_eq!(lender.len(), 2);
439 lender.next_back();
440 assert_eq!(lender.len(), 1);
441 lender.next();
442 assert_eq!(lender.len(), 0);
443}