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