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}