Fri, 14 Feb 2025 23:31:24 -0500
slice_assume_init_mut deprecation workaround
5 | 1 | /*! |
2 | Utilities for mapping over various container types. | |
3 | */ | |
0 | 4 | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
5 | use itertools::izip; |
55
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
6 | #[cfg(feature = "nightly")] |
0 | 7 | use std::mem::MaybeUninit; |
8 | ||
5 | 9 | /// Trait for a fixed-length container type. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
10 | /// |
5 | 11 | /// Implemented by [`Loc`][crate::loc::Loc] vectors, [`Cube`][crate::sets::Cube]s, |
12 | /// and basic arrays. | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
13 | pub trait FixedLength<const N: usize> { |
5 | 14 | /// Type of elements of the container. |
0 | 15 | type Elem; |
5 | 16 | /// Type of iterators over the elements of the container. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
17 | type Iter: Iterator<Item = Self::Elem>; |
5 | 18 | |
19 | /// Returns an iteartor over the elements of the container. | |
0 | 20 | fn fl_iter(self) -> Self::Iter; |
21 | } | |
22 | ||
5 | 23 | /// Trait for a mutable fixed-length container type. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
24 | pub trait FixedLengthMut<const N: usize>: FixedLength<N> { |
5 | 25 | /// Type of iterators over references to mutable elements of the container. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
26 | type IterMut<'a>: Iterator<Item = &'a mut Self::Elem> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
27 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
28 | Self: 'a; |
5 | 29 | |
30 | /// Returns an iterator over mutable references to elements of the container. | |
0 | 31 | fn fl_iter_mut(&mut self) -> Self::IterMut<'_>; |
32 | } | |
33 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
34 | impl<A, const N: usize> FixedLength<N> for [A; N] { |
0 | 35 | type Elem = A; |
36 | type Iter = std::array::IntoIter<A, N>; | |
37 | #[inline] | |
38 | fn fl_iter(self) -> Self::Iter { | |
39 | self.into_iter() | |
40 | } | |
41 | } | |
42 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
43 | impl<A, const N: usize> FixedLengthMut<N> for [A; N] { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
44 | type IterMut<'a> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
45 | = std::slice::IterMut<'a, A> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
46 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
47 | A: 'a; |
0 | 48 | #[inline] |
49 | fn fl_iter_mut(&mut self) -> Self::IterMut<'_> { | |
50 | self.iter_mut() | |
51 | } | |
52 | } | |
53 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
54 | impl<'a, A, const N: usize> FixedLength<N> for &'a [A; N] { |
0 | 55 | type Elem = &'a A; |
56 | type Iter = std::slice::Iter<'a, A>; | |
57 | #[inline] | |
58 | fn fl_iter(self) -> Self::Iter { | |
59 | self.iter() | |
60 | } | |
61 | } | |
62 | ||
63 | macro_rules! tuple_or_singleton { | |
64 | ($a:ident,) => { $a }; | |
65 | ($($a:ident),+) => { ($($a),+) } | |
66 | } | |
67 | ||
68 | macro_rules! make_mapmany { | |
69 | ($name:ident, $name_indexed:ident, $var0:ident $($var:ident)* ; | |
70 | $etype0:ident $($etype:ident)*, $ctype0:ident $($ctype:ident)*) => { | |
5 | 71 | /// Map over [`FixedLength`] container(s), returning an array. |
0 | 72 | #[inline] |
73 | pub fn $name< | |
74 | $etype0, | |
75 | $($etype,)* | |
76 | $ctype0 : FixedLength<N,Elem=$etype0>, | |
77 | $($ctype : FixedLength<N,Elem=$etype>,)* | |
78 | Res, | |
79 | const N : usize | |
80 | >( | |
81 | $var0 : $ctype0, | |
82 | $($var : $ctype,)* | |
83 | f : impl Fn($etype0, $($etype),*) -> Res | |
84 | ) -> [Res; N] { | |
85 | let zipit = izip!($var0.fl_iter(), $($var.fl_iter()),*); | |
86 | let map = zipit.map(|tuple_or_singleton!($var0, $($var),*)| f($var0, $($var),*)); | |
87 | collect_into_array_unchecked(map) | |
88 | } | |
89 | ||
5 | 90 | /// Map over [`FixedLength`] containers(s) and element indices, returning an array. |
0 | 91 | #[inline] |
92 | pub fn $name_indexed< | |
93 | $etype0, | |
94 | $($etype,)* | |
95 | $ctype0 : FixedLength<N,Elem=$etype0>, | |
96 | $($ctype : FixedLength<N,Elem=$etype>,)* | |
97 | Res, | |
98 | const N : usize | |
99 | >( | |
100 | $var0 : $ctype0, | |
101 | $($var : $ctype,)* | |
102 | f : impl Fn(usize, $etype0, $($etype),*) -> Res | |
103 | ) -> [Res; N] { | |
104 | let zipit = (0..N).zip(izip!($var0.fl_iter(), $($var.fl_iter()),*)); | |
105 | let map = zipit.map(|(i, tuple_or_singleton!($var0, $($var),*))| f(i, $var0, $($var),*)); | |
106 | collect_into_array_unchecked(map) | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | make_mapmany!(map1, map1_indexed, a; A, CA); | |
112 | make_mapmany!(map2, map2_indexed, a b; A B, CA CB); | |
113 | make_mapmany!(map3, map3_indexed, a b c; A B C, CA CB CC); | |
114 | make_mapmany!(map4, map4_indexed, a b c d; A B C D, CA CB CC CD); | |
115 | make_mapmany!(map5, map5_indexed, a b c d e; A B C D E, CA CB CC CD CE); | |
116 | make_mapmany!(map6, map6_indexed, a b c d e f; A B C D E F, CA CB CC CD CE CF); | |
117 | ||
118 | macro_rules! make_mapmany_mut{ | |
119 | ($name:ident, $name_indexed:ident, $var0:ident $($var:ident)* ; | |
120 | $etype0:ident $($etype:ident)*, $ctype0:ident $($ctype:ident)*) => { | |
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
121 | /// Map over [`FixedLength`] container(s) with mutable references to the first container. |
0 | 122 | #[inline] |
123 | pub fn $name< | |
124 | $etype0, | |
125 | $($etype,)* | |
126 | $ctype0 : FixedLengthMut<N,Elem=$etype0>, | |
127 | $($ctype : FixedLength<N,Elem=$etype>,)* | |
128 | const N : usize | |
129 | > ( | |
130 | $var0 : &mut $ctype0, | |
131 | $($var : $ctype,)* | |
132 | f : impl Fn(&mut $etype0, $($etype),*) | |
133 | ) { | |
134 | let zipit = izip!($var0.fl_iter_mut(), $($var.fl_iter()),*); | |
135 | zipit.for_each(|tuple_or_singleton!($var0, $($var),*)| f($var0, $($var),*)); | |
136 | } | |
137 | ||
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
138 | /// Map over [`FixedLength`] container(s) and element indices |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
139 | /// with mutable references to the first container. |
0 | 140 | #[inline] |
141 | pub fn $name_indexed< | |
142 | $etype0, | |
143 | $($etype,)* | |
144 | $ctype0 : FixedLengthMut<N,Elem=$etype0>, | |
145 | $($ctype : FixedLength<N,Elem=$etype>,)* | |
146 | const N : usize | |
147 | > ( | |
148 | $var0 : &mut $ctype0, | |
149 | $($var : $ctype,)* | |
150 | f : impl Fn(usize, &mut $etype0, $($etype),*) | |
151 | ) { | |
152 | let zipit = (0..N).zip(izip!($var0.fl_iter_mut(), $($var.fl_iter()),*)); | |
153 | zipit.for_each(|(i, tuple_or_singleton!($var0, $($var),*))| f(i, $var0, $($var),*)); | |
154 | } | |
155 | } | |
156 | } | |
157 | ||
158 | make_mapmany_mut!(map1_mut, map1_indexed_mut, a; A, CA); | |
159 | make_mapmany_mut!(map2_mut, map2_indexed_mut, a b; A B, CA CB); | |
160 | make_mapmany_mut!(map3_mut, map3_indexed_mut, a b c; A B C, CA CB CC); | |
161 | make_mapmany_mut!(map4_mut, map4_indexed_mut, a b c d; A B C D, CA CB CC CD); | |
162 | make_mapmany_mut!(map5_mut, map5_indexed_mut, a b c d e; A B C D E, CA CB CC CD CE); | |
163 | make_mapmany_mut!(map6_mut, map6_indexed_mut, a b c d e f; A B C D E F, CA CB CC CD CE CF); | |
164 | ||
165 | /// Initialise an array of length `N` by calling `f` multiple times. | |
166 | #[inline] | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
167 | pub fn array_init<A, F: Fn() -> A, const N: usize>(f: F) -> [A; N] { |
0 | 168 | //[(); N].map(|_| f()) |
169 | core::array::from_fn(|_| f()) | |
170 | } | |
171 | ||
172 | // /// Initialise an array of length `N` by calling `f` with the index of each element. | |
173 | // #[inline] | |
174 | // pub fn array_gen<A, F : Fn(usize) -> A, const N : usize>(f : F) -> [A; N] { | |
175 | // //[(); N].indexmap(|i, _| f(i)) | |
176 | // core::array::from_fn(f) | |
177 | // } | |
178 | ||
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
179 | /// Iterator returned by [`foldmap`][FoldMappable::foldmap] applied to an iterator. |
5 | 180 | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
181 | pub struct FoldMap<I: Iterator<Item = A>, A, B, J: Copy, F: Fn(J, A) -> (J, B)> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
182 | iter: I, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
183 | f: F, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
184 | j: J, |
0 | 185 | } |
186 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
187 | impl<A, B, I: Iterator<Item = A>, J: Copy, F: Fn(J, A) -> (J, B)> Iterator |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
188 | for FoldMap<I, A, B, J, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
189 | { |
0 | 190 | type Item = B; |
191 | #[inline] | |
192 | fn next(&mut self) -> Option<B> { | |
193 | self.iter.next().map(|a| { | |
194 | let (jnew, b) = (self.f)(self.j, a); | |
195 | self.j = jnew; | |
196 | b | |
197 | }) | |
198 | } | |
199 | } | |
200 | ||
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
201 | /// Iterator returned by [`indexmap`][IndexMappable::indexmap] applied to an iterator. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
202 | pub struct IndexMap<I: Iterator<Item = A>, A, B, F: Fn(usize, A) -> B> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
203 | iter: I, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
204 | f: F, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
205 | j: usize, |
0 | 206 | } |
207 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
208 | impl<A, B, I: Iterator<Item = A>, F: Fn(usize, A) -> B> Iterator for IndexMap<I, A, B, F> { |
0 | 209 | type Item = B; |
210 | #[inline] | |
211 | fn next(&mut self) -> Option<B> { | |
212 | self.iter.next().map(|a| { | |
213 | let b = (self.f)(self.j, a); | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
214 | self.j = self.j + 1; |
0 | 215 | b |
216 | }) | |
217 | } | |
218 | } | |
219 | ||
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
220 | /// Trait for things that can be foldmapped. |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
221 | /// |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
222 | /// `A` is the type of elements of `Self`, and `J` the accumulator type for the folding. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
223 | pub trait FoldMappable<A, J>: Sized { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
224 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
225 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
226 | F: Fn(J, A) -> (J, B); |
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
227 | /// Fold and map over `self` with `f`. `j` is the initial accumulator for folding. |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
228 | /// |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
229 | /// The output type depends on the implementation, but will generally have elements of |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
230 | /// type `B`. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
231 | fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F>; |
0 | 232 | } |
233 | ||
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
234 | /// Trait for things that can be indexmapped. |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
235 | /// |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
236 | /// `A` is the type of elements of `Self`. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
237 | pub trait IndexMappable<A>: Sized { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
238 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
239 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
240 | F: Fn(usize, A) -> B; |
2
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
241 | /// Map over element indices and elements of `self`. |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
242 | /// |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
243 | /// The output type depends on the implementation, but will generally have elements of |
ac84e995e119
Convert iteration utilities to GATs
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
244 | /// type `B`. |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
245 | fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F>; |
0 | 246 | } |
247 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
248 | impl<'a, A, J: Copy> FoldMappable<&'a A, J> for std::slice::Iter<'a, A> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
249 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
250 | = FoldMap<Self, &'a A, B, J, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
251 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
252 | F: Fn(J, &'a A) -> (J, B); |
0 | 253 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
254 | fn foldmap<B, F: Fn(J, &'a A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
255 | FoldMap { iter: self, j, f } |
0 | 256 | } |
257 | } | |
258 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
259 | impl<'a, A> IndexMappable<&'a A> for std::slice::Iter<'a, A> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
260 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
261 | = IndexMap<Self, &'a A, B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
262 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
263 | F: Fn(usize, &'a A) -> B; |
0 | 264 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
265 | fn indexmap<B, F: Fn(usize, &'a A) -> B>(self, f: F) -> Self::Output<B, F> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
266 | IndexMap { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
267 | iter: self, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
268 | j: 0, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
269 | f, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
270 | } |
0 | 271 | } |
272 | } | |
273 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
274 | impl<A, J: Copy, const N: usize> FoldMappable<A, J> for std::array::IntoIter<A, N> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
275 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
276 | = FoldMap<Self, A, B, J, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
277 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
278 | F: Fn(J, A) -> (J, B); |
0 | 279 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
280 | fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> Self::Output<B, F> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
281 | FoldMap { iter: self, j, f } |
0 | 282 | } |
283 | } | |
284 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
285 | impl<'a, A, const N: usize> IndexMappable<A> for std::array::IntoIter<A, N> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
286 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
287 | = IndexMap<Self, A, B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
288 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
289 | F: Fn(usize, A) -> B; |
0 | 290 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
291 | fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> Self::Output<B, F> { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
292 | IndexMap { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
293 | iter: self, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
294 | j: 0, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
295 | f, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
296 | } |
0 | 297 | } |
298 | } | |
299 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
300 | impl<A, J: Copy, const N: usize> FoldMappable<A, J> for [A; N] { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
301 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
302 | = [B; N] |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
303 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
304 | F: Fn(J, A) -> (J, B); |
0 | 305 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
306 | fn foldmap<B, F: Fn(J, A) -> (J, B)>(self, j: J, f: F) -> [B; N] { |
0 | 307 | // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; |
308 | // let mut res = MaybeUninit::uninit_array::<N>(); | |
309 | // for (a, i) in self.into_iter().zip(0..N) { | |
310 | // let (jnew, b) = f(j, a); | |
311 | // unsafe { *(res.get_unchecked_mut(i)) = MaybeUninit::new(b) }; | |
312 | // j = jnew; | |
313 | // } | |
314 | // //unsafe { res.as_mut_ptr().cast::<[B; N]>().read() } | |
315 | // unsafe { MaybeUninit::array_assume_init(res) } | |
316 | let it = self.into_iter().foldmap(j, f); | |
317 | collect_into_array_unchecked(it) | |
318 | } | |
319 | } | |
320 | ||
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
321 | impl<A, const N: usize> IndexMappable<A> for [A; N] { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
322 | type Output<B, F> |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
323 | = [B; N] |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
324 | where |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
325 | F: Fn(usize, A) -> B; |
0 | 326 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
327 | fn indexmap<B, F: Fn(usize, A) -> B>(self, f: F) -> [B; N] { |
0 | 328 | // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; |
329 | // let mut res = MaybeUninit::uninit_array::<N>(); | |
330 | // for (a, i) in self.into_iter().zip(0..N) { | |
331 | // let b = f(i, a); | |
332 | // unsafe { *(res.get_unchecked_mut(i)) = MaybeUninit::new(b) }; | |
333 | // } | |
334 | // //unsafe { res.as_mut_ptr().cast::<[B; N]>().read() } | |
335 | // unsafe { MaybeUninit::array_assume_init(res) } | |
336 | let it = self.into_iter().indexmap(f); | |
337 | collect_into_array_unchecked(it) | |
338 | } | |
339 | } | |
340 | ||
341 | /// This is taken and simplified from core::array to not involve `ControlFlow`, | |
342 | /// `Try` etc. (Pulling everything including `NeverShortCircuit` turned out | |
343 | /// too much to maintain here.) | |
344 | /// | |
345 | /// Pulls `N` items from `iter` and returns them as an array. If the iterator | |
346 | /// yields fewer than `N` items, `None` is returned and all already yielded | |
347 | /// items are dropped. | |
348 | /// | |
349 | /// Since the iterator is passed as a mutable reference and this function calls | |
350 | /// `next` at most `N` times, the iterator can still be used afterwards to | |
351 | /// retrieve the remaining items. | |
352 | /// | |
353 | /// If `iter.next()` panicks, all items already yielded by the iterator are | |
354 | /// dropped. | |
55
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
355 | #[cfg(feature = "nightly")] |
0 | 356 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
357 | pub(crate) fn collect_into_array_unchecked<T, I: Iterator<Item = T>, const N: usize>( |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
358 | mut iter: I, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
359 | ) -> [T; N] { |
0 | 360 | if N == 0 { |
361 | // SAFETY: An empty array is always inhabited and has no validity invariants. | |
362 | return unsafe { core::mem::zeroed() }; | |
363 | } | |
364 | ||
365 | struct Guard<'a, T, const N: usize> { | |
366 | array_mut: &'a mut [MaybeUninit<T>; N], | |
367 | initialized: usize, | |
368 | } | |
369 | ||
370 | impl<T, const N: usize> Drop for Guard<'_, T, N> { | |
371 | #[inline] | |
372 | fn drop(&mut self) { | |
373 | debug_assert!(self.initialized <= N); | |
374 | ||
375 | // SAFETY: this slice will contain only initialized objects. | |
376 | unsafe { | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
377 | for elem in self.array_mut.get_unchecked_mut(..self.initialized) { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
378 | elem.assume_init_drop(); |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
379 | } |
0 | 380 | } |
381 | } | |
382 | } | |
383 | ||
384 | let mut array = MaybeUninit::uninit_array::<N>(); | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
385 | let mut guard = Guard { |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
386 | array_mut: &mut array, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
387 | initialized: 0, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
388 | }; |
0 | 389 | |
390 | while let Some(item) = iter.next() { | |
391 | // SAFETY: `guard.initialized` starts at 0, is increased by one in the | |
392 | // loop and the loop is aborted once it reaches N (which is | |
393 | // `array.len()`). | |
394 | unsafe { | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
395 | guard |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
396 | .array_mut |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
397 | .get_unchecked_mut(guard.initialized) |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
398 | .write(item); |
0 | 399 | } |
400 | guard.initialized += 1; | |
401 | ||
402 | // Check if the whole array was initialized. | |
403 | if guard.initialized == N { | |
404 | core::mem::forget(guard); | |
405 | ||
406 | // SAFETY: the condition above asserts that all elements are | |
407 | // initialized. | |
408 | let out = unsafe { MaybeUninit::array_assume_init(array) }; | |
409 | return out; | |
410 | } | |
411 | } | |
412 | ||
413 | unreachable!("Something went wrong with iterator length") | |
414 | } | |
415 | ||
55
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
416 | #[cfg(not(feature = "nightly"))] |
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
417 | #[inline] |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
418 | pub(crate) fn collect_into_array_unchecked<T, I: Iterator<Item = T>, const N: usize>( |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
419 | iter: I, |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
420 | ) -> [T; N] { |
55
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
421 | match iter.collect::<Vec<T>>().try_into() { |
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
422 | Ok(a) => a, |
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
423 | Err(_) => panic!("collect_into_array failure: should not happen"), |
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
424 | } |
7b2ee3e84c5f
Add "nightly" feature and provide alternative low-performance implementations of several things when not available.
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
425 | } |
0 | 426 | |
427 | #[cfg(test)] | |
428 | mod tests { | |
429 | use super::*; | |
430 | ||
431 | #[test] | |
432 | fn mapx_test() { | |
91
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
433 | let a = [0, 1, 2]; |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
434 | let mut b = [2, 1, 0]; |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
435 | assert_eq!(map1(a, |x| x + 1), [1, 2, 3]); |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
436 | assert_eq!(map2(a, b, |x, y| x + y), [2, 2, 2]); |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
437 | assert_eq!(map1_indexed(a, |i, y| y - i), [0, 0, 0]); |
db870f2a2cde
slice_assume_init_mut deprecation workaround
Tuomo Valkonen <tuomov@iki.fi>
parents:
55
diff
changeset
|
438 | map1_indexed_mut(&mut b, |i, y| *y = i); |
0 | 439 | assert_eq!(b, a); |
440 | } | |
441 | } |