serde_utils/
fixed_bytes_hex.rs1use crate::hex::PrefixedHexVisitor;
6use serde::de::Error;
7use serde::{Deserializer, Serializer};
8
9macro_rules! bytes_hex {
10 ($num_bytes: tt) => {
11 use super::*;
12
13 const BYTES_LEN: usize = $num_bytes;
14
15 pub fn serialize<S>(bytes: &[u8; BYTES_LEN], serializer: S) -> Result<S::Ok, S::Error>
16 where
17 S: Serializer,
18 {
19 let mut hex_string: String = "0x".to_string();
20 hex_string.push_str(&hex::encode(&bytes));
21
22 serializer.serialize_str(&hex_string)
23 }
24
25 pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; BYTES_LEN], D::Error>
26 where
27 D: Deserializer<'de>,
28 {
29 let decoded = deserializer.deserialize_str(PrefixedHexVisitor)?;
30
31 if decoded.len() != BYTES_LEN {
32 return Err(D::Error::custom(format!(
33 "expected {} bytes for array, got {}",
34 BYTES_LEN,
35 decoded.len()
36 )));
37 }
38
39 let mut array = [0; BYTES_LEN];
40 array.copy_from_slice(&decoded);
41 Ok(array)
42 }
43
44 #[cfg(test)]
45 mod test {
46 use super::*;
47 use serde::{Deserialize, Serialize};
48
49 #[derive(Debug, PartialEq, Serialize, Deserialize)]
50 #[serde(transparent)]
51 struct Wrapper {
52 #[serde(with = "super")]
53 val: [u8; BYTES_LEN],
54 }
55
56 fn generate_string_value(v1: &str, v2: &str) -> String {
57 let mut i = 0;
58 let mut value = String::new();
59 while i < BYTES_LEN * 2 {
60 if i % 2 == 0 {
61 value.push_str(v1);
62 } else {
63 value.push_str(v2);
64 }
65 i += 1;
66 }
67 value
68 }
69
70 #[test]
71 fn encoding() {
72 let zero = "0".repeat(BYTES_LEN * 2);
73 assert_eq!(
74 &serde_json::to_string(&Wrapper {
75 val: [0; BYTES_LEN]
76 })
77 .unwrap(),
78 &format!("\"0x{}\"", zero)
79 );
80
81 assert_eq!(
82 &serde_json::to_string(&Wrapper {
83 val: [123; BYTES_LEN]
84 })
85 .unwrap(),
86 &format!("\"0x{}\"", generate_string_value("7", "b"))
87 );
88
89 let max = "f".repeat(BYTES_LEN * 2);
90 assert_eq!(
91 &serde_json::to_string(&Wrapper {
92 val: [u8::MAX; BYTES_LEN]
93 })
94 .unwrap(),
95 &format!("\"0x{}\"", max)
96 );
97 }
98
99 #[test]
100 fn decoding() {
101 let zero = "0".repeat(BYTES_LEN * 2);
102 assert_eq!(
103 serde_json::from_str::<Wrapper>(&format!("\"0x{}\"", zero)).unwrap(),
104 Wrapper {
105 val: [0; BYTES_LEN]
106 },
107 );
108 assert_eq!(
109 serde_json::from_str::<Wrapper>(&format!(
110 "\"0x{}\"",
111 generate_string_value("7", "b")
112 ))
113 .unwrap(),
114 Wrapper {
115 val: [123; BYTES_LEN]
116 },
117 );
118
119 let max = "f".repeat(BYTES_LEN * 2);
120 assert_eq!(
121 serde_json::from_str::<Wrapper>(&format!("\"0x{}\"", max)).unwrap(),
122 Wrapper {
123 val: [u8::MAX; BYTES_LEN]
124 },
125 );
126
127 serde_json::from_str::<Wrapper>(&format!("\"{}\"", "0".repeat(BYTES_LEN * 2)))
129 .unwrap_err();
130
131 let exceed_max = "f".repeat((BYTES_LEN * 2) + 1);
132 serde_json::from_str::<Wrapper>(&format!("\"0x{}\"", exceed_max)).unwrap_err();
134 }
135 }
136 };
137}
138
139pub mod bytes_4_hex {
140 bytes_hex!(4);
141}
142
143pub mod bytes_8_hex {
144 bytes_hex!(8);
145}