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