Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  sequence.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

//! 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()
        }
    }
}

[ Dauer der Verarbeitung: 0.36 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge