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

use super::*;

impl Serializable for u64 {
    fn serialize(&self, serializer: &mut dyn Serializer) {
        serializer.write(&self.to_le_bytes());
    }
}

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

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

impl Error for IntParseError {}

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

impl AtomicBase for u64 {
    type AParseError = IntParseError;
}

impl ImplMode for u64 {
    type Mode = InliningMode;
}

impl CInliningAtomic for u64 {
    fn ca_extension_error(tail: &[u8]) -> Self::AParseError {
        IntParseError::ExtraData(tail.len())
    }

    fn ca_ideserialize<I: Stream>(stream: I) -> AIParseResult<Self, I> {
        let (x, stream) = stream.iread_n_const::<8>(IntParseError::from_ref)?;
        Ok((u64::from_le_bytes(x), stream))
    }
}

impl ConstSizeAtomic for u64 {
    const SIZE: usize = 8;
}

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

    #[test]
    fn can_parse_zero() {
        assert_eq!(u64::parse_slice(&[0, 0, 0, 0, 0, 0, 0, 0]).unwrap(), 0);
    }

    #[test]
    fn can_parse_le() {
        assert_eq!(
            u64::parse_slice(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap(),
            0x0807060504030201,
        );
    }

    #[test]
    fn cannot_parse_empty_slice() {
        assert_eq!(u64::parse_slice(&[]).unwrap_err(), IntParseError::Eof);
    }

    #[test]
    fn cannot_parse_undersized_slice() {
        assert_eq!(
            u64::parse_slice(&[0, 0, 0, 0, 0, 0, 0]).unwrap_err(),
            IntParseError::Eof,
        );
    }

    #[test]
    fn cannot_parse_oversized_slice() {
        assert_eq!(
            u64::parse_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap_err(),
            IntParseError::ExtraData(1),
        );
    }
}