use nom::{bytes::complete::take_while_m_n, character::is_hex_digit, multi::many1, IResult};
pub fn hex_bytes(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
let (input, bytes) = many1(hex_byte)(input)?;
Ok((input, bytes))
}
fn hex_byte(input: &[u8]) -> IResult<&[u8], u8> {
let (input, digits) = take_while_m_n(2, 2, is_hex_digit)(input)?;
let result = (digits[0] as char).to_digit(16).unwrap_or(0) << 4
| (digits[1] as char).to_digit(16).unwrap_or(0);
Ok((input, result as u8))
}
pub fn hex_u64(input: &[u8]) -> IResult<&[u8], u64> {
let (input, raw_bytes) = take_while_m_n(1, 16, is_hex_digit)(input)?;
let mut value = 0u64;
for digit in raw_bytes {
value <<= 4;
value |= (*digit as char).to_digit(16).unwrap() as u64;
}
Ok((input, value))
}
#[cfg(test)]
mod test {
use super::*;
const EMPTY: &[u8] = &[];
#[test]
fn parse_hex_bytes() {
assert_eq!(
hex_bytes(b"7265736574").unwrap(),
(EMPTY, vec![0x72, 0x65, 0x73, 0x65, 0x74])
);
}
#[test]
fn parse_hex_byte() {
assert_eq!(hex_byte(b"72").unwrap(), (EMPTY, 0x72));
assert_eq!(hex_byte(b"00").unwrap(), (EMPTY, 0x00));
assert_eq!(hex_byte(b"FF").unwrap(), (EMPTY, 0xff));
assert_eq!(hex_byte(b"ab").unwrap(), (EMPTY, 0xab));
assert_eq!(hex_byte(b"853").unwrap(), ("3".as_bytes(), 0x85));
}
#[test]
fn parse_hex_u64() {
assert_eq!(hex_u64(b"0").unwrap(), (EMPTY, 0x0));
assert_eq!(hex_u64(b"00000000").unwrap(), (EMPTY, 0x0));
assert_eq!(
hex_u64(b"00000000000000000").unwrap(),
("0".as_bytes(), 0x0)
);
assert_eq!(
hex_u64(b"1230000000000000").unwrap(),
(EMPTY, 0x1230_0000_0000_0000)
);
}
}