//! 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: Sized + IntoIterator { /// `GenericArray` associated length type Length: ArrayLength; /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence` type Sequence: GenericSequence + FromIterator; /// 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) -> Self::Sequence where F: FnMut(usize) -> T; #[doc(hidden)] fn inverted_zip( self, lhs: GenericArray, mut f: F, ) -> MappedSequence, B, U> where GenericArray: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, 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(self, lhs: Lhs, mut f: F) -> MappedSequence where Lhs: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, 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 = ::Item; unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a S where &'a S: IntoIterator, { type Length = S::Length; type Sequence = S::Sequence; #[inline] fn generate(f: F) -> Self::Sequence where F: FnMut(usize) -> T, { S::generate(f) } } unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a mut S where &'a mut S: IntoIterator, { type Length = S::Length; type Sequence = S::Sequence; #[inline] fn generate(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: Sized + GenericSequence { /// `GenericSequence` that has one more element than `Self` type Longer: Shorten; /// 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: Sized + GenericSequence { /// `GenericSequence` that has one less element than `Self` type Shorter: Lengthen; /// 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> Lengthen for GenericArray where N: Add, Add1: ArrayLength, Add1: Sub, Sub1>: ArrayLength, { type Longer = GenericArray>; fn append(self, last: T) -> Self::Longer { let mut longer: MaybeUninit = 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 = 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> Shorten for GenericArray where N: Sub, Sub1: ArrayLength, Sub1: Add, Add1>: ArrayLength, { type Shorter = GenericArray>; 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::::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: GenericSequence where K: ArrayLength, { /// First part of the resulting split array type First: GenericSequence; /// Second part of the resulting split array type Second: GenericSequence; /// Splits an array at the given index, returning the separate parts of the array. fn split(self) -> (Self::First, Self::Second); } unsafe impl Split for GenericArray where N: ArrayLength, K: ArrayLength, N: Sub, Diff: ArrayLength, { type First = GenericArray; type Second = GenericArray>; 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 for &'a GenericArray where N: ArrayLength, K: ArrayLength + 'static, N: Sub, Diff: ArrayLength, { type First = &'a GenericArray; type Second = &'a GenericArray>; 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 for &'a mut GenericArray where N: ArrayLength, K: ArrayLength + 'static, N: Sub, Diff: ArrayLength, { type First = &'a mut GenericArray; type Second = &'a mut GenericArray>; 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: GenericSequence where M: ArrayLength, { /// Sequence to be concatenated with `self` type Rest: GenericSequence; /// Resulting sequence formed by the concatenation. type Output: GenericSequence; /// Concatenate, or join, two sequences. fn concat(self, rest: Self::Rest) -> Self::Output; } unsafe impl Concat for GenericArray where N: ArrayLength + Add, M: ArrayLength, Sum: ArrayLength, { type Rest = GenericArray; type Output = GenericArray>; fn concat(self, rest: Self::Rest) -> Self::Output { let mut output: MaybeUninit = 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() } } }