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}