alloy_primitives/bits/
serde.rs1use super::{Address, FixedBytes};
2use core::fmt;
3use serde::{
4 de::{self, Visitor},
5 Deserialize, Deserializer, Serialize, Serializer,
6};
7
8impl Serialize for Address {
9 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
10 where
11 S: Serializer,
12 {
13 if serializer.is_human_readable() {
14 let checksum_address = self.to_checksum_buffer(None);
15 serializer.serialize_str(checksum_address.as_str())
16 } else {
17 serializer.serialize_bytes(self.as_slice())
18 }
19 }
20}
21
22impl<'de> Deserialize<'de> for Address {
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: Deserializer<'de>,
26 {
27 Deserialize::deserialize(deserializer).map(Self)
28 }
29}
30
31impl<const N: usize> Serialize for FixedBytes<N> {
32 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
33 if serializer.is_human_readable() {
34 let mut buf = hex::Buffer::<N, true>::new();
35 serializer.serialize_str(buf.format(&self.0))
36 } else {
37 serializer.serialize_bytes(self.as_slice())
38 }
39 }
40}
41
42impl<'de, const N: usize> Deserialize<'de> for FixedBytes<N> {
43 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
44 struct FixedVisitor<const N: usize>;
45
46 impl<'de, const N: usize> Visitor<'de> for FixedVisitor<N> {
47 type Value = FixedBytes<N>;
48
49 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(
51 formatter,
52 "{} bytes, represented as a hex string of length {}, an array of u8, or raw bytes",
53 N,
54 N * 2
55 )
56 }
57
58 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
59 FixedBytes::try_from(v).map_err(de::Error::custom)
60 }
61
62 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
63 let len_error =
64 |i| de::Error::invalid_length(i, &format!("exactly {N} bytes").as_str());
65 let mut bytes = [0u8; N];
66
67 for (i, byte) in bytes.iter_mut().enumerate() {
68 *byte = seq.next_element()?.ok_or_else(|| len_error(i))?;
69 }
70
71 if let Ok(Some(_)) = seq.next_element::<u8>() {
72 return Err(len_error(N + 1));
73 }
74
75 Ok(FixedBytes(bytes))
76 }
77
78 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
79 <FixedBytes<N> as hex::FromHex>::from_hex(v).map_err(de::Error::custom)
80 }
81 }
82
83 if deserializer.is_human_readable() {
84 deserializer.deserialize_any(FixedVisitor::<N>)
85 } else {
86 deserializer.deserialize_bytes(FixedVisitor::<N>)
87 }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use core::str::FromStr;
94
95 use super::*;
96 use alloc::string::ToString;
97 use serde::Deserialize;
98
99 #[derive(Debug, Deserialize)]
100 struct TestCase<const N: usize> {
101 fixed: FixedBytes<N>,
102 }
103
104 #[test]
105 fn serde() {
106 let bytes = FixedBytes([0, 0, 0, 0, 1, 35, 69, 103, 137, 171, 205, 239]);
107 let ser = serde_json::to_string(&bytes).unwrap();
108 assert_eq!(ser, "\"0x000000000123456789abcdef\"");
109 assert_eq!(serde_json::from_str::<FixedBytes<12>>(&ser).unwrap(), bytes);
110
111 let val = serde_json::to_value(bytes).unwrap();
112 assert_eq!(val, serde_json::json! {"0x000000000123456789abcdef"});
113 assert_eq!(serde_json::from_value::<FixedBytes<12>>(val).unwrap(), bytes);
114 }
115
116 #[test]
117 fn serde_address() {
118 let address = Address::from_str("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359").unwrap();
119 let ser = serde_json::to_string(&address).unwrap();
120 assert_eq!(ser, "\"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359\"");
122 }
123
124 #[test]
125 fn serde_num_array() {
126 let json = serde_json::json! {{"fixed": [0,1,2,3,4]}};
127
128 assert_eq!(
129 serde_json::from_value::<TestCase<5>>(json.clone()).unwrap().fixed,
130 FixedBytes([0, 1, 2, 3, 4])
131 );
132
133 let e = serde_json::from_value::<TestCase<4>>(json).unwrap_err();
134 let es = e.to_string();
135 assert!(es.contains("invalid length 5, expected exactly 4 bytes"), "{es}");
136 }
137
138 #[test]
139 fn test_bincode_roundtrip() {
140 let bytes = FixedBytes([0, 0, 0, 0, 1, 35, 69, 103, 137, 171, 205, 239]);
141
142 let bin = bincode::serialize(&bytes).unwrap();
143 assert_eq!(bincode::deserialize::<FixedBytes<12>>(&bin).unwrap(), bytes);
144 }
145}