use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{MaybeUninit, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::{mem, ptr, slice}; use typenum::bit::{B0, B1}; use typenum::uint::{UInt, UTerm, Unsigned};
/// Trait making `GenericArray` work, marking types to be used as length of an array pubunsafetrait ArrayLength<T>: Unsigned { /// Associated type representing the array type for the number type ArrayType;
}
unsafeimpl<T> ArrayLength<T> for UTerm { #[doc(hidden)] type ArrayType = [T; 0];
}
/// Internal type used to generate a struct of appropriate size #[allow(dead_code)] #[repr(C)] #[doc(hidden)] pubstruct GenericArrayImplEven<T, U> {
parent1: U,
parent2: U,
_marker: PhantomData<T>,
}
impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
/// Internal type used to generate a struct of appropriate size #[allow(dead_code)] #[repr(C)] #[doc(hidden)] pubstruct GenericArrayImplOdd<T, U> {
parent1: U,
parent2: U,
data: T,
}
/// Creates an array one element at a time using a mutable iterator /// you can write to with `ptr::write`. /// /// Increment the position while iterating to mark off created elements, /// which will be dropped if `into_inner` is not called. #[doc(hidden)] pubstruct ArrayBuilder<T, N: ArrayLength<T>> {
array: MaybeUninit<GenericArray<T, N>>,
position: usize,
}
/// Creates a mutable iterator for writing to the array using `ptr::write`. /// /// Increment the position value given as a mutable reference as you iterate /// to mark how many elements have been created. #[doc(hidden)] #[inline] pubunsafefn iter_position(&mutself) -> (slice::IterMut<T>, &tyle='color:red'>mut usize) {
((&mut *self.array.as_mut_ptr()).iter_mut(), &mutself.position)
}
/// When done writing (assuming all elements have been written to), /// get the inner array. #[doc(hidden)] #[inline] pubunsafefn into_inner(self) -> GenericArray<T, N> { let array = ptr::read(&self.array);
mem::forget(self);
array.assume_init()
}
}
impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> { fn drop(&mutself) { if mem::needs_drop::<T>() { unsafe { for value in &mut (&mut *self.array.as_mut_ptr())[..self.position] {
ptr::drop_in_place(value);
}
}
}
}
}
/// Consumes an array. /// /// Increment the position while iterating and any leftover elements /// will be dropped if position does not go to N #[doc(hidden)] pubstruct ArrayConsumer<T, N: ArrayLength<T>> {
array: ManuallyDrop<GenericArray<T, N>>,
position: usize,
}
/// Creates an iterator and mutable reference to the internal position /// to keep track of consumed elements. /// /// Increment the position as you iterate to mark off consumed elements #[doc(hidden)] #[inline] pubunsafefn iter_position(&mutself) -> (slice::Iter<T>, &e='color:red'>mut usize) {
(self.array.iter(), &mutself.position)
}
}
impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> { fn drop(&mutself) { if mem::needs_drop::<T>() { for value in &mutself.array[self.position..N::USIZE] { unsafe {
ptr::drop_in_place(value);
}
}
}
}
}
impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N> where
N: ArrayLength<T>,
{ type IntoIter = slice::Iter<'a, T>; type Item = &'a T;
fn fold<U, F>(self, init: U, mut f: F) -> U where
F: FnMut(U, T) -> U,
{ unsafe { letmut source = ArrayConsumer::new(self);
let (array_iter, position) = source.iter_position();
array_iter.fold(init, |acc, src| { let value = ptr::read(src);
*position += 1;
f(acc, value)
})
}
}
}
impl<T, N> GenericArray<T, N> where
N: ArrayLength<T>,
{ /// Extracts a slice containing the entire array. #[inline] pubfn as_slice(&self) -> &[T] { self.deref()
}
/// Extracts a mutable slice containing the entire array. #[inline] pubfn as_mut_slice(&mutself) -> &mut [T] { self.deref_mut()
}
/// Converts slice to a generic array reference with inferred length; /// /// Length of the slice must be equal to the length of the array. #[inline] pubfn from_slice(slice: &[T]) -> &GenericArray<T, N> {
slice.into()
}
/// Converts mutable slice to a mutable generic array reference /// /// Length of the slice must be equal to the length of the array. #[inline] pubfn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
slice.into()
}
}
impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> { /// Converts slice to a generic array reference with inferred length; /// /// Length of the slice must be equal to the length of the array. #[inline] fn from(slice: &[T]) -> &GenericArray<T, N> {
assert_eq!(slice.len(), N::USIZE);
unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
}
}
impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> { /// Converts mutable slice to a mutable generic array reference /// /// Length of the slice must be equal to the length of the array. #[inline] fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {
assert_eq!(slice.len(), N::USIZE);
impl<T: Clone, N> GenericArray<T, N> where
N: ArrayLength<T>,
{ /// Construct a `GenericArray` from a slice by cloning its content /// /// Length of the slice must be equal to the length of the array #[inline] pubfn clone_from_slice(list: &[T]) -> GenericArray<T, N> { Self::from_exact_iter(list.iter().cloned())
.expect("Slice must be the same length as the array")
}
}
impl<T, N> GenericArray<T, N> where
N: ArrayLength<T>,
{ /// Creates a new `GenericArray` instance from an iterator with a specific size. /// /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`. pubfn from_exact_iter<I>(iter: I) -> Option<Self> where
I: IntoIterator<Item = T>,
{ letmut iter = iter.into_iter();
// The iterator produced fewer than `N` elements. if *position != N::USIZE { return None;
}
// The iterator produced more than `N` elements. if iter.next().is_some() { return None;
}
}
Some(destination.into_inner())
}
}
}
/// A reimplementation of the `transmute` function, avoiding problems /// when the compiler can't prove equal sizes. #[inline] #[doc(hidden)] pubunsafefn transmute<A, B>(a: A) -> B { let a = ManuallyDrop::new(a);
::core::ptr::read(&*a as *const A as *const B)
}
#[cfg(test)] mod test { // Compile with: // cargo rustc --lib --profile test --release -- // -C target-cpu=native -C opt-level=3 --emit asm // and view the assembly to make sure test_assembly generates // SIMD instructions instead of a naive loop.
#[inline(never)] pubfn black_box<T>(val: T) -> T { use core::{mem, ptr};
let ret = unsafe { ptr::read_volatile(&val) };
mem::forget(val);
ret
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.