use core::fmt;
use serde::{Deserializer, Serializer, de};
use crate::bytesm::hex_digit;
pub fn serialize<S, const N: usize>(bytes: &[u8; N], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&HexDisplay(bytes))
}
struct HexDisplay<'a>(&'a [u8]);
impl fmt::Display for HexDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in self.0 {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}
pub fn deserialize<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(HexVisitor::<N>)
}
struct HexVisitor<const N: usize>;
impl<'de, const N: usize> de::Visitor<'de> for HexVisitor<N> {
type Value = [u8; N];
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "a hexadecimal string encoding exactly {N} bytes")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
if !value.len().is_multiple_of(2) || value.len() / 2 != N {
return Err(E::invalid_length(value.len(), &self));
}
let mut bytes = [0; N];
let (pairs, _) = value.as_bytes().as_chunks::<2>();
for (byte, pair) in bytes.iter_mut().zip(pairs) {
*byte = (hex_digit(pair[0]).map_err(E::custom)? << 4)
| hex_digit(pair[1]).map_err(E::custom)?;
}
Ok(bytes)
}
}