From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/generic-array/src/sequence.rs | 380 +++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 third_party/rust/generic-array/src/sequence.rs (limited to 'third_party/rust/generic-array/src/sequence.rs') diff --git a/third_party/rust/generic-array/src/sequence.rs b/third_party/rust/generic-array/src/sequence.rs new file mode 100644 index 0000000000..0119d3db67 --- /dev/null +++ b/third_party/rust/generic-array/src/sequence.rs @@ -0,0 +1,380 @@ +//! 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() + } + } +} -- cgit v1.2.3