| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- //! Useful traits for manipulating sequences of data stored in `GenericArray`s
- use super::*;
- use core::ops::{Add, Sub};
- use core::mem::MaybeUninit;
- use core::ptr;
- use typenum::operator_aliases::*;
- /// Defines some sequence with an associated length and iteration capabilities.
- ///
- /// This is useful for passing N-length generic arrays as generics.
- pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
- /// `GenericArray` associated length
- type Length: ArrayLength<T>;
- /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence`
- type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
- /// Initializes a new sequence instance using the given function.
- ///
- /// If the generator function panics while initializing the sequence,
- /// any already initialized elements will be dropped.
- fn generate<F>(f: F) -> Self::Sequence
- where
- F: FnMut(usize) -> T;
- #[doc(hidden)]
- fn inverted_zip<B, U, F>(
- self,
- lhs: GenericArray<B, Self::Length>,
- mut f: F,
- ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
- where
- GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length>
- + MappedGenericSequence<B, U>,
- Self: MappedGenericSequence<T, U>,
- Self::Length: ArrayLength<B> + ArrayLength<U>,
- F: FnMut(B, Self::Item) -> U,
- {
- unsafe {
- let mut left = ArrayConsumer::new(lhs);
- let (left_array_iter, left_position) = left.iter_position();
- FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map(
- |(l, right_value)| {
- let left_value = ptr::read(l);
- *left_position += 1;
- f(left_value, right_value)
- },
- ))
- }
- }
- #[doc(hidden)]
- fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
- where
- Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
- Self: MappedGenericSequence<T, U>,
- Self::Length: ArrayLength<B> + ArrayLength<U>,
- F: FnMut(Lhs::Item, Self::Item) -> U,
- {
- FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r)))
- }
- }
- /// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item`
- ///
- /// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`,
- /// this can be useful for keeping things organized.
- pub type SequenceItem<T> = <T as IntoIterator>::Item;
- unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S
- where
- &'a S: IntoIterator,
- {
- type Length = S::Length;
- type Sequence = S::Sequence;
- #[inline]
- fn generate<F>(f: F) -> Self::Sequence
- where
- F: FnMut(usize) -> T,
- {
- S::generate(f)
- }
- }
- unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S
- where
- &'a mut S: IntoIterator,
- {
- type Length = S::Length;
- type Sequence = S::Sequence;
- #[inline]
- fn generate<F>(f: F) -> Self::Sequence
- where
- F: FnMut(usize) -> T,
- {
- S::generate(f)
- }
- }
- /// Defines any `GenericSequence` which can be lengthened or extended by appending
- /// or prepending an element to it.
- ///
- /// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back`
- pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> {
- /// `GenericSequence` that has one more element than `Self`
- type Longer: Shorten<T, Shorter = Self>;
- /// Returns a new array with the given element appended to the end of it.
- ///
- /// Example:
- ///
- /// ```rust
- /// # use generic_array::{arr, sequence::Lengthen};
- /// # fn main() {
- /// let a = arr![i32; 1, 2, 3];
- ///
- /// let b = a.append(4);
- ///
- /// assert_eq!(b, arr![i32; 1, 2, 3, 4]);
- /// # }
- /// ```
- fn append(self, last: T) -> Self::Longer;
- /// Returns a new array with the given element prepended to the front of it.
- ///
- /// Example:
- ///
- /// ```rust
- /// # use generic_array::{arr, sequence::Lengthen};
- /// # fn main() {
- /// let a = arr![i32; 1, 2, 3];
- ///
- /// let b = a.prepend(4);
- ///
- /// assert_eq!(b, arr![i32; 4, 1, 2, 3]);
- /// # }
- /// ```
- fn prepend(self, first: T) -> Self::Longer;
- }
- /// Defines a `GenericSequence` which can be shortened by removing the first or last element from it.
- ///
- /// Additionally, any shortened sequence can be lengthened by
- /// appending or prepending an element to it.
- pub unsafe trait Shorten<T>: Sized + GenericSequence<T> {
- /// `GenericSequence` that has one less element than `Self`
- type Shorter: Lengthen<T, Longer = Self>;
- /// Returns a new array without the last element, and the last element.
- ///
- /// Example:
- ///
- /// ```rust
- /// # use generic_array::{arr, sequence::Shorten};
- /// # fn main() {
- /// let a = arr![i32; 1, 2, 3, 4];
- ///
- /// let (init, last) = a.pop_back();
- ///
- /// assert_eq!(init, arr![i32; 1, 2, 3]);
- /// assert_eq!(last, 4);
- /// # }
- /// ```
- fn pop_back(self) -> (Self::Shorter, T);
- /// Returns a new array without the first element, and the first element.
- /// Example:
- ///
- /// ```rust
- /// # use generic_array::{arr, sequence::Shorten};
- /// # fn main() {
- /// let a = arr![i32; 1, 2, 3, 4];
- ///
- /// let (head, tail) = a.pop_front();
- ///
- /// assert_eq!(head, 1);
- /// assert_eq!(tail, arr![i32; 2, 3, 4]);
- /// # }
- /// ```
- fn pop_front(self) -> (T, Self::Shorter);
- }
- unsafe impl<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N>
- where
- N: Add<B1>,
- Add1<N>: ArrayLength<T>,
- Add1<N>: Sub<B1, Output = N>,
- Sub1<Add1<N>>: ArrayLength<T>,
- {
- type Longer = GenericArray<T, Add1<N>>;
- fn append(self, last: T) -> Self::Longer {
- let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
- // Note this is *mut Self, so add(1) increments by the whole array
- let out_ptr = longer.as_mut_ptr() as *mut Self;
- unsafe {
- // write self first
- ptr::write(out_ptr, self);
- // increment past self, then write the last
- ptr::write(out_ptr.add(1) as *mut T, last);
- longer.assume_init()
- }
- }
- fn prepend(self, first: T) -> Self::Longer {
- let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
- // Note this is *mut T, so add(1) increments by a single T
- let out_ptr = longer.as_mut_ptr() as *mut T;
- unsafe {
- // write the first at the start
- ptr::write(out_ptr, first);
- // increment past the first, then write self
- ptr::write(out_ptr.add(1) as *mut Self, self);
- longer.assume_init()
- }
- }
- }
- unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N>
- where
- N: Sub<B1>,
- Sub1<N>: ArrayLength<T>,
- Sub1<N>: Add<B1, Output = N>,
- Add1<Sub1<N>>: ArrayLength<T>,
- {
- type Shorter = GenericArray<T, Sub1<N>>;
- fn pop_back(self) -> (Self::Shorter, T) {
- let whole = ManuallyDrop::new(self);
- unsafe {
- let init = ptr::read(whole.as_ptr() as _);
- let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _);
- (init, last)
- }
- }
- fn pop_front(self) -> (T, Self::Shorter) {
- // ensure this doesn't get dropped
- let whole = ManuallyDrop::new(self);
- unsafe {
- let head = ptr::read(whole.as_ptr() as _);
- let tail = ptr::read(whole.as_ptr().offset(1) as _);
- (head, tail)
- }
- }
- }
- /// Defines a `GenericSequence` that can be split into two parts at a given pivot index.
- pub unsafe trait Split<T, K>: GenericSequence<T>
- where
- K: ArrayLength<T>,
- {
- /// First part of the resulting split array
- type First: GenericSequence<T>;
- /// Second part of the resulting split array
- type Second: GenericSequence<T>;
- /// Splits an array at the given index, returning the separate parts of the array.
- fn split(self) -> (Self::First, Self::Second);
- }
- unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
- where
- N: ArrayLength<T>,
- K: ArrayLength<T>,
- N: Sub<K>,
- Diff<N, K>: ArrayLength<T>,
- {
- type First = GenericArray<T, K>;
- type Second = GenericArray<T, Diff<N, K>>;
- fn split(self) -> (Self::First, Self::Second) {
- unsafe {
- // ensure this doesn't get dropped
- let whole = ManuallyDrop::new(self);
- let head = ptr::read(whole.as_ptr() as *const _);
- let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _);
- (head, tail)
- }
- }
- }
- unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N>
- where
- N: ArrayLength<T>,
- K: ArrayLength<T> + 'static,
- N: Sub<K>,
- Diff<N, K>: ArrayLength<T>,
- {
- type First = &'a GenericArray<T, K>;
- type Second = &'a GenericArray<T, Diff<N, K>>;
- fn split(self) -> (Self::First, Self::Second) {
- unsafe {
- let ptr_to_first: *const T = self.as_ptr();
- let head = &*(ptr_to_first as *const _);
- let tail = &*(ptr_to_first.add(K::USIZE) as *const _);
- (head, tail)
- }
- }
- }
- unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N>
- where
- N: ArrayLength<T>,
- K: ArrayLength<T> + 'static,
- N: Sub<K>,
- Diff<N, K>: ArrayLength<T>,
- {
- type First = &'a mut GenericArray<T, K>;
- type Second = &'a mut GenericArray<T, Diff<N, K>>;
- fn split(self) -> (Self::First, Self::Second) {
- unsafe {
- let ptr_to_first: *mut T = self.as_mut_ptr();
- let head = &mut *(ptr_to_first as *mut _);
- let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _);
- (head, tail)
- }
- }
- }
- /// Defines `GenericSequence`s which can be joined together, forming a larger array.
- pub unsafe trait Concat<T, M>: GenericSequence<T>
- where
- M: ArrayLength<T>,
- {
- /// Sequence to be concatenated with `self`
- type Rest: GenericSequence<T, Length = M>;
- /// Resulting sequence formed by the concatenation.
- type Output: GenericSequence<T>;
- /// Concatenate, or join, two sequences.
- fn concat(self, rest: Self::Rest) -> Self::Output;
- }
- unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
- where
- N: ArrayLength<T> + Add<M>,
- M: ArrayLength<T>,
- Sum<N, M>: ArrayLength<T>,
- {
- type Rest = GenericArray<T, M>;
- type Output = GenericArray<T, Sum<N, M>>;
- fn concat(self, rest: Self::Rest) -> Self::Output {
- let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit();
- let out_ptr = output.as_mut_ptr() as *mut Self;
- unsafe {
- // write all of self to the pointer
- ptr::write(out_ptr, self);
- // increment past self, then write the rest
- ptr::write(out_ptr.add(1) as *mut _, rest);
- output.assume_init()
- }
- }
- }
|