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