1pub const fn concat<T: Copy, const N: usize, const M: usize, const O: usize>(
5 first: [T; N],
6 second: [T; M],
7) -> [T; O] {
8 assert!(O == N + M);
9 crate::const_utils::const_concat_inner(&[&first, &second])
10}
11
12pub const fn pad<const N: usize, const M: usize>(input: [u8; M]) -> [u8; N] {
16 assert!(N >= M);
17
18 let mut out = [0u8; N];
19 let mut idx = 0;
20 loop {
21 if idx >= M {
22 break;
23 }
24 out[idx] = input[idx];
25 idx += 1;
26 }
27 out
28}
29
30pub trait ArrayExt<const N: usize> {
33 fn split_array_ref_stable<const M: usize>(&self) -> (&[u8; M], &[u8]);
39
40 fn rsplit_array_ref_stable<const M: usize>(&self) -> (&[u8], &[u8; M]);
46}
47
48impl<const N: usize> ArrayExt<N> for [u8; N] {
49 #[inline]
50 fn split_array_ref_stable<const M: usize>(&self) -> (&[u8; M], &[u8]) {
51 self[..].split_first_chunk::<M>().unwrap()
52 }
53
54 #[inline]
55 fn rsplit_array_ref_stable<const M: usize>(&self) -> (&[u8], &[u8; M]) {
56 self[..].split_last_chunk::<M>().unwrap()
57 }
58}
59
60#[cfg(test)]
61mod test {
62 use crate::array;
63
64 #[test]
65 fn test_concat() {
66 const ACTUAL: [&str; 3] = array::concat(["a"], ["b", "c"]);
67 assert_eq!(ACTUAL, ["a", "b", "c"]);
68
69 const EMPTY: [&str; 0] = [];
70 const ACTUAL_WITH_EMPTY: [&str; 3] = array::concat(EMPTY, ACTUAL);
71 assert_eq!(ACTUAL_WITH_EMPTY, ACTUAL);
72 }
73
74 #[test]
75 fn test_pad() {
76 let input = *b"hello";
77 let actual = array::pad(input);
78 let expected = *b"hello\x00\x00\x00\x00\x00";
79 assert_eq!(actual, expected);
80
81 let actual = array::pad(input);
82 let expected = *b"hello";
83 assert_eq!(actual, expected);
84 }
85}