Skip to main content

zeppelin_embed/format/
golden.rs

1//! Helpers shared by byte-exact golden-fixture tests.
2
3/// Decodes ASCII hexadecimal while rejecting malformed fixture text.
4pub fn decode_hex(text: &str) -> Result<Vec<u8>, HexError> {
5    let compact = text.bytes().filter(|byte| !byte.is_ascii_whitespace());
6    let mut high = None;
7    let mut bytes = Vec::new();
8    for byte in compact {
9        let nibble = match byte {
10            b'0'..=b'9' => byte - b'0',
11            b'a'..=b'f' => byte - b'a' + 10,
12            b'A'..=b'F' => byte - b'A' + 10,
13            _ => return Err(HexError::InvalidDigit(byte)),
14        };
15        if let Some(first) = high.take() {
16            bytes.push((first << 4) | nibble);
17        } else {
18            high = Some(nibble);
19        }
20    }
21    if high.is_some() {
22        return Err(HexError::OddLength);
23    }
24    Ok(bytes)
25}
26
27/// Malformed textual golden fixture.
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29pub enum HexError {
30    /// The fixture contained an odd number of hexadecimal nibbles.
31    OddLength,
32    /// The fixture contained a non-hexadecimal byte.
33    InvalidDigit(u8),
34}
35
36impl std::fmt::Display for HexError {
37    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        match self {
39            Self::OddLength => formatter.write_str("golden hex has an odd number of nibbles"),
40            Self::InvalidDigit(byte) => {
41                write!(formatter, "golden hex contains invalid byte {byte}")
42            }
43        }
44    }
45}
46
47impl std::error::Error for HexError {}