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