/rust/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/sequence.rs
Line | Count | Source |
1 | | //! Useful traits for manipulating sequences of data stored in `GenericArray`s |
2 | | |
3 | | use super::*; |
4 | | use core::ops::{Add, Sub}; |
5 | | use core::mem::MaybeUninit; |
6 | | use core::ptr; |
7 | | use typenum::operator_aliases::*; |
8 | | |
9 | | /// Defines some sequence with an associated length and iteration capabilities. |
10 | | /// |
11 | | /// This is useful for passing N-length generic arrays as generics. |
12 | | pub unsafe trait GenericSequence<T>: Sized + IntoIterator { |
13 | | /// `GenericArray` associated length |
14 | | type Length: ArrayLength<T>; |
15 | | |
16 | | /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence` |
17 | | type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>; |
18 | | |
19 | | /// Initializes a new sequence instance using the given function. |
20 | | /// |
21 | | /// If the generator function panics while initializing the sequence, |
22 | | /// any already initialized elements will be dropped. |
23 | | fn generate<F>(f: F) -> Self::Sequence |
24 | | where |
25 | | F: FnMut(usize) -> T; |
26 | | |
27 | | #[doc(hidden)] |
28 | 0 | fn inverted_zip<B, U, F>( |
29 | 0 | self, |
30 | 0 | lhs: GenericArray<B, Self::Length>, |
31 | 0 | mut f: F, |
32 | 0 | ) -> MappedSequence<GenericArray<B, Self::Length>, B, U> |
33 | 0 | where |
34 | 0 | GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length> |
35 | 0 | + MappedGenericSequence<B, U>, |
36 | 0 | Self: MappedGenericSequence<T, U>, |
37 | 0 | Self::Length: ArrayLength<B> + ArrayLength<U>, |
38 | 0 | F: FnMut(B, Self::Item) -> U, |
39 | | { |
40 | | unsafe { |
41 | 0 | let mut left = ArrayConsumer::new(lhs); |
42 | | |
43 | 0 | let (left_array_iter, left_position) = left.iter_position(); |
44 | | |
45 | 0 | FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map( |
46 | 0 | |(l, right_value)| { |
47 | 0 | let left_value = ptr::read(l); |
48 | | |
49 | 0 | *left_position += 1; |
50 | | |
51 | 0 | f(left_value, right_value) |
52 | 0 | }, |
53 | | )) |
54 | | } |
55 | 0 | } |
56 | | |
57 | | #[doc(hidden)] |
58 | 0 | fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U> |
59 | 0 | where |
60 | 0 | Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>, |
61 | 0 | Self: MappedGenericSequence<T, U>, |
62 | 0 | Self::Length: ArrayLength<B> + ArrayLength<U>, |
63 | 0 | F: FnMut(Lhs::Item, Self::Item) -> U, |
64 | | { |
65 | 0 | FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r))) |
66 | 0 | } |
67 | | } |
68 | | |
69 | | /// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item` |
70 | | /// |
71 | | /// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`, |
72 | | /// this can be useful for keeping things organized. |
73 | | pub type SequenceItem<T> = <T as IntoIterator>::Item; |
74 | | |
75 | | unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S |
76 | | where |
77 | | &'a S: IntoIterator, |
78 | | { |
79 | | type Length = S::Length; |
80 | | type Sequence = S::Sequence; |
81 | | |
82 | | #[inline] |
83 | 0 | fn generate<F>(f: F) -> Self::Sequence |
84 | 0 | where |
85 | 0 | F: FnMut(usize) -> T, |
86 | | { |
87 | 0 | S::generate(f) |
88 | 0 | } |
89 | | } |
90 | | |
91 | | unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S |
92 | | where |
93 | | &'a mut S: IntoIterator, |
94 | | { |
95 | | type Length = S::Length; |
96 | | type Sequence = S::Sequence; |
97 | | |
98 | | #[inline] |
99 | 0 | fn generate<F>(f: F) -> Self::Sequence |
100 | 0 | where |
101 | 0 | F: FnMut(usize) -> T, |
102 | | { |
103 | 0 | S::generate(f) |
104 | 0 | } |
105 | | } |
106 | | |
107 | | /// Defines any `GenericSequence` which can be lengthened or extended by appending |
108 | | /// or prepending an element to it. |
109 | | /// |
110 | | /// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back` |
111 | | pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> { |
112 | | /// `GenericSequence` that has one more element than `Self` |
113 | | type Longer: Shorten<T, Shorter = Self>; |
114 | | |
115 | | /// Returns a new array with the given element appended to the end of it. |
116 | | /// |
117 | | /// Example: |
118 | | /// |
119 | | /// ```rust |
120 | | /// # use generic_array::{arr, sequence::Lengthen}; |
121 | | /// # fn main() { |
122 | | /// let a = arr![i32; 1, 2, 3]; |
123 | | /// |
124 | | /// let b = a.append(4); |
125 | | /// |
126 | | /// assert_eq!(b, arr![i32; 1, 2, 3, 4]); |
127 | | /// # } |
128 | | /// ``` |
129 | | fn append(self, last: T) -> Self::Longer; |
130 | | |
131 | | /// Returns a new array with the given element prepended to the front of it. |
132 | | /// |
133 | | /// Example: |
134 | | /// |
135 | | /// ```rust |
136 | | /// # use generic_array::{arr, sequence::Lengthen}; |
137 | | /// # fn main() { |
138 | | /// let a = arr![i32; 1, 2, 3]; |
139 | | /// |
140 | | /// let b = a.prepend(4); |
141 | | /// |
142 | | /// assert_eq!(b, arr![i32; 4, 1, 2, 3]); |
143 | | /// # } |
144 | | /// ``` |
145 | | fn prepend(self, first: T) -> Self::Longer; |
146 | | } |
147 | | |
148 | | /// Defines a `GenericSequence` which can be shortened by removing the first or last element from it. |
149 | | /// |
150 | | /// Additionally, any shortened sequence can be lengthened by |
151 | | /// appending or prepending an element to it. |
152 | | pub unsafe trait Shorten<T>: Sized + GenericSequence<T> { |
153 | | /// `GenericSequence` that has one less element than `Self` |
154 | | type Shorter: Lengthen<T, Longer = Self>; |
155 | | |
156 | | /// Returns a new array without the last element, and the last element. |
157 | | /// |
158 | | /// Example: |
159 | | /// |
160 | | /// ```rust |
161 | | /// # use generic_array::{arr, sequence::Shorten}; |
162 | | /// # fn main() { |
163 | | /// let a = arr![i32; 1, 2, 3, 4]; |
164 | | /// |
165 | | /// let (init, last) = a.pop_back(); |
166 | | /// |
167 | | /// assert_eq!(init, arr![i32; 1, 2, 3]); |
168 | | /// assert_eq!(last, 4); |
169 | | /// # } |
170 | | /// ``` |
171 | | fn pop_back(self) -> (Self::Shorter, T); |
172 | | |
173 | | /// Returns a new array without the first element, and the first element. |
174 | | /// Example: |
175 | | /// |
176 | | /// ```rust |
177 | | /// # use generic_array::{arr, sequence::Shorten}; |
178 | | /// # fn main() { |
179 | | /// let a = arr![i32; 1, 2, 3, 4]; |
180 | | /// |
181 | | /// let (head, tail) = a.pop_front(); |
182 | | /// |
183 | | /// assert_eq!(head, 1); |
184 | | /// assert_eq!(tail, arr![i32; 2, 3, 4]); |
185 | | /// # } |
186 | | /// ``` |
187 | | fn pop_front(self) -> (T, Self::Shorter); |
188 | | } |
189 | | |
190 | | unsafe impl<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N> |
191 | | where |
192 | | N: Add<B1>, |
193 | | Add1<N>: ArrayLength<T>, |
194 | | Add1<N>: Sub<B1, Output = N>, |
195 | | Sub1<Add1<N>>: ArrayLength<T>, |
196 | | { |
197 | | type Longer = GenericArray<T, Add1<N>>; |
198 | | |
199 | 0 | fn append(self, last: T) -> Self::Longer { |
200 | 0 | let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit(); |
201 | | |
202 | | // Note this is *mut Self, so add(1) increments by the whole array |
203 | 0 | let out_ptr = longer.as_mut_ptr() as *mut Self; |
204 | | |
205 | | unsafe { |
206 | | // write self first |
207 | 0 | ptr::write(out_ptr, self); |
208 | | // increment past self, then write the last |
209 | 0 | ptr::write(out_ptr.add(1) as *mut T, last); |
210 | | |
211 | 0 | longer.assume_init() |
212 | | } |
213 | 0 | } |
214 | | |
215 | 0 | fn prepend(self, first: T) -> Self::Longer { |
216 | 0 | let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit(); |
217 | | |
218 | | // Note this is *mut T, so add(1) increments by a single T |
219 | 0 | let out_ptr = longer.as_mut_ptr() as *mut T; |
220 | | |
221 | | unsafe { |
222 | | // write the first at the start |
223 | 0 | ptr::write(out_ptr, first); |
224 | | // increment past the first, then write self |
225 | 0 | ptr::write(out_ptr.add(1) as *mut Self, self); |
226 | | |
227 | 0 | longer.assume_init() |
228 | | } |
229 | 0 | } |
230 | | } |
231 | | |
232 | | unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N> |
233 | | where |
234 | | N: Sub<B1>, |
235 | | Sub1<N>: ArrayLength<T>, |
236 | | Sub1<N>: Add<B1, Output = N>, |
237 | | Add1<Sub1<N>>: ArrayLength<T>, |
238 | | { |
239 | | type Shorter = GenericArray<T, Sub1<N>>; |
240 | | |
241 | 0 | fn pop_back(self) -> (Self::Shorter, T) { |
242 | 0 | let whole = ManuallyDrop::new(self); |
243 | | |
244 | | unsafe { |
245 | 0 | let init = ptr::read(whole.as_ptr() as _); |
246 | 0 | let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _); |
247 | | |
248 | 0 | (init, last) |
249 | | } |
250 | 0 | } |
251 | | |
252 | 0 | fn pop_front(self) -> (T, Self::Shorter) { |
253 | | // ensure this doesn't get dropped |
254 | 0 | let whole = ManuallyDrop::new(self); |
255 | | |
256 | | unsafe { |
257 | 0 | let head = ptr::read(whole.as_ptr() as _); |
258 | 0 | let tail = ptr::read(whole.as_ptr().offset(1) as _); |
259 | | |
260 | 0 | (head, tail) |
261 | | } |
262 | 0 | } |
263 | | } |
264 | | |
265 | | /// Defines a `GenericSequence` that can be split into two parts at a given pivot index. |
266 | | pub unsafe trait Split<T, K>: GenericSequence<T> |
267 | | where |
268 | | K: ArrayLength<T>, |
269 | | { |
270 | | /// First part of the resulting split array |
271 | | type First: GenericSequence<T>; |
272 | | /// Second part of the resulting split array |
273 | | type Second: GenericSequence<T>; |
274 | | |
275 | | /// Splits an array at the given index, returning the separate parts of the array. |
276 | | fn split(self) -> (Self::First, Self::Second); |
277 | | } |
278 | | |
279 | | unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N> |
280 | | where |
281 | | N: ArrayLength<T>, |
282 | | K: ArrayLength<T>, |
283 | | N: Sub<K>, |
284 | | Diff<N, K>: ArrayLength<T>, |
285 | | { |
286 | | type First = GenericArray<T, K>; |
287 | | type Second = GenericArray<T, Diff<N, K>>; |
288 | | |
289 | 0 | fn split(self) -> (Self::First, Self::Second) { |
290 | | unsafe { |
291 | | // ensure this doesn't get dropped |
292 | 0 | let whole = ManuallyDrop::new(self); |
293 | | |
294 | 0 | let head = ptr::read(whole.as_ptr() as *const _); |
295 | 0 | let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _); |
296 | | |
297 | 0 | (head, tail) |
298 | | } |
299 | 0 | } |
300 | | } |
301 | | |
302 | | unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N> |
303 | | where |
304 | | N: ArrayLength<T>, |
305 | | K: ArrayLength<T> + 'static, |
306 | | N: Sub<K>, |
307 | | Diff<N, K>: ArrayLength<T>, |
308 | | { |
309 | | type First = &'a GenericArray<T, K>; |
310 | | type Second = &'a GenericArray<T, Diff<N, K>>; |
311 | | |
312 | 0 | fn split(self) -> (Self::First, Self::Second) { |
313 | | unsafe { |
314 | 0 | let ptr_to_first: *const T = self.as_ptr(); |
315 | 0 | let head = &*(ptr_to_first as *const _); |
316 | 0 | let tail = &*(ptr_to_first.add(K::USIZE) as *const _); |
317 | 0 | (head, tail) |
318 | | } |
319 | 0 | } |
320 | | } |
321 | | |
322 | | unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N> |
323 | | where |
324 | | N: ArrayLength<T>, |
325 | | K: ArrayLength<T> + 'static, |
326 | | N: Sub<K>, |
327 | | Diff<N, K>: ArrayLength<T>, |
328 | | { |
329 | | type First = &'a mut GenericArray<T, K>; |
330 | | type Second = &'a mut GenericArray<T, Diff<N, K>>; |
331 | | |
332 | 0 | fn split(self) -> (Self::First, Self::Second) { |
333 | | unsafe { |
334 | 0 | let ptr_to_first: *mut T = self.as_mut_ptr(); |
335 | 0 | let head = &mut *(ptr_to_first as *mut _); |
336 | 0 | let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _); |
337 | 0 | (head, tail) |
338 | | } |
339 | 0 | } |
340 | | } |
341 | | |
342 | | /// Defines `GenericSequence`s which can be joined together, forming a larger array. |
343 | | pub unsafe trait Concat<T, M>: GenericSequence<T> |
344 | | where |
345 | | M: ArrayLength<T>, |
346 | | { |
347 | | /// Sequence to be concatenated with `self` |
348 | | type Rest: GenericSequence<T, Length = M>; |
349 | | |
350 | | /// Resulting sequence formed by the concatenation. |
351 | | type Output: GenericSequence<T>; |
352 | | |
353 | | /// Concatenate, or join, two sequences. |
354 | | fn concat(self, rest: Self::Rest) -> Self::Output; |
355 | | } |
356 | | |
357 | | unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N> |
358 | | where |
359 | | N: ArrayLength<T> + Add<M>, |
360 | | M: ArrayLength<T>, |
361 | | Sum<N, M>: ArrayLength<T>, |
362 | | { |
363 | | type Rest = GenericArray<T, M>; |
364 | | type Output = GenericArray<T, Sum<N, M>>; |
365 | | |
366 | 0 | fn concat(self, rest: Self::Rest) -> Self::Output { |
367 | 0 | let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit(); |
368 | | |
369 | 0 | let out_ptr = output.as_mut_ptr() as *mut Self; |
370 | | |
371 | | unsafe { |
372 | | // write all of self to the pointer |
373 | 0 | ptr::write(out_ptr, self); |
374 | | // increment past self, then write the rest |
375 | 0 | ptr::write(out_ptr.add(1) as *mut _, rest); |
376 | | |
377 | 0 | output.assume_init() |
378 | | } |
379 | 0 | } |
380 | | } |