lending_iterator/lending_iterator/constructors/windows_mut_.rs
1/// Creates an <code>impl [LendingIterator]</code> over the **sliding windows**
2/// of a slice, **with `&mut` / exclusive** access over them (yields `&mut [T]`
3/// slices).
4///
5/// This is thus "simply" the `mut` counter-part of [`windows()`],
6/// but for the `mut` playing a key role w.r.t. semantics and borrows: indeed,
7/// **the different sliding windows may overlap**! This goes against the
8/// exclusivity of `&mut` references, so **the different windows cannot
9/// coƫxist!**
10///
11/// This is something that the traditional [`Iterator`] trait cannot express,
12/// thence this [`LendingIterator`] definition which can.
13///
14/// - This is a free function version of the [`.windows_mut()`] method
15/// provided by the eponymous [extension trait](https://docs.rs/extension_traits).
16///
17/// That is, feel free to check out that extension method, since in practice
18/// it's even more ergonomic to use.
19///
20/// [`windows()`]: https://doc.rust-lang.org/1.62.0/std/primitive.slice.html#method.windows
21/// [`.windows_mut()`]: trait@super::windows_mut#impl-windows_mut<T>-for-%5BT%5D
22pub
23fn windows_mut<T, const WINDOW_SIZE: usize> (
24 slice: &mut [T],
25) -> WindowsMut<&mut [T], WINDOW_SIZE>
26{
27 WindowsMut {
28 slice,
29 start: 0,
30 }
31}
32
33/// The <code>impl [LendingIterator]</code> returned by [`windows_mut()`].
34pub
35struct WindowsMut<Slice, const WINDOW_SIZE: usize> {
36 slice: Slice,
37 start: usize,
38}
39
40#[gat]
41impl<'lt, T, const WINDOW_SIZE: usize>
42 LendingIterator
43for
44 WindowsMut<&'lt mut [T], WINDOW_SIZE>
45{
46 type Item<'next>
47 where
48 Self : 'next,
49 =
50 &'next mut [T; WINDOW_SIZE]
51 ;
52
53 fn next (
54 self: &'_ mut WindowsMut<&'lt mut [T], WINDOW_SIZE>,
55 ) -> Option<&'_ mut [T; WINDOW_SIZE]>
56 {
57 self.nth(0)
58 }
59
60 #[inline]
61 fn nth (
62 self: &'_ mut WindowsMut<&'lt mut [T], WINDOW_SIZE>,
63 n: usize,
64 ) -> Option<&'_ mut [T; WINDOW_SIZE]>
65 {
66 let new_start = self.start.checked_add(n)?;
67 let slice =
68 self.slice
69 .get_mut(new_start ..)?
70 .get_mut(.. WINDOW_SIZE)?
71 ;
72 self.start = new_start + 1;
73 Some(slice.try_into().unwrap())
74 }
75}