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