Skip to main content

lexe_std/
array.rs

1//! Small helper functions for `[u8; N]` arrays.
2
3/// `const` pad an `M`-byte array with zeroes, so that it's `N` bytes long.
4// TODO(phlip9): should be an extension trait method, but rust doesn't allow
5// const trait fns yet.
6pub const fn pad<const N: usize, const M: usize>(input: [u8; M]) -> [u8; N] {
7    assert!(N >= M);
8
9    let mut out = [0u8; N];
10    let mut idx = 0;
11    loop {
12        if idx >= M {
13            break;
14        }
15        out[idx] = input[idx];
16        idx += 1;
17    }
18    out
19}
20
21/// Copies of nightly-only functions for `[u8; N]`.
22// TODO(phlip9): remove functions as they stabilize.
23pub trait ArrayExt<const N: usize> {
24    /// Divides one array reference into two at an index.
25    ///
26    /// The first will contain all indices from `[0, M)` (excluding
27    /// the index `M` itself) and the second will contain all
28    /// indices from `[M, N)` (excluding the index `N` itself).
29    fn split_array_ref_stable<const M: usize>(&self) -> (&[u8; M], &[u8]);
30
31    /// Divides one array reference into two at an index from the end.
32    ///
33    /// The first will contain all indices from `[0, N - M)` (excluding
34    /// the index `N - M` itself) and the second will contain all
35    /// indices from `[N - M, N)` (excluding the index `N` itself).
36    fn rsplit_array_ref_stable<const M: usize>(&self) -> (&[u8], &[u8; M]);
37}
38
39impl<const N: usize> ArrayExt<N> for [u8; N] {
40    #[inline]
41    fn split_array_ref_stable<const M: usize>(&self) -> (&[u8; M], &[u8]) {
42        self[..].split_first_chunk::<M>().unwrap()
43    }
44
45    #[inline]
46    fn rsplit_array_ref_stable<const M: usize>(&self) -> (&[u8], &[u8; M]) {
47        self[..].split_last_chunk::<M>().unwrap()
48    }
49}
50
51#[cfg(test)]
52mod test {
53    use crate::array;
54
55    #[test]
56    fn test_pad() {
57        let input = *b"hello";
58        let actual = array::pad(input);
59        let expected = *b"hello\x00\x00\x00\x00\x00";
60        assert_eq!(actual, expected);
61
62        let actual = array::pad(input);
63        let expected = *b"hello";
64        assert_eq!(actual, expected);
65    }
66}