cl_array_ext/
lib.rs

1//! Some array extensions that really have no purpose other than to make me feel accomplisheds
2
3#![no_std]
4#![allow(incomplete_features)]
5#![feature(generic_const_exprs, ptr_metadata)]
6#![warn(clippy::pedantic, missing_docs)]
7
8mod slice;
9pub use slice::*;
10
11/// Trait that extends upon [array]
12pub trait ArrayExt<T, const N: usize>: Sized {
13    /// Split an array into two smaller arrays
14    ///
15    /// ```
16    /// use cl_array_ext::ArrayExt;
17    /// let (a, b) = [1_i32, 2, 3, 4, 5].array_split_at::<3>();
18    /// assert_eq!(a, [1, 2, 3]);
19    /// assert_eq!(b, [4, 5]);
20    /// ```
21    fn array_split_at<const M: usize>(self) -> ([T; M], [T; N - M])
22    where
23        [T; N - M]: Sized;
24
25    /// Take only M elements out of the array
26    ///
27    /// ```
28    /// use cl_array_ext::ArrayExt;
29    /// let a = [1, 2, 3, 4, 5].truncate::<3>();
30    /// assert_eq!(a, [1, 2, 3]);
31    /// ```
32    fn truncate<const M: usize>(self) -> [T; M]
33    where
34        [T; N - M]: Sized,
35    {
36        self.array_split_at().0
37    }
38
39    /// Join two arrays into one larger array
40    ///
41    /// ```
42    /// use cl_array_ext::ArrayExt;
43    /// let a = [1_i32, 2, 3].append([4, 5]);
44    /// assert_eq!(a, [1, 2, 3, 4, 5]);
45    /// ```
46    fn append<const M: usize>(self, other: [T; M]) -> [T; N + M];
47}
48
49impl<T, const N: usize> ArrayExt<T, N> for [T; N] {
50    fn array_split_at<const M: usize>(self) -> ([T; M], [T; N - M])
51    where
52        [T; N - M]: Sized,
53    {
54        let arr = core::mem::ManuallyDrop::new(self).as_ptr();
55        unsafe {
56            (
57                core::ptr::read(arr.add(0).cast()),
58                core::ptr::read(arr.add(M).cast()),
59            )
60        }
61    }
62
63    fn append<const M: usize>(self, other: [T; M]) -> [T; N + M] {
64        let arr_a = core::mem::ManuallyDrop::new(self).as_ptr();
65        let arr_b = core::mem::ManuallyDrop::new(other).as_ptr();
66        let mut arr_c = core::mem::MaybeUninit::<[T; N + M]>::uninit();
67        let p = arr_c.as_mut_ptr().cast::<T>();
68
69        unsafe {
70            core::ptr::copy(arr_a, p.add(0), N);
71            core::ptr::copy(arr_b, p.add(N), M);
72
73            core::mem::MaybeUninit::assume_init(arr_c)
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use crate::ArrayExt;
81
82    #[test]
83    fn split_at() {
84        let (a, b) = [1, 2, 3, 4, 5].array_split_at::<3>();
85        assert_eq!(a, [1, 2, 3]);
86        assert_eq!(b, [4, 5]);
87    }
88
89    #[test]
90    fn append() {
91        let a = [1, 2, 3].append([4, 5]);
92
93        assert_eq!(a, [1, 2, 3, 4, 5]);
94    }
95}