fj_interop/
ext.rs

1//! Extension traits for standard library types
2
3/// Extension trait for arrays
4pub trait ArrayExt<T, const N: usize> {
5    /// Stable replacement for `each_ref`
6    ///
7    /// <https://doc.rust-lang.org/std/primitive.array.html#method.each_ref>
8    fn each_ref_ext(&self) -> [&T; N];
9
10    /// Stable replacement for `each_mut`
11    ///
12    /// <https://doc.rust-lang.org/std/primitive.array.html#method.each_mut>
13    fn each_mut_ext(&mut self) -> [&mut T; N];
14
15    /// Stable replacement for `try_map`
16    ///
17    /// <https://doc.rust-lang.org/std/primitive.array.html#method.try_map>
18    fn try_map_ext<F, U, E>(self, f: F) -> Result<[U; N], E>
19    where
20        F: FnMut(T) -> Result<U, E>;
21
22    /// Stable replacement for `zip`
23    ///
24    /// <https://doc.rust-lang.org/std/primitive.array.html#method.zip>
25    fn zip_ext<U>(self, rhs: [U; N]) -> [(T, U); N];
26}
27
28impl<T> ArrayExt<T, 2> for [T; 2] {
29    fn each_ref_ext(&self) -> [&T; 2] {
30        let [a, b] = self;
31        [a, b]
32    }
33
34    fn each_mut_ext(&mut self) -> [&mut T; 2] {
35        let [a, b] = self;
36        [a, b]
37    }
38
39    fn try_map_ext<F, U, E>(self, f: F) -> Result<[U; 2], E>
40    where
41        F: FnMut(T) -> Result<U, E>,
42    {
43        let [a, b] = self.map(f);
44        Ok([a?, b?])
45    }
46
47    fn zip_ext<U>(self, rhs: [U; 2]) -> [(T, U); 2] {
48        let [a, b] = self;
49        let [q, r] = rhs;
50        [(a, q), (b, r)]
51    }
52}
53
54impl<T> ArrayExt<T, 3> for [T; 3] {
55    fn each_ref_ext(&self) -> [&T; 3] {
56        let [a, b, c] = self;
57        [a, b, c]
58    }
59
60    fn each_mut_ext(&mut self) -> [&mut T; 3] {
61        let [a, b, c] = self;
62        [a, b, c]
63    }
64
65    fn try_map_ext<F, U, E>(self, f: F) -> Result<[U; 3], E>
66    where
67        F: FnMut(T) -> Result<U, E>,
68    {
69        let [a, b, c] = self.map(f);
70        Ok([a?, b?, c?])
71    }
72
73    fn zip_ext<U>(self, rhs: [U; 3]) -> [(T, U); 3] {
74        let [a, b, c] = self;
75        let [q, r, s] = rhs;
76        [(a, q), (b, r), (c, s)]
77    }
78}
79
80impl<T> ArrayExt<T, 4> for [T; 4] {
81    fn each_ref_ext(&self) -> [&T; 4] {
82        let [a, b, c, d] = self;
83        [a, b, c, d]
84    }
85
86    fn each_mut_ext(&mut self) -> [&mut T; 4] {
87        let [a, b, c, d] = self;
88        [a, b, c, d]
89    }
90
91    fn try_map_ext<F, U, E>(self, f: F) -> Result<[U; 4], E>
92    where
93        F: FnMut(T) -> Result<U, E>,
94    {
95        let [a, b, c, d] = self.map(f);
96        Ok([a?, b?, c?, d?])
97    }
98
99    fn zip_ext<U>(self, rhs: [U; 4]) -> [(T, U); 4] {
100        let [a, b, c, d] = self;
101        let [q, r, s, t] = rhs;
102        [(a, q), (b, r), (c, s), (d, t)]
103    }
104}
105
106/// Extension trait for arrays
107pub trait SliceExt<T> {
108    /// Stable replacement for `array_chunks`
109    ///
110    /// <https://doc.rust-lang.org/std/primitive.slice.html#method.array_chunks>
111    fn array_chunks_ext<const N: usize>(&self) -> ArrayChunks<T, N>;
112
113    /// Stable replacement for `array_windows`
114    ///
115    /// <https://doc.rust-lang.org/std/primitive.slice.html#method.array_windows>
116    fn array_windows_ext<const N: usize>(&self) -> ArrayWindows<T, N>;
117}
118
119impl<T> SliceExt<T> for &[T] {
120    fn array_chunks_ext<const N: usize>(&self) -> ArrayChunks<T, N> {
121        ArrayChunks {
122            slice: self,
123            index: 0,
124        }
125    }
126
127    fn array_windows_ext<const N: usize>(&self) -> ArrayWindows<T, N> {
128        ArrayWindows {
129            slice: self,
130            index: 0,
131        }
132    }
133}
134
135/// Returned by [`SliceExt::array_chunks_ext`]
136pub struct ArrayChunks<'a, T: 'a, const N: usize> {
137    slice: &'a [T],
138    index: usize,
139}
140
141impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> {
142    type Item = &'a [T; N];
143
144    fn next(&mut self) -> Option<Self::Item> {
145        if self.index + N > self.slice.len() {
146            return None;
147        }
148
149        let next = &self.slice[self.index..self.index + N];
150        self.index += N;
151
152        let next = next.try_into().unwrap();
153        Some(next)
154    }
155}
156
157/// Returned by [`SliceExt::array_windows_ext`]
158pub struct ArrayWindows<'a, T: 'a, const N: usize> {
159    slice: &'a [T],
160    index: usize,
161}
162
163impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
164    type Item = &'a [T; N];
165
166    fn next(&mut self) -> Option<Self::Item> {
167        if self.index + N > self.slice.len() {
168            return None;
169        }
170
171        let next = &self.slice[self.index..self.index + N];
172        self.index += 1;
173
174        let next = next.try_into().unwrap();
175        Some(next)
176    }
177}