generic_array/sequence.rs
1//! Useful traits for manipulating sequences of data stored in `GenericArray`s
2
3use super::*;
4use core::mem::MaybeUninit;
5use core::ops::{Add, Div, Mul, Sub};
6use core::ptr;
7use 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///
13/// # Safety
14/// Care must be taken when implementing such that methods are safe.
15///
16/// Lengths must match, and element drop on panic must be handled.
17pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
18 /// `GenericArray` associated length
19 type Length: ArrayLength;
20
21 /// Owned sequence type used in conjunction with reference implementations of `GenericSequence`
22 type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
23
24 /// Initializes a new sequence instance using the given function.
25 ///
26 /// If the generator function panics while initializing the sequence,
27 /// any already initialized elements will be dropped.
28 ///
29 /// See also [`FallibleGenericSequence::try_generate`].
30 fn generate<F>(f: F) -> Self::Sequence
31 where
32 F: FnMut(usize) -> T;
33
34 /// Initializes a new sequence instance by repeating the given value.
35 ///
36 /// Clones the value for all but the last element, taking ownership of the original value for the last.
37 ///
38 /// This is semantically equivalent to `FromIterator::from_iter(core::iter::repeat_n(value, N::USIZE))`
39 /// but available on older Rust versions. `repeat_n` was stabilized in Rust 1.82.0
40 #[inline(always)]
41 fn repeat(value: T) -> Self::Sequence
42 where
43 T: Clone,
44 {
45 let mut value = Some(value);
46
47 Self::generate(move |i| unsafe {
48 if i + 1 == Self::Length::USIZE {
49 // for the last element, take the value
50 value.take().unwrap_unchecked()
51 } else if let Some(ref v) = value {
52 // otherwise, clone it
53 v.clone()
54 } else {
55 // SAFETY: this should never be reached
56 core::hint::unreachable_unchecked()
57 }
58 })
59 }
60
61 /// Treats `self` as the right-hand operand in a zip operation
62 ///
63 /// This is optimized for stack-allocated `GenericArray`s
64 #[cfg_attr(not(feature = "internals"), doc(hidden))]
65 #[inline(always)]
66 fn inverted_zip<B, U, F>(
67 self,
68 lhs: GenericArray<B, Self::Length>,
69 mut f: F,
70 ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
71 where
72 GenericArray<B, Self::Length>:
73 GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
74 Self: MappedGenericSequence<T, U>,
75 F: FnMut(B, Self::Item) -> U,
76 {
77 unsafe {
78 let mut left = ManuallyDrop::new(lhs);
79 let mut left = IntrusiveArrayConsumer::new(&mut left);
80
81 let (left_array_iter, left_position) = left.iter_position();
82
83 FromIterator::from_iter(left_array_iter.zip(self).map(|(l, right_value)| {
84 let left_value = ptr::read(l);
85
86 *left_position += 1;
87
88 f(left_value, right_value)
89 }))
90 }
91 }
92
93 /// Treats `self` as the right-hand operand in a zip operation
94 #[cfg_attr(not(feature = "internals"), doc(hidden))]
95 #[inline(always)]
96 fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
97 where
98 Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
99 Self: MappedGenericSequence<T, U>,
100 F: FnMut(Lhs::Item, Self::Item) -> U,
101 {
102 FromIterator::from_iter(lhs.into_iter().zip(self).map(|(l, r)| f(l, r)))
103 }
104}
105
106/// Extension to `FromIterator` for fallible initialization.
107pub trait FromFallibleIterator<T>: Sized {
108 /// Initializes a new collection from a fallible iterator.
109 ///
110 /// If the iterator returns an error or panics while initializing the sequence,
111 /// any already initialized elements will be dropped and the error returned.
112 ///
113 /// Unlike `.collect::<Result<Self, E>>()`, which short-circuits the source iterator
114 /// on the first error before the collection's `FromIterator` impl can verify the
115 /// correct number of elements — causing a length-mismatch panic — this method
116 /// handles the error and length check correctly.
117 fn from_fallible_iter<I, E>(iter: I) -> Result<Self, E>
118 where
119 I: IntoIterator<Item = Result<T, E>>;
120}
121
122macro_rules! decl_fallible_sequence_inner {
123 () => {
124 /// Error type for sequence creation failures, independent of the element generator.
125 ///
126 /// For infallible sequence types such as [`GenericArray`](crate::GenericArray),
127 /// this is [`Infallible`](core::convert::Infallible).
128 type Error;
129
130 /// Initializes a new sequence instance using the given fallible function.
131 ///
132 /// If the generator function returns an error or panics while initializing the sequence,
133 /// any already initialized elements will be dropped.
134 ///
135 /// Returns `Ok(Ok(sequence))` on success, `Ok(Err(e))` if the generator fails,
136 /// or `Err(Self::Error)` if the sequence itself cannot be created (e.g., allocation failure).
137 fn try_generate<F, E>(f: F) -> Result<Result<Self::Sequence, E>, Self::Error>
138 where
139 F: FnMut(usize) -> Result<T, E>;
140 };
141}
142
143#[rustversion::before(1.79)]
144macro_rules! decl_fallible_sequence {
145 ($(#[$meta:meta])*) => {
146 $(#[$meta])*
147 pub unsafe trait FallibleGenericSequence<T>: GenericSequence<T>
148 where
149 Self::Sequence: FromFallibleIterator<T>,
150 {
151 decl_fallible_sequence_inner!();
152 }
153 };
154}
155
156#[rustversion::since(1.79)]
157macro_rules! decl_fallible_sequence {
158 ($(#[$meta:meta])*) => {
159 $(#[$meta])*
160 pub unsafe trait FallibleGenericSequence<T>:
161 GenericSequence<T, Sequence: FromFallibleIterator<T>>
162 {
163 decl_fallible_sequence_inner!();
164 }
165 };
166}
167
168decl_fallible_sequence! {
169 /// Extension to `GenericSequence` for fallible initialization.
170 ///
171 /// # Safety
172 ///
173 /// Care must be taken when implementing such that methods are safe.
174 ///
175 /// Lengths must match, and element drop on panic or error must be handled.
176 ///
177 /// # Compatibility
178 ///
179 /// Associated type bounds were only introduced in Rust 1.79, and to ensure easy usage
180 /// on newer versions of Rust this trait uses that. However, on pre-1.79 Rust, the
181 /// `Sequence: FromFallibleIterator<T>` trait is not implied, and must be manually
182 /// specified when `FallibleGenericSequence` is used.
183}
184
185/// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item`
186///
187/// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`,
188/// this can be useful for keeping things organized.
189pub type SequenceItem<T> = <T as IntoIterator>::Item;
190
191unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S
192where
193 &'a S: IntoIterator,
194{
195 type Length = S::Length;
196 type Sequence = S::Sequence;
197
198 #[inline(always)]
199 fn generate<F>(f: F) -> Self::Sequence
200 where
201 F: FnMut(usize) -> T,
202 {
203 S::generate(f)
204 }
205}
206
207unsafe impl<'a, T: 'a, S: FallibleGenericSequence<T>> FallibleGenericSequence<T> for &'a S
208where
209 &'a S: IntoIterator,
210 Self::Sequence: FromFallibleIterator<T>,
211{
212 type Error = S::Error;
213
214 #[inline(always)]
215 fn try_generate<F, E>(f: F) -> Result<Result<Self::Sequence, E>, Self::Error>
216 where
217 F: FnMut(usize) -> Result<T, E>,
218 {
219 S::try_generate(f)
220 }
221}
222
223unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S
224where
225 &'a mut S: IntoIterator,
226{
227 type Length = S::Length;
228 type Sequence = S::Sequence;
229
230 #[inline(always)]
231 fn generate<F>(f: F) -> Self::Sequence
232 where
233 F: FnMut(usize) -> T,
234 {
235 S::generate(f)
236 }
237}
238
239unsafe impl<'a, T: 'a, S: FallibleGenericSequence<T>> FallibleGenericSequence<T> for &'a mut S
240where
241 &'a mut S: IntoIterator,
242 Self::Sequence: FromFallibleIterator<T>,
243{
244 type Error = S::Error;
245
246 #[inline(always)]
247 fn try_generate<F, E>(f: F) -> Result<Result<Self::Sequence, E>, Self::Error>
248 where
249 F: FnMut(usize) -> Result<T, E>,
250 {
251 S::try_generate(f)
252 }
253}
254
255/// Defines any `GenericSequence` which can be lengthened or extended by appending
256/// or prepending an element to it.
257///
258/// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back`
259///
260/// # Safety
261/// While the [`append`](Lengthen::append) and [`prepend`](Lengthen::prepend)
262/// methods are marked safe, care must be taken when implementing them.
263pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> {
264 /// `GenericSequence` that has one more element than `Self`
265 type Longer: Shorten<T, Shorter = Self>;
266
267 /// Returns a new array with the given element appended to the end of it.
268 ///
269 /// Example:
270 ///
271 /// ```rust
272 /// # use generic_array::{arr, sequence::Lengthen};
273 ///
274 /// let a = arr![1, 2, 3];
275 ///
276 /// let b = a.append(4);
277 ///
278 /// assert_eq!(b, arr![1, 2, 3, 4]);
279 /// ```
280 fn append(self, last: T) -> Self::Longer;
281
282 /// Returns a new array with the given element prepended to the front of it.
283 ///
284 /// Example:
285 ///
286 /// ```rust
287 /// # use generic_array::{arr, sequence::Lengthen};
288 ///
289 /// let a = arr![1, 2, 3];
290 ///
291 /// let b = a.prepend(4);
292 ///
293 /// assert_eq!(b, arr![4, 1, 2, 3]);
294 /// ```
295 fn prepend(self, first: T) -> Self::Longer;
296}
297
298/// Defines a `GenericSequence` which can be shortened by removing the first or last element from it.
299///
300/// Additionally, any shortened sequence can be lengthened by
301/// appending or prepending an element to it.
302///
303/// # Safety
304/// While the [`pop_back`](Shorten::pop_back) and [`pop_front`](Shorten::pop_front)
305/// methods are marked safe, care must be taken when implementing them.
306pub unsafe trait Shorten<T>: Sized + GenericSequence<T> {
307 /// `GenericSequence` that has one less element than `Self`
308 type Shorter: Lengthen<T, Longer = Self>;
309
310 /// Returns a new array without the last element, and the last element.
311 ///
312 /// Example:
313 ///
314 /// ```rust
315 /// # use generic_array::{arr, sequence::Shorten};
316 ///
317 /// let a = arr![1, 2, 3, 4];
318 ///
319 /// let (init, last) = a.pop_back();
320 ///
321 /// assert_eq!(init, arr![1, 2, 3]);
322 /// assert_eq!(last, 4);
323 /// ```
324 fn pop_back(self) -> (Self::Shorter, T);
325
326 /// Returns a new array without the first element, and the first element.
327 /// Example:
328 ///
329 /// ```rust
330 /// # use generic_array::{arr, sequence::Shorten};
331 ///
332 /// let a = arr![1, 2, 3, 4];
333 ///
334 /// let (head, tail) = a.pop_front();
335 ///
336 /// assert_eq!(head, 1);
337 /// assert_eq!(tail, arr![2, 3, 4]);
338 /// ```
339 fn pop_front(self) -> (T, Self::Shorter);
340}
341
342unsafe impl<T, N: ArrayLength> Lengthen<T> for GenericArray<T, N>
343where
344 N: Add<B1>,
345 Add1<N>: ArrayLength,
346 Add1<N>: Sub<B1, Output = N>,
347 Sub1<Add1<N>>: ArrayLength,
348{
349 type Longer = GenericArray<T, Add1<N>>;
350
351 #[inline]
352 fn append(self, last: T) -> Self::Longer {
353 let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
354
355 // Note this is *mut Self, so add(1) increments by the whole array
356 let out_ptr = longer.as_mut_ptr() as *mut Self;
357
358 unsafe {
359 // write self first
360 ptr::write(out_ptr, self);
361 // increment past self, then write the last
362 ptr::write(out_ptr.add(1) as *mut T, last);
363
364 longer.assume_init()
365 }
366 }
367
368 #[inline]
369 fn prepend(self, first: T) -> Self::Longer {
370 let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
371
372 // Note this is *mut T, so add(1) increments by a single T
373 let out_ptr = longer.as_mut_ptr() as *mut T;
374
375 unsafe {
376 // write the first at the start
377 ptr::write(out_ptr, first);
378 // increment past the first, then write self
379 ptr::write(out_ptr.add(1) as *mut Self, self);
380
381 longer.assume_init()
382 }
383 }
384}
385
386unsafe impl<T, N: ArrayLength> Shorten<T> for GenericArray<T, N>
387where
388 N: Sub<B1>,
389 Sub1<N>: ArrayLength,
390 Sub1<N>: Add<B1, Output = N>,
391 Add1<Sub1<N>>: ArrayLength,
392{
393 type Shorter = GenericArray<T, Sub1<N>>;
394
395 #[inline]
396 fn pop_back(self) -> (Self::Shorter, T) {
397 let whole = ManuallyDrop::new(self);
398
399 unsafe {
400 let init = ptr::read(whole.as_ptr() as _);
401 let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _);
402
403 (init, last)
404 }
405 }
406
407 #[inline]
408 fn pop_front(self) -> (T, Self::Shorter) {
409 // ensure this doesn't get dropped
410 let whole = ManuallyDrop::new(self);
411
412 unsafe {
413 let head = ptr::read(whole.as_ptr() as _);
414 let tail = ptr::read(whole.as_ptr().offset(1) as _);
415
416 (head, tail)
417 }
418 }
419}
420
421/// Defines a `GenericSequence` that can be split into two parts at a given pivot index.
422///
423/// # Safety
424/// While the [`split`](Split::split) method is marked safe,
425/// care must be taken when implementing it.
426pub unsafe trait Split<T, K: ArrayLength>: GenericSequence<T> {
427 /// First part of the resulting split array
428 type First: GenericSequence<T>;
429 /// Second part of the resulting split array
430 type Second: GenericSequence<T>;
431
432 /// Splits an array at the given index, returning the separate parts of the array.
433 fn split(self) -> (Self::First, Self::Second);
434}
435
436unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
437where
438 N: ArrayLength,
439 K: ArrayLength,
440 N: Sub<K>,
441 Diff<N, K>: ArrayLength,
442{
443 type First = GenericArray<T, K>;
444 type Second = GenericArray<T, Diff<N, K>>;
445
446 #[inline]
447 fn split(self) -> (Self::First, Self::Second) {
448 unsafe {
449 // ensure this doesn't get dropped
450 let whole = ManuallyDrop::new(self);
451
452 let head = ptr::read(whole.as_ptr() as *const _);
453 let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _);
454
455 (head, tail)
456 }
457 }
458}
459
460unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N>
461where
462 N: ArrayLength,
463 K: ArrayLength,
464 N: Sub<K>,
465 Diff<N, K>: ArrayLength,
466{
467 type First = &'a GenericArray<T, K>;
468 type Second = &'a GenericArray<T, Diff<N, K>>;
469
470 #[inline]
471 fn split(self) -> (Self::First, Self::Second) {
472 unsafe {
473 let ptr_to_first: *const T = self.as_ptr();
474 let head = &*(ptr_to_first as *const _);
475 let tail = &*(ptr_to_first.add(K::USIZE) as *const _);
476 (head, tail)
477 }
478 }
479}
480
481unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N>
482where
483 N: ArrayLength,
484 K: ArrayLength,
485 N: Sub<K>,
486 Diff<N, K>: ArrayLength,
487{
488 type First = &'a mut GenericArray<T, K>;
489 type Second = &'a mut GenericArray<T, Diff<N, K>>;
490
491 #[inline]
492 fn split(self) -> (Self::First, Self::Second) {
493 unsafe {
494 let ptr_to_first: *mut T = self.as_mut_ptr();
495 let head = &mut *(ptr_to_first as *mut _);
496 let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _);
497 (head, tail)
498 }
499 }
500}
501
502/// Defines `GenericSequence`s which can be joined together, forming a larger array.
503///
504/// # Safety
505/// While the [`concat`](Concat::concat) method is marked safe,
506/// care must be taken when implementing it.
507pub unsafe trait Concat<T, M: ArrayLength>: GenericSequence<T> {
508 /// Sequence to be concatenated with `self`
509 type Rest: GenericSequence<T, Length = M>;
510
511 /// Resulting sequence formed by the concatenation.
512 type Output: GenericSequence<T>;
513
514 /// Concatenate, or join, two sequences.
515 fn concat(self, rest: Self::Rest) -> Self::Output;
516}
517
518unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
519where
520 N: ArrayLength + Add<M>,
521 M: ArrayLength,
522 Sum<N, M>: ArrayLength,
523{
524 type Rest = GenericArray<T, M>;
525 type Output = GenericArray<T, Sum<N, M>>;
526
527 #[inline]
528 fn concat(self, rest: Self::Rest) -> Self::Output {
529 let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit();
530
531 let out_ptr = output.as_mut_ptr() as *mut Self;
532
533 unsafe {
534 // write all of self to the pointer
535 ptr::write(out_ptr, self);
536 // increment past self, then write the rest
537 ptr::write(out_ptr.add(1) as *mut _, rest);
538
539 output.assume_init()
540 }
541 }
542}
543
544/// Defines a `GenericSequence` which can be shortened by removing an element at a given index.
545///
546/// # Safety
547/// While the [`remove`](Remove::remove) and [`swap_remove`](Remove::swap_remove) methods are marked safe,
548/// care must be taken when implementing it. The [`remove_unchecked`](Remove::remove_unchecked)
549/// and [`swap_remove_unchecked`](Remove::swap_remove_unchecked) methods are unsafe
550/// and must be used with caution.
551pub unsafe trait Remove<T, N: ArrayLength>: GenericSequence<T> {
552 /// Resulting sequence formed by removing an element at the given index.
553 type Output: GenericSequence<T>;
554
555 /// Removes an element at the given index, shifting elements
556 /// after the given index to the left to fill the gap, resulting
557 /// in a time complexity of O(n) where `n=N-idx-1`
558 ///
559 /// # Example
560 ///
561 /// ```rust
562 /// # use generic_array::{arr, sequence::Remove};
563 /// let a = arr![1, 2, 3, 4];
564 ///
565 /// let (removed, b) = a.remove(2);
566 /// assert_eq!(removed, 3);
567 /// assert_eq!(b, arr![1, 2, 4]);
568 /// ```
569 ///
570 /// # Panics
571 ///
572 /// Panics if the index is out of bounds.
573 #[inline]
574 fn remove(self, idx: usize) -> (T, Self::Output) {
575 assert!(
576 idx < N::USIZE,
577 "Index out of bounds: the len is {} but the index is {}",
578 N::USIZE,
579 idx
580 );
581
582 unsafe { self.remove_unchecked(idx) }
583 }
584
585 /// Removes an element at the given index, swapping it with the last element.
586 ///
587 /// # Example
588 ///
589 /// ```rust
590 /// # use generic_array::{arr, sequence::Remove};
591 /// let a = arr![1, 2, 3, 4];
592 ///
593 /// let (removed, b) = a.swap_remove(1);
594 /// assert_eq!(removed, 2);
595 /// assert_eq!(b, arr![1, 4, 3]); // note 4 is now at index 1
596 /// ```
597 ///
598 /// # Panics
599 ///
600 /// Panics if the index is out of bounds.
601 fn swap_remove(self, idx: usize) -> (T, Self::Output) {
602 assert!(
603 idx < N::USIZE,
604 "Index out of bounds: the len is {} but the index is {}",
605 N::USIZE,
606 idx
607 );
608
609 unsafe { self.swap_remove_unchecked(idx) }
610 }
611
612 /// Removes an element at the given index without bounds checking,
613 /// shifting elements after the given index to the left to fill the gap,
614 /// resulting in a time complexity of O(n) where `n=N-idx-1`
615 ///
616 /// See [`remove`](Remove::remove) for an example.
617 ///
618 /// # Safety
619 /// The caller must ensure that the index is within bounds, otherwise
620 /// it is undefined behavior.
621 unsafe fn remove_unchecked(self, idx: usize) -> (T, Self::Output);
622
623 /// Removes an element at the given index without bounds checking, swapping it with the last element.
624 ///
625 /// See [`swap_remove`](Remove::swap_remove) for an example.
626 ///
627 /// # Safety
628 /// The caller must ensure that the index is within bounds, otherwise
629 /// it is undefined behavior.
630 unsafe fn swap_remove_unchecked(self, idx: usize) -> (T, Self::Output);
631}
632
633unsafe impl<T, N> Remove<T, N> for GenericArray<T, N>
634where
635 N: ArrayLength + Sub<B1>,
636 Sub1<N>: ArrayLength,
637{
638 type Output = GenericArray<T, Sub1<N>>;
639
640 #[inline]
641 unsafe fn remove_unchecked(self, idx: usize) -> (T, Self::Output) {
642 if idx >= N::USIZE || N::USIZE == 0 {
643 core::hint::unreachable_unchecked();
644 }
645
646 let mut array = ManuallyDrop::new(self);
647
648 let dst = array.as_mut_ptr().add(idx);
649
650 let removed = ptr::read(dst);
651
652 // shift all elements over by one to fill gap
653 ptr::copy(dst.add(1), dst, N::USIZE - idx - 1);
654
655 // return removed element and truncated array
656 (removed, mem::transmute_copy(&array))
657 }
658
659 #[inline]
660 unsafe fn swap_remove_unchecked(self, idx: usize) -> (T, Self::Output) {
661 if idx >= N::USIZE || N::USIZE == 0 {
662 core::hint::unreachable_unchecked();
663 }
664
665 let mut array = ManuallyDrop::new(self);
666
667 array.swap(idx, N::USIZE - 1);
668
669 // remove the last element
670 let removed = ptr::read(array.as_ptr().add(N::USIZE - 1));
671
672 // return removed element and truncated array
673 (removed, mem::transmute_copy(&array))
674 }
675}
676
677/// Defines a `GenericSequence` of `GenericArray`s which can be flattened into a single `GenericArray`,
678/// at zero cost.
679///
680/// # Safety
681/// While the [`flatten`](Flatten::flatten) method is marked safe,
682/// care must be taken when implementing it. However, the given trait bounds
683/// should be sufficient to ensure safety.
684pub unsafe trait Flatten<T, N, M>: GenericSequence<GenericArray<T, N>, Length = M>
685where
686 N: ArrayLength + Mul<M>,
687 Prod<N, M>: ArrayLength,
688{
689 /// Flattened sequence type
690 type Output: GenericSequence<T, Length = Prod<N, M>>;
691
692 /// Flattens the sequence into a single `GenericArray`.
693 ///
694 /// # Example
695 ///
696 /// ```rust
697 /// # use generic_array::{arr, sequence::Flatten};
698 /// assert_eq!(
699 /// arr![arr![1, 2], arr![3, 4], arr![5, 6]].flatten(),
700 /// arr![1, 2, 3, 4, 5, 6]
701 /// );
702 /// ```
703 fn flatten(self) -> Self::Output;
704}
705
706/// Defines a `GenericSequence` of `T` which can be split evenly into a sequence of `GenericArray`s,
707///
708/// # Safety
709/// While the [`unflatten`](Unflatten::unflatten) method is marked safe,
710/// care must be taken when implementing it. However, the given trait bounds
711/// should be sufficient to ensure safety.
712pub unsafe trait Unflatten<T, NM, N>: GenericSequence<T, Length = NM>
713where
714 NM: ArrayLength + Div<N>,
715 N: ArrayLength,
716 Quot<NM, N>: ArrayLength,
717{
718 /// Unflattened sequence type
719 type Output: GenericSequence<GenericArray<T, N>, Length = Quot<NM, N>>;
720
721 /// Unflattens the sequence into a sequence of `GenericArray`s.
722 ///
723 /// # Example
724 ///
725 /// ```rust
726 /// # use generic_array::{arr, sequence::Unflatten};
727 /// assert_eq!(
728 /// arr![1, 2, 3, 4, 5, 6].unflatten(),
729 /// arr![arr![1, 2], arr![3, 4], arr![5, 6]]
730 /// );
731 /// ```
732 fn unflatten(self) -> Self::Output;
733}
734
735unsafe impl<T, N, M> Flatten<T, N, M> for GenericArray<GenericArray<T, N>, M>
736where
737 N: ArrayLength + Mul<M>,
738 M: ArrayLength,
739 Prod<N, M>: ArrayLength,
740{
741 type Output = GenericArray<T, Prod<N, M>>;
742
743 #[inline(always)]
744 fn flatten(self) -> Self::Output {
745 unsafe { crate::const_transmute(self) }
746 }
747}
748
749unsafe impl<'a, T, N, M> Flatten<T, N, M> for &'a GenericArray<GenericArray<T, N>, M>
750where
751 N: ArrayLength + Mul<M>,
752 M: ArrayLength,
753 Prod<N, M>: ArrayLength,
754{
755 type Output = &'a GenericArray<T, Prod<N, M>>;
756
757 #[inline(always)]
758 fn flatten(self) -> Self::Output {
759 unsafe { mem::transmute(self) }
760 }
761}
762
763unsafe impl<'a, T, N, M> Flatten<T, N, M> for &'a mut GenericArray<GenericArray<T, N>, M>
764where
765 N: ArrayLength + Mul<M>,
766 M: ArrayLength,
767 Prod<N, M>: ArrayLength,
768{
769 type Output = &'a mut GenericArray<T, Prod<N, M>>;
770
771 #[inline(always)]
772 fn flatten(self) -> Self::Output {
773 unsafe { mem::transmute(self) }
774 }
775}
776
777unsafe impl<T, NM, N> Unflatten<T, NM, N> for GenericArray<T, NM>
778where
779 NM: ArrayLength + Div<N>,
780 N: ArrayLength,
781 Quot<NM, N>: ArrayLength,
782{
783 type Output = GenericArray<GenericArray<T, N>, Quot<NM, N>>;
784
785 #[inline(always)]
786 fn unflatten(self) -> Self::Output {
787 unsafe { crate::const_transmute(self) }
788 }
789}
790
791unsafe impl<'a, T, NM, N> Unflatten<T, NM, N> for &'a GenericArray<T, NM>
792where
793 NM: ArrayLength + Div<N>,
794 N: ArrayLength,
795 Quot<NM, N>: ArrayLength,
796{
797 type Output = &'a GenericArray<GenericArray<T, N>, Quot<NM, N>>;
798
799 #[inline(always)]
800 fn unflatten(self) -> Self::Output {
801 unsafe { mem::transmute(self) }
802 }
803}
804
805unsafe impl<'a, T, NM, N> Unflatten<T, NM, N> for &'a mut GenericArray<T, NM>
806where
807 NM: ArrayLength + Div<N>,
808 N: ArrayLength,
809 Quot<NM, N>: ArrayLength,
810{
811 type Output = &'a mut GenericArray<GenericArray<T, N>, Quot<NM, N>>;
812
813 #[inline(always)]
814 fn unflatten(self) -> Self::Output {
815 unsafe { mem::transmute(self) }
816 }
817}