use std::error::Error;
use std::fmt;
pub fn parse_hex(hex: &str) -> Result<Vec<u8>, HexError> {
if hex.len() % 2 != 0 {
return Err(HexError {
context: format!("{} is not valid hex: odd number of digits", hex),
source: None,
});
}
let mut res = vec![];
for i in (0..hex.len()).step_by(2) {
res.push(
u8::from_str_radix(&hex[i..i + 2], 16).map_err(|err| HexError {
context: format!("{} contains invalid hex", hex),
source: Some(Box::new(err)),
})?,
);
}
Ok(res)
}
#[derive(Debug)]
pub struct HexError {
context: String,
source: Option<Box<dyn Error + Send>>,
}
impl Error for HexError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.source.as_ref().map(|e| &**e as &(dyn Error + 'static))
}
}
impl fmt::Display for HexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref err) = self.source {
write!(f, "{}: {}", self.context, err)
} else {
f.write_str(&self.context)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_hex() {
assert_eq!(
vec![00u8, 10u8],
parse_hex("000a").expect("unable to parse 000a")
);
assert_eq!(
vec![01u8, 99u8, 255u8],
parse_hex("0163ff").expect("unable to parse 0163ff")
);
assert!(parse_hex("0").is_err());
assert!(parse_hex("0G").is_err());
let empty: Vec<u8> = Vec::with_capacity(0);
assert_eq!(empty, parse_hex("").expect("unable to parse empty"));
}
}