serde_utils/
u64_hex_be.rs1use serde::de::{self, Error, Visitor};
6use serde::{Deserializer, Serializer};
7use std::fmt;
8
9const BYTES_LEN: usize = 8;
10
11pub struct QuantityVisitor;
12impl<'de> Visitor<'de> for QuantityVisitor {
13 type Value = Vec<u8>;
14
15 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
16 formatter.write_str("a hex string")
17 }
18
19 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
20 where
21 E: de::Error,
22 {
23 if !value.starts_with("0x") {
24 return Err(de::Error::custom("must start with 0x"));
25 }
26
27 let stripped = value.trim_start_matches("0x");
28
29 if stripped.is_empty() {
30 Err(de::Error::custom(format!(
31 "quantity cannot be {}",
32 stripped
33 )))
34 } else if stripped == "0" {
35 Ok(vec![0])
36 } else if stripped.starts_with('0') {
37 Err(de::Error::custom("cannot have leading zero"))
38 } else if stripped.len() % 2 != 0 {
39 hex::decode(format!("0{}", stripped))
40 .map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))
41 } else {
42 hex::decode(stripped).map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))
43 }
44 }
45}
46
47pub fn serialize<S>(num: &u64, serializer: S) -> Result<S::Ok, S::Error>
48where
49 S: Serializer,
50{
51 let raw = hex::encode(num.to_be_bytes());
52 let trimmed = raw.trim_start_matches('0');
53
54 let hex = if trimmed.is_empty() { "0" } else { trimmed };
55
56 serializer.serialize_str(&format!("0x{}", &hex))
57}
58
59pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
60where
61 D: Deserializer<'de>,
62{
63 let decoded = deserializer.deserialize_str(QuantityVisitor)?;
64
65 if decoded.len() > BYTES_LEN {
67 return Err(D::Error::custom(format!(
68 "expected max {} bytes for array, got {}",
69 BYTES_LEN,
70 decoded.len()
71 )));
72 }
73
74 let mut array = [0; BYTES_LEN];
75 array[BYTES_LEN - decoded.len()..].copy_from_slice(&decoded);
76 Ok(u64::from_be_bytes(array))
77}
78
79#[cfg(test)]
80mod test {
81 use serde::{Deserialize, Serialize};
82 use serde_json;
83
84 #[derive(Debug, PartialEq, Serialize, Deserialize)]
85 #[serde(transparent)]
86 struct Wrapper {
87 #[serde(with = "super")]
88 val: u64,
89 }
90
91 #[test]
92 fn encoding() {
93 assert_eq!(
94 &serde_json::to_string(&Wrapper { val: 0 }).unwrap(),
95 "\"0x0\""
96 );
97 assert_eq!(
98 &serde_json::to_string(&Wrapper { val: 1 }).unwrap(),
99 "\"0x1\""
100 );
101 assert_eq!(
102 &serde_json::to_string(&Wrapper { val: 256 }).unwrap(),
103 "\"0x100\""
104 );
105 assert_eq!(
106 &serde_json::to_string(&Wrapper { val: 65 }).unwrap(),
107 "\"0x41\""
108 );
109 assert_eq!(
110 &serde_json::to_string(&Wrapper { val: 1024 }).unwrap(),
111 "\"0x400\""
112 );
113 }
114
115 #[test]
116 fn decoding() {
117 assert_eq!(
118 serde_json::from_str::<Wrapper>("\"0x0\"").unwrap(),
119 Wrapper { val: 0 },
120 );
121 assert_eq!(
122 serde_json::from_str::<Wrapper>("\"0x41\"").unwrap(),
123 Wrapper { val: 65 },
124 );
125 assert_eq!(
126 serde_json::from_str::<Wrapper>("\"0x400\"").unwrap(),
127 Wrapper { val: 1024 },
128 );
129 serde_json::from_str::<Wrapper>("\"0x\"").unwrap_err();
130 serde_json::from_str::<Wrapper>("\"0x0400\"").unwrap_err();
131 serde_json::from_str::<Wrapper>("\"400\"").unwrap_err();
132 serde_json::from_str::<Wrapper>("\"ff\"").unwrap_err();
133 }
134}