Skip to main content

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}