#![deny(missing_docs)]
#![no_std]
extern crate alloc;
use alloc::vec::Vec;
use core::fmt::{self, Display};
use serdapt::{DeserializeWith, SerializeWith};
use serde::{de::Visitor, Deserializer, Serialize, Serializer};
#[non_exhaustive]
pub struct Hex<const UPPERCASE: bool = false> {}
pub type LowHex = Hex<false>;
pub type UpHex = Hex<true>;
impl<const UPPERCASE: bool> Hex<UPPERCASE> {
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: ?Sized,
S: Serializer,
Self: SerializeWith<T>,
{
Self::serialize_with(value, serializer)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
Self: DeserializeWith<'de, T>,
{
Self::deserialize_with(deserializer)
}
}
impl<T> SerializeWith<T> for Hex<false>
where
T: AsRef<[u8]>,
{
fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
Serialize::serialize(&hex::encode(value), serializer)
}
}
impl<T> SerializeWith<T> for Hex<true>
where
T: AsRef<[u8]>,
{
fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
Serialize::serialize(&hex::encode_upper(value), serializer)
}
}
impl<'de, const U: bool, T> DeserializeWith<'de, T> for Hex<U>
where
T: TryFrom<Vec<u8>>,
T::Error: Display,
{
fn deserialize_with<D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(HexVisitor)?;
bytes.try_into().map_err(serde::de::Error::custom)
}
}
struct HexVisitor;
impl Visitor<'_> for HexVisitor {
type Value = Vec<u8>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a hex string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
hex::decode(v).map_err(serde::de::Error::custom)
}
}
#[non_exhaustive]
pub struct HexArray<const UPPERCASE: bool = false> {}
pub type LowHexArray = HexArray<false>;
pub type UpHexArray = HexArray<true>;
impl<const U: bool> HexArray<U> {
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: ?Sized,
S: Serializer,
Self: SerializeWith<T>,
{
Self::serialize_with(value, serializer)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
Self: DeserializeWith<'de, T>,
{
Self::deserialize_with(deserializer)
}
}
impl<T> SerializeWith<T> for HexArray<false>
where
T: AsRef<[u8]>,
{
fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
Serialize::serialize(&hex::encode(value), serializer)
}
}
impl<T> SerializeWith<T> for HexArray<true>
where
T: AsRef<[u8]>,
{
fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
Serialize::serialize(&hex::encode_upper(value), serializer)
}
}
impl<'de, const U: bool, const N: usize> DeserializeWith<'de, [u8; N]> for HexArray<U> {
fn deserialize_with<D>(deserializer: D) -> Result<[u8; N], D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(HexArrayVisitor::<N>)
}
}
struct HexArrayVisitor<const N: usize>;
impl<const N: usize> Visitor<'_> for HexArrayVisitor<N> {
type Value = [u8; N];
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a hex string encoding {N} bytes")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let mut out = [0u8; N];
hex::decode_to_slice(v, &mut out).map_err(|e| match e {
hex::FromHexError::InvalidStringLength => E::invalid_length(v.len() / 2, &self),
_ => E::custom(e),
})?;
Ok(out)
}
}