use std::error::Error;
use std::fmt::{self, Write};
#[cfg(feature = "admin-service")]
use serde::de;
#[cfg(feature = "admin-service")]
use serde::{Deserializer, Serializer};
pub fn to_hex(bytes: &[u8]) -> String {
let mut buf = String::new();
for b in bytes {
write!(&mut buf, "{:02x}", b).expect("Unable to write to string");
}
buf
}
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)
}
#[cfg(feature = "admin-service")]
pub fn as_hex<S>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&to_hex(data))
}
#[cfg(feature = "admin-service")]
pub fn deserialize_hex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
struct DeserializeHex;
impl<'de> de::Visitor<'de> for DeserializeHex {
type Value = Vec<u8>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a hex string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
match parse_hex(v) {
Ok(vec) => Ok(vec),
Err(err) => Err(de::Error::custom(err)),
}
}
}
deserializer.deserialize_any(DeserializeHex)
}
#[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(|err| &**err 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(feature = "admin-service")]
#[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());
assert_eq!(
"abcdef",
&to_hex(&parse_hex("abcdef").expect("unable to parse hex for round trip"))
);
assert_eq!(
"012345",
&to_hex(&parse_hex("012345").expect("unable to parse hex for round trip"))
);
let empty: Vec<u8> = Vec::with_capacity(0);
assert_eq!(empty, parse_hex("").expect("unable to parse empty"));
}
}