lender/sources/
windows_mut.rs

1use crate::{Lend, Lender, Lending};
2
3/// Create a new lender that returns mutable contiguous overlapping windows of fixed size over a slice.
4///
5/// This is the mutable, lending variant of [`windows`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.windows).
6/// The const generic equivalent is [`array_windows_mut`].
7///
8/// Note that the [`WindowsMutExt`] trait provides a convenient entry point for this function
9/// as a method on slices and arrays.
10///
11/// # Examples
12/// ```rust
13/// # use lender::prelude::*;
14/// let mut s = [0, 1, 2, 3];
15/// let mut lender = lender::windows_mut(&mut s, 2);
16/// assert_eq!(lender.next(), Some(&mut [0, 1][..]));
17///
18/// // Using the extension trait
19/// let mut lender = s.windows_mut(2);
20/// assert_eq!(lender.next(), Some(&mut [0, 1][..]));
21/// ```
22pub fn windows_mut<T>(slice: &mut [T], size: usize) -> WindowsMut<'_, T> {
23    WindowsMut { slice, size, curr_pos: 0 }
24}
25
26/// This struct is returned by [`windows_mut`].
27pub struct WindowsMut<'a, T> {
28    pub(crate) slice: &'a mut [T],
29    pub(crate) size: usize,
30    pub(crate) curr_pos: usize,
31}
32
33impl<'any, T> Lending<'any> for WindowsMut<'_, T> {
34    type Lend = &'any mut [T];
35}
36
37impl<T> Lender for WindowsMut<'_, T> {
38    fn next(&mut self) -> Option<Lend<'_, Self>> {
39        // See https://github.com/danielhenrymantilla/lending-iterator.rs/blob/5353b5e6ce8be9d07d0cfd86e23e481377074780/src/lending_iterator/constructors/windows_mut_.rs
40        let window = self.slice.get_mut(self.curr_pos..)?.get_mut(..self.size)?;
41        self.curr_pos += 1;
42        Some(window)
43    }
44}
45
46/// Create a new lender that returns mutable overlapping array windows of fixed size over a slice.
47///
48/// This is the mutable, lending variant of [`array_windows`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.windows).
49/// The non-const generic equivalent is [`windows_mut`].
50///
51/// Note that the [`WindowsMutExt`] trait provides a convenient entry point for this function
52/// as a method on slices and arrays.
53///
54/// See [`array_windows`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.array_windows) for more information.
55/// # Examples
56/// ```rust
57/// # use lender::prelude::*;
58/// let mut s = [0, 1, 2, 3];
59/// let mut lender = lender::array_windows_mut::<_, 2>(&mut s);
60/// assert_eq!(lender.next(), Some(&mut [0, 1]));
61///
62/// // Using the extension trait
63/// let mut lender = s.array_windows_mut::<2>();
64/// assert_eq!(lender.next(), Some(&mut [0, 1]));
65/// ```
66pub fn array_windows_mut<T, const WINDOW_SIZE: usize>(slice: &mut [T]) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
67    ArrayWindowsMut { slice, curr_pos: 0 }
68}
69
70/// This struct is returned by [`array_windows_mut`].
71pub struct ArrayWindowsMut<'a, T, const WINDOW_SIZE: usize> {
72    pub(crate) slice: &'a mut [T],
73    pub(crate) curr_pos: usize,
74}
75
76impl<'any, T, const WINDOW_SIZE: usize> Lending<'any> for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
77    type Lend = &'any mut [T; WINDOW_SIZE];
78}
79
80impl<T, const WINDOW_SIZE: usize> Lender for ArrayWindowsMut<'_, T, WINDOW_SIZE> {
81    fn next(&mut self) -> Option<Lend<'_, Self>> {
82        // See https://github.com/danielhenrymantilla/lending-iterator.rs/blob/5353b5e6ce8be9d07d0cfd86e23e481377074780/src/lending_iterator/constructors/windows_mut_.rs
83        let window = self.slice.get_mut(self.curr_pos..)?.get_mut(..WINDOW_SIZE)?;
84        self.curr_pos += 1;
85        Some(window.try_into().unwrap())
86    }
87}
88
89/// Extension trait adding to slices and arrays the methods [`windows_mut`](WindowsMutExt::windows_mut)
90/// and [`array_windows_mut`](WindowsMutExt::array_windows_mut).
91pub trait WindowsMutExt<T> {
92    fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T>;
93    fn array_windows_mut<const WINDOW_SIZE: usize>(&mut self) -> ArrayWindowsMut<'_, T, WINDOW_SIZE>;
94}
95
96impl<T> WindowsMutExt<T> for [T] {
97    /// This method is a convenient entry point for [`windows_mut`](crate::windows_mut).
98    fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T> {
99        windows_mut(self, size)
100    }
101    /// This method is a convenient entry point for [`array_windows_mut`](crate::array_windows_mut).
102    fn array_windows_mut<const WINDOW_SIZE: usize>(&mut self) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
103        array_windows_mut(self)
104    }
105}
106
107impl<T, const N: usize> WindowsMutExt<T> for [T; N] {
108    /// This method is a convenient entry point for [`windows_mut`](crate::windows_mut).
109    fn windows_mut(&mut self, size: usize) -> WindowsMut<'_, T> {
110        windows_mut(self, size)
111    }
112    /// This method is a convenient entry point for [`array_windows_mut`](crate::array_windows_mut).
113    fn array_windows_mut<const WINDOW_SIZE: usize>(&mut self) -> ArrayWindowsMut<'_, T, WINDOW_SIZE> {
114        array_windows_mut(self)
115    }
116}
117
118#[cfg(test)]
119#[test]
120fn test_array_windows_mut() {
121    let mut s = [0, 1, 2, 3];
122    let mut lender = array_windows_mut::<_, 2>(&mut s);
123    assert_eq!(lender.next(), Some(&mut [0, 1]));
124    assert_eq!(lender.next(), Some(&mut [1, 2]));
125    assert_eq!(lender.next(), Some(&mut [2, 3]));
126    assert_eq!(lender.next(), None);
127}
128
129#[test]
130fn test_windows_mut() {
131    let mut s = [0, 1, 2, 3];
132    let mut lender = windows_mut(&mut s, 2);
133    assert_eq!(lender.next(), Some(&mut [0, 1][..]));
134    assert_eq!(lender.next(), Some(&mut [1, 2][..]));
135    assert_eq!(lender.next(), Some(&mut [2, 3][..]));
136    assert_eq!(lender.next(), None);
137}