pub trait HexExt {
fn to_hex(&self) -> String;
fn from_hex(s: &str) -> Result<Self, HexError> where Self: Sized;
}
impl HexExt for [u8] {
fn to_hex(&self) -> String {
self.iter().map(|b| format!("{:02x}", b)).collect()
}
}
impl HexExt for Vec<u8> {
fn to_hex(&self) -> String {
self.as_slice().to_hex()
}
fn from_hex(s: &str) -> Result<Self, HexError> {
let cleaned: String = s.chars().filter(|c| c.is_ascii_hexdigit()).collect();
if cleaned.len() % 2 != 0 {
return Err(HexError::OddLength);
}
cleaned.as_bytes()
.chunks(2)
.map(|chunk| {
u8::from_str_radix(std::str::from_utf8(chunk).unwrap(), 16)
.map_err(|_| HexError::InvalidCharacter)
})
.collect::<Result<Vec<_>, _>>()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HexError {
OddLength,
InvalidCharacter,
}
impl core::fmt::Display for HexError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
HexError::OddLength => write!(f, "odd number of hex digits"),
HexError::InvalidCharacter => write!(f, "invalid hex character"),
}
}
}
impl core::error::Error for HexError {}