pallet_revive/evm/api/
hex_serde.rs1use alloc::{format, string::String, vec::Vec};
19use alloy_core::hex;
20use serde::{Deserialize, Deserializer, Serializer};
21
22pub trait HexCodec: Sized {
23 type Error;
24 fn to_hex(&self) -> String;
25 fn from_hex(s: String) -> Result<Self, Self::Error>;
26}
27
28macro_rules! impl_hex_codec {
29 ($($t:ty),*) => {
30 $(
31 impl HexCodec for $t {
32 type Error = core::num::ParseIntError;
33 fn to_hex(&self) -> String {
34 format!("0x{:x}", self)
35 }
36 fn from_hex(s: String) -> Result<Self, Self::Error> {
37 <$t>::from_str_radix(s.trim_start_matches("0x"), 16)
38 }
39 }
40 )*
41 };
42}
43
44impl_hex_codec!(u8, u32);
45
46impl<const T: usize> HexCodec for [u8; T] {
47 type Error = hex::FromHexError;
48 fn to_hex(&self) -> String {
49 format!("0x{}", hex::encode(self))
50 }
51 fn from_hex(s: String) -> Result<Self, Self::Error> {
52 let data = hex::decode(s.trim_start_matches("0x"))?;
53 data.try_into().map_err(|_| hex::FromHexError::InvalidStringLength)
54 }
55}
56
57impl HexCodec for Vec<u8> {
58 type Error = hex::FromHexError;
59 fn to_hex(&self) -> String {
60 format!("0x{}", hex::encode(self))
61 }
62 fn from_hex(s: String) -> Result<Self, Self::Error> {
63 hex::decode(s.trim_start_matches("0x"))
64 }
65}
66
67pub fn serialize<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
68where
69 S: Serializer,
70 T: HexCodec,
71{
72 let s = value.to_hex();
73 serializer.serialize_str(&s)
74}
75
76pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
77where
78 D: Deserializer<'de>,
79 T: HexCodec,
80 <T as HexCodec>::Error: core::fmt::Debug,
81{
82 let s = String::deserialize(deserializer)?;
83 let value = T::from_hex(s).map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?;
84 Ok(value)
85}