alloy_primitives/bits/
serde.rs

1use 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        // serialize in checksum format
121        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}