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)}
    }
}