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
use crate::rstd::inlining::*;

use super::*;

impl<const N: usize> Serializable for [u8; N] {
    fn serialize(&self, serializer: &mut dyn Serializer) {
        serializer.write(self)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum ArrayParseError {
    Eof,
    ExtraData(usize),
}

impl Display for ArrayParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Eof => write!(f, "encountered EOF write parsing an array"),
            Self::ExtraData(length) => write!(
                f,
                "encountered extra data of length {length} while parsing an array",
            ),
        }
    }
}

impl Error for ArrayParseError {}

impl From<&[u8]> for ArrayParseError {
    fn from(_value: &[u8]) -> Self {
        Self::Eof
    }
}

impl<const N: usize> AtomicBase for [u8; N] {
    type AParseError = ArrayParseError;
}

impl<const N: usize> ImplMode for [u8; N] {
    type Mode = InliningMode;
}

impl<const N: usize> CInliningAtomic for [u8; N] {
    fn ca_extension_error(tail: &[u8]) -> Self::AParseError {
        ArrayParseError::ExtraData(tail.len())
    }

    fn ca_ideserialize<I: Stream>(stream: I) -> AIParseResult<Self, I> {
        stream.iread_n_const::<N>(ArrayParseError::from_ref)
    }
}

impl<const N: usize> ConstSizeAtomic for [u8; N] {
    const SIZE: usize = N;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn cannot_parse_array() {
        assert_eq!(<[u8; 3]>::parse_slice(&[1, 2, 3]).unwrap(), [1, 2, 3]);
    }

    #[test]
    fn cannot_parse_undersized_slice() {
        assert_eq!(
            <[u8; 2]>::parse_slice(&[0, 0, 0, 0]).unwrap_err(),
            ArrayParseError::ExtraData(2),
        );
    }

    #[test]
    fn cannot_parse_oversized_slice() {
        assert_eq!(
            <[u8; 4]>::parse_slice(&[0, 0]).unwrap_err(),
            ArrayParseError::Eof
        );
    }
}