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