use super::*;
use core::mem::MaybeUninit;
use core::ops::{Add, Div, Mul, Sub};
use core::ptr;
use typenum::operator_aliases::*;
pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
type Length: ArrayLength;
type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
fn generate<F>(f: F) -> Self::Sequence
where
F: FnMut(usize) -> T;
#[cfg_attr(not(feature = "internals"), doc(hidden))]
#[inline(always)]
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>,
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).map(|(l, right_value)| {
let left_value = ptr::read(l);
*left_position += 1;
f(left_value, right_value)
}))
}
}
#[cfg_attr(not(feature = "internals"), doc(hidden))]
#[inline(always)]
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>,
F: FnMut(Lhs::Item, Self::Item) -> U,
{
FromIterator::from_iter(lhs.into_iter().zip(self).map(|(l, r)| f(l, r)))
}
}
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(always)]
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(always)]
fn generate<F>(f: F) -> Self::Sequence
where
F: FnMut(usize) -> T,
{
S::generate(f)
}
}
pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> {
type Longer: Shorten<T, Shorter = Self>;
fn append(self, last: T) -> Self::Longer;
fn prepend(self, first: T) -> Self::Longer;
}
pub unsafe trait Shorten<T>: Sized + GenericSequence<T> {
type Shorter: Lengthen<T, Longer = Self>;
fn pop_back(self) -> (Self::Shorter, T);
fn pop_front(self) -> (T, Self::Shorter);
}
unsafe impl<T, N: ArrayLength> Lengthen<T> for GenericArray<T, N>
where
N: Add<B1>,
Add1<N>: ArrayLength,
Add1<N>: Sub<B1, Output = N>,
Sub1<Add1<N>>: ArrayLength,
{
type Longer = GenericArray<T, Add1<N>>;
#[inline]
fn append(self, last: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
let out_ptr = longer.as_mut_ptr() as *mut Self;
unsafe {
ptr::write(out_ptr, self);
ptr::write(out_ptr.add(1) as *mut T, last);
longer.assume_init()
}
}
#[inline]
fn prepend(self, first: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
let out_ptr = longer.as_mut_ptr() as *mut T;
unsafe {
ptr::write(out_ptr, first);
ptr::write(out_ptr.add(1) as *mut Self, self);
longer.assume_init()
}
}
}
unsafe impl<T, N: ArrayLength> Shorten<T> for GenericArray<T, N>
where
N: Sub<B1>,
Sub1<N>: ArrayLength,
Sub1<N>: Add<B1, Output = N>,
Add1<Sub1<N>>: ArrayLength,
{
type Shorter = GenericArray<T, Sub1<N>>;
#[inline]
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)
}
}
#[inline]
fn pop_front(self) -> (T, Self::Shorter) {
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)
}
}
}
pub unsafe trait Split<T, K: ArrayLength>: GenericSequence<T> {
type First: GenericSequence<T>;
type Second: GenericSequence<T>;
fn split(self) -> (Self::First, Self::Second);
}
unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
where
N: ArrayLength,
K: ArrayLength,
N: Sub<K>,
Diff<N, K>: ArrayLength,
{
type First = GenericArray<T, K>;
type Second = GenericArray<T, Diff<N, K>>;
#[inline]
fn split(self) -> (Self::First, Self::Second) {
unsafe {
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,
K: ArrayLength,
N: Sub<K>,
Diff<N, K>: ArrayLength,
{
type First = &'a GenericArray<T, K>;
type Second = &'a GenericArray<T, Diff<N, K>>;
#[inline]
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,
K: ArrayLength,
N: Sub<K>,
Diff<N, K>: ArrayLength,
{
type First = &'a mut GenericArray<T, K>;
type Second = &'a mut GenericArray<T, Diff<N, K>>;
#[inline]
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)
}
}
}
pub unsafe trait Concat<T, M: ArrayLength>: GenericSequence<T> {
type Rest: GenericSequence<T, Length = M>;
type Output: GenericSequence<T>;
fn concat(self, rest: Self::Rest) -> Self::Output;
}
unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
where
N: ArrayLength + Add<M>,
M: ArrayLength,
Sum<N, M>: ArrayLength,
{
type Rest = GenericArray<T, M>;
type Output = GenericArray<T, Sum<N, M>>;
#[inline]
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 {
ptr::write(out_ptr, self);
ptr::write(out_ptr.add(1) as *mut _, rest);
output.assume_init()
}
}
}
pub unsafe trait Remove<T, N: ArrayLength>: GenericSequence<T> {
type Output: GenericSequence<T>;
#[inline]
fn remove(self, idx: usize) -> (T, Self::Output) {
assert!(
idx < N::USIZE,
"Index out of bounds: the len is {} but the index is {}",
N::USIZE,
idx
);
unsafe { self.remove_unchecked(idx) }
}
fn swap_remove(self, idx: usize) -> (T, Self::Output) {
assert!(
idx < N::USIZE,
"Index out of bounds: the len is {} but the index is {}",
N::USIZE,
idx
);
unsafe { self.swap_remove_unchecked(idx) }
}
unsafe fn remove_unchecked(self, idx: usize) -> (T, Self::Output);
unsafe fn swap_remove_unchecked(self, idx: usize) -> (T, Self::Output);
}
unsafe impl<T, N> Remove<T, N> for GenericArray<T, N>
where
N: ArrayLength + Sub<B1>,
Sub1<N>: ArrayLength,
{
type Output = GenericArray<T, Sub1<N>>;
#[inline]
unsafe fn remove_unchecked(self, idx: usize) -> (T, Self::Output) {
if idx >= N::USIZE || N::USIZE == 0 {
core::hint::unreachable_unchecked();
}
let mut array = ManuallyDrop::new(self);
let dst = array.as_mut_ptr().add(idx);
let removed = ptr::read(dst);
ptr::copy(dst.add(1), dst, N::USIZE - idx - 1);
(removed, mem::transmute_copy(&array))
}
#[inline]
unsafe fn swap_remove_unchecked(self, idx: usize) -> (T, Self::Output) {
if idx >= N::USIZE || N::USIZE == 0 {
core::hint::unreachable_unchecked();
}
let mut array = ManuallyDrop::new(self);
array.swap(idx, N::USIZE - 1);
let removed = ptr::read(array.as_ptr().add(N::USIZE - 1));
(removed, mem::transmute_copy(&array))
}
}
pub unsafe trait Flatten<T, N, M>: GenericSequence<GenericArray<T, N>, Length = M>
where
N: ArrayLength + Mul<M>,
Prod<N, M>: ArrayLength,
{
type Output: GenericSequence<T, Length = Prod<N, M>>;
fn flatten(self) -> Self::Output;
}
pub unsafe trait Unflatten<T, NM, N>: GenericSequence<T, Length = NM>
where
NM: ArrayLength + Div<N>,
N: ArrayLength,
Quot<NM, N>: ArrayLength,
{
type Output: GenericSequence<GenericArray<T, N>, Length = Quot<NM, N>>;
fn unflatten(self) -> Self::Output;
}
unsafe impl<T, N, M> Flatten<T, N, M> for GenericArray<GenericArray<T, N>, M>
where
N: ArrayLength + Mul<M>,
M: ArrayLength,
Prod<N, M>: ArrayLength,
{
type Output = GenericArray<T, Prod<N, M>>;
#[inline(always)]
fn flatten(self) -> Self::Output {
unsafe { crate::const_transmute(self) }
}
}
unsafe impl<'a, T, N, M> Flatten<T, N, M> for &'a GenericArray<GenericArray<T, N>, M>
where
N: ArrayLength + Mul<M>,
M: ArrayLength,
Prod<N, M>: ArrayLength,
{
type Output = &'a GenericArray<T, Prod<N, M>>;
#[inline(always)]
fn flatten(self) -> Self::Output {
unsafe { mem::transmute(self) }
}
}
unsafe impl<'a, T, N, M> Flatten<T, N, M> for &'a mut GenericArray<GenericArray<T, N>, M>
where
N: ArrayLength + Mul<M>,
M: ArrayLength,
Prod<N, M>: ArrayLength,
{
type Output = &'a mut GenericArray<T, Prod<N, M>>;
#[inline(always)]
fn flatten(self) -> Self::Output {
unsafe { mem::transmute(self) }
}
}
unsafe impl<T, NM, N> Unflatten<T, NM, N> for GenericArray<T, NM>
where
NM: ArrayLength + Div<N>,
N: ArrayLength,
Quot<NM, N>: ArrayLength,
{
type Output = GenericArray<GenericArray<T, N>, Quot<NM, N>>;
#[inline(always)]
fn unflatten(self) -> Self::Output {
unsafe { crate::const_transmute(self) }
}
}
unsafe impl<'a, T, NM, N> Unflatten<T, NM, N> for &'a GenericArray<T, NM>
where
NM: ArrayLength + Div<N>,
N: ArrayLength,
Quot<NM, N>: ArrayLength,
{
type Output = &'a GenericArray<GenericArray<T, N>, Quot<NM, N>>;
#[inline(always)]
fn unflatten(self) -> Self::Output {
unsafe { mem::transmute(self) }
}
}
unsafe impl<'a, T, NM, N> Unflatten<T, NM, N> for &'a mut GenericArray<T, NM>
where
NM: ArrayLength + Div<N>,
N: ArrayLength,
Quot<NM, N>: ArrayLength,
{
type Output = &'a mut GenericArray<GenericArray<T, N>, Quot<NM, N>>;
#[inline(always)]
fn unflatten(self) -> Self::Output {
unsafe { mem::transmute(self) }
}
}