array_trait/as_array.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use slice_trait::AsSlice;
#[const_trait]
pub trait AsArray: ~const AsSlice
{
/// Length of array as compile-time constant
///
/// ## Example 1: Length
/// [Array::LENGTH](Array::LENGTH) will always equal the actual length of the array.
///
/// ```rust
/// use array_trait::*;
///
/// const L: usize = 4;
///
/// let array: [f32; L] = [1.0, 2.0, 3.0, 4.0];
///
/// assert_eq!(<[f32; L]>::LENGTH, L);
/// assert_eq!(<[f32; L]>::LENGTH, array.len());
/// ```
///
/// ## Example 2: Generic const-expression usage
/// This can be used in const-expressions as shown below.
///
/// ```rust
/// #![feature(generic_const_exprs)]
/// #![feature(iter_array_chunks)]
///
/// use array_trait::*;
///
/// fn first_half<T: Array>(array: T) -> [<T as core::iter::IntoIterator>::Item; T::LENGTH/2]
/// {
/// array.into_iter().array_chunks().next().unwrap()
/// }
///
/// assert_eq!(first_half([1.0, 2.0, 3.0, 4.0]), [1.0, 2.0]);
/// ```
const LENGTH: usize;
/// Returns self as an array-slice
///
/// Similar to [Array::into_array](Array::into_array), but is passed by reference.
///
/// Useful in the case where a trait is implemented using a generic bound to the [Array](Array) trait.
/// In this case, the compiler does not automatically know that the type with the [Array](Array)-trait is an actual array.
/// This method lets you tell the compiler that you are now working with an actual array, and not just something
/// which implements the trait [Array](Array).
fn as_array(&self) -> &[Self::Item; Self::LENGTH];
/// Returns self as a mutable array-slice
///
/// Similar to [Array::into_array](Array::into_array), but is passed by mutable reference.
///
/// Useful in the case where a trait is implemented using a generic bound to the [Array](Array) trait.
/// In this case, the compiler does not automatically know that the type with the [Array](Array)-trait is an actual array.
/// This method lets you tell the compiler that you are now working with an actual array, and not just something
/// which implements the trait [Array](Array).
fn as_array_mut(&mut self) -> &mut [Self::Item; Self::LENGTH];
}
impl<T, const LENGTH: usize> const AsArray for [T; LENGTH]
{
const LENGTH: usize = LENGTH;
fn as_array(&self) -> &[Self::Item; Self::LENGTH]
{
unsafe {core::mem::transmute(self)}
}
fn as_array_mut(&mut self) -> &mut [Self::Item; Self::LENGTH]
{
unsafe {core::mem::transmute(self)}
}
}
/*#[cfg(feature = "alloc")]
impl<T, const N: usize> const AsArray for alloc::boxed::Box<T>
where
T: ~const AsArray<LENGTH = {N}>,
[(); T::LENGTH]:
{
const LENGTH: usize = N;
fn as_array(&self) -> &[Self::Item; N]
{
let arr = (**self).as_array();
unsafe {core::mem::transmute(arr)}
}
fn as_array_mut(&mut self) -> &mut [Self::Item; N]
{
let arr = (**self).as_array_mut();
unsafe {core::mem::transmute(arr)}
}
}*/
#[cfg(feature = "alloc")]
impl<T, const N: usize> const AsArray for alloc::boxed::Box<[T; N]>
{
const LENGTH: usize = N;
fn as_array(&self) -> &[Self::Item; Self::LENGTH]
{
let a: &[T; N] = self;
unsafe {core::mem::transmute(a)}
}
fn as_array_mut(&mut self) -> &mut [Self::Item; Self::LENGTH]
{
let a: &mut [T; N] = self;
unsafe {core::mem::transmute(a)}
}
}