use crate::lib::*;
use hex::FromHexError;
const HEX_ENCODING_PREFIX: &str = "0x";
#[derive(Debug)]
pub enum HexError {
Hex(FromHexError),
MissingPrefix,
}
impl fmt::Display for HexError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Hex(e) => write!(f, "{e}"),
Self::MissingPrefix => {
write!(f, "missing prefix `{HEX_ENCODING_PREFIX}` when deserializing hex data")
}
}
}
}
impl From<FromHexError> for HexError {
fn from(e: FromHexError) -> Self {
Self::Hex(e)
}
}
#[cfg(feature = "std")]
impl std::error::Error for HexError {}
fn try_bytes_from_hex_str(s: &str) -> Result<Vec<u8>, HexError> {
let target = s.strip_prefix(HEX_ENCODING_PREFIX).ok_or(HexError::MissingPrefix)?;
let data = hex::decode(target)?;
Ok(data)
}
pub mod as_hex {
use super::*;
use serde::Deserialize;
pub fn serialize<S, T: AsRef<[u8]>>(data: T, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let encoding = hex::encode(data.as_ref());
let output = format!("{HEX_ENCODING_PREFIX}{encoding}");
serializer.collect_str(&output)
}
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: serde::Deserializer<'de>,
T: for<'a> TryFrom<&'a [u8]>,
{
let s = <String>::deserialize(deserializer)?;
let data = try_bytes_from_hex_str(&s).map_err(serde::de::Error::custom)?;
let inner = T::try_from(&data)
.map_err(|_| serde::de::Error::custom("could not parse instance from byte data"))?;
Ok(inner)
}
}
#[cfg(test)]
mod test {
use crate::prelude::*;
#[derive(
PartialEq, Eq, Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize,
)]
struct FixedTestStruct {
a: u8,
b: u64,
c: u32,
}
#[derive(
PartialEq, Eq, Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize,
)]
struct VarTestStruct {
a: u16,
b: List<u16, 1024>,
c: u8,
}
#[derive(
PartialEq, Eq, Debug, Default, SimpleSerialize, serde::Serialize, serde::Deserialize,
)]
struct ComplexTestStruct {
a: u16,
b: List<u16, 128>,
c: u8,
d: List<u8, 256>,
e: VarTestStruct,
f: Vector<FixedTestStruct, 4>,
g: Vector<VarTestStruct, 2>,
h: Bitvector<9>,
i: Bitlist<32>,
j: U256,
}
#[test]
fn test_roundtrip() {
let value = ComplexTestStruct {
a: 51972,
b: List::<u16, 128>::try_from(vec![48645]).unwrap(),
c: 46,
d: List::<u8, 256>::try_from(vec![105]).unwrap(),
e: VarTestStruct {
a: 1558,
b: List::<u16, 1024>::try_from(vec![39947]).unwrap(),
c: 65,
},
f: Vector::<FixedTestStruct, 4>::try_from(vec![
FixedTestStruct { a: 70, b: 905948488145107787, c: 2675781419 },
FixedTestStruct { a: 3, b: 12539792087931462647, c: 4719259 },
FixedTestStruct { a: 73, b: 13544872847030609257, c: 2819826618 },
FixedTestStruct { a: 159, b: 16328658841145598323, c: 2375225558 },
])
.unwrap(),
g: Vector::<VarTestStruct, 2>::try_from(vec![
VarTestStruct {
a: 30336,
b: List::<u16, 1024>::try_from(vec![30909]).unwrap(),
c: 240,
},
VarTestStruct {
a: 64263,
b: List::<u16, 1024>::try_from(vec![38121]).unwrap(),
c: 100,
},
])
.unwrap(),
h: Bitvector::try_from(
[true, false, false, true, false, false, false, true, true].as_ref(),
)
.unwrap(),
i: Bitlist::try_from([true, false, true, true].as_ref()).unwrap(),
j: U256::from_bytes_le([12u8; 32]),
};
let json_repr = serde_json::to_value(&value).unwrap();
let roundtrip_value: ComplexTestStruct = serde_json::from_value(json_repr).unwrap();
assert_eq!(value, roundtrip_value);
}
}