1#![cfg(feature = "serde")]
4#![cfg_attr(docsrs, doc(cfg(feature = "serde")))]
5
6use crate::{fmt::StackString, nbytes, Bits, Uint};
7use core::{fmt, str};
8use serde::{
9 de::{Error, Unexpected, Visitor},
10 Deserialize, Deserializer, Serialize, Serializer,
11};
12
13const ZERO_STR: &str = "0x0";
16
17impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
18 fn serialize_human<const FULL: bool, S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
19 if BITS <= 8 {
21 self.serialize_human_sized::<FULL, 8, _>(s)
22 } else {
23 self.serialize_human_sized::<FULL, BITS, _>(s)
24 }
25 }
26
27 fn serialize_human_sized<const FULL: bool, const SIZE: usize, S: Serializer>(
28 &self,
29 s: S,
30 ) -> Result<S::Ok, S::Error> {
31 let mut buffer = StackString::<SIZE>::new();
32 self.write_hex::<FULL>(&mut buffer);
33 s.serialize_str(buffer.as_str())
34 }
35
36 fn serialize_binary<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
37 s.serialize_bytes(&self.to_be_bytes_vec())
38 }
39
40 fn write_hex<const FULL: bool>(&self, s: &mut (impl fmt::Write + ?Sized)) {
41 if BITS == 0 {
42 s.write_str(ZERO_STR)
43 } else if FULL {
44 write!(s, "{:#0w$x}", *self, w = 2 + Self::BYTES * 2)
45 } else {
46 write!(s, "{:#x}", *self)
47 }
48 .unwrap();
49 }
50}
51
52impl<const BITS: usize, const LIMBS: usize> Serialize for Uint<BITS, LIMBS> {
57 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
58 if serializer.is_human_readable() {
59 self.serialize_human::<false, _>(serializer)
60 } else {
61 self.serialize_binary(serializer)
62 }
63 }
64}
65
66impl<'de, const BITS: usize, const LIMBS: usize> Deserialize<'de> for Uint<BITS, LIMBS> {
71 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
72 if deserializer.is_human_readable() {
73 deserializer.deserialize_any(HrVisitor)
74 } else {
75 deserializer.deserialize_bytes(ByteVisitor)
76 }
77 }
78}
79
80impl<const BITS: usize, const LIMBS: usize> Serialize for Bits<BITS, LIMBS> {
81 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
82 if serializer.is_human_readable() {
83 self.as_uint().serialize_human::<true, _>(serializer)
84 } else {
85 self.as_uint().serialize_binary(serializer)
86 }
87 }
88}
89
90impl<'de, const BITS: usize, const LIMBS: usize> Deserialize<'de> for Bits<BITS, LIMBS> {
91 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
92 Uint::deserialize(deserializer).map(Self::from)
93 }
94}
95
96struct HrVisitor<const BITS: usize, const LIMBS: usize>;
100
101impl<const BITS: usize, const LIMBS: usize> Visitor<'_> for HrVisitor<BITS, LIMBS> {
102 type Value = Uint<BITS, LIMBS>;
103
104 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(formatter, "a {} byte hex string", nbytes(BITS))
106 }
107
108 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
109 Uint::try_from(v).map_err(|_| Error::invalid_value(Unexpected::Unsigned(v), &self))
110 }
111
112 fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
113 Uint::try_from(v).map_err(Error::custom)
115 }
116
117 fn visit_str<E: Error>(self, value: &str) -> Result<Self::Value, E> {
118 if value == ZERO_STR {
120 return Ok(Uint::<BITS, LIMBS>::ZERO);
121 }
122 if BITS == 0 {
125 return Err(Error::invalid_value(Unexpected::Str(value), &self));
126 }
127
128 value
129 .parse()
130 .map_err(|_| Error::invalid_value(Unexpected::Str(value), &self))
131 }
132}
133
134struct ByteVisitor<const BITS: usize, const LIMBS: usize>;
136
137impl<const BITS: usize, const LIMBS: usize> Visitor<'_> for ByteVisitor<BITS, LIMBS> {
138 type Value = Uint<BITS, LIMBS>;
139
140 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
141 write!(formatter, "{BITS} bits of binary data in big endian order")
142 }
143
144 fn visit_bytes<E: Error>(self, value: &[u8]) -> Result<Self::Value, E> {
145 if value.len() != nbytes(BITS) {
146 return Err(Error::invalid_length(value.len(), &self));
147 }
148 Uint::try_from_be_slice(value).ok_or_else(|| {
149 Error::invalid_value(
150 Unexpected::Other(&format!("too large for Uint<{BITS}>")),
151 &self,
152 )
153 })
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160 use crate::{const_for, nlimbs};
161 use proptest::proptest;
162
163 #[allow(unused_imports)]
164 use alloc::vec::Vec;
165
166 #[test]
167 fn test_serde_human_readable() {
168 const_for!(BITS in SIZES {
169 const LIMBS: usize = nlimbs(BITS);
170 proptest!(|(value: Uint<BITS, LIMBS>)| {
171 let s = format!("U{BITS} => {value}");
172 let serialized = serde_json::to_string(&value).expect(&s);
173 let deserialized = serde_json::from_str::<Uint<BITS, LIMBS>>(&serialized).expect(&s);
174 assert_eq!(value, deserialized);
175 });
176 proptest!(|(value: Bits<BITS, LIMBS>)| {
177 let serialized = serde_json::to_string(&value).unwrap();
178 let deserialized = serde_json::from_str::<Bits<BITS, LIMBS>>(&serialized).unwrap();
179 assert_eq!(value, deserialized);
180 });
181 });
182 }
183
184 #[test]
185 fn test_human_readable_de() {
186 let jason = r#"[
187 1,
188 "0x1",
189 "0o1",
190 "0b1"
191 ]"#;
192 let numbers: Vec<Uint<1, 1>> = serde_json::from_str(jason).unwrap();
193 uint! {
194 assert_eq!(numbers, vec![1_U1, 1_U1, 1_U1, 1_U1]);
195 }
196
197 let jason = r#"[
198 "",
199 "0x",
200 "0o",
201 "0b"
202 ]"#;
203 let numbers: Vec<Uint<1, 1>> = serde_json::from_str(jason).unwrap();
204 uint! {
205 assert_eq!(numbers, vec![0_U1, 0_U1, 0_U1, 0_U1]);
206 }
207 }
208
209 #[test]
210 fn test_serde_machine_readable() {
211 const_for!(BITS in SIZES {
212 const LIMBS: usize = nlimbs(BITS);
213 proptest!(|(value: Uint<BITS, LIMBS>)| {
214 let serialized = bincode::serialize(&value).unwrap();
215 let deserialized = bincode::deserialize::<Uint<BITS, LIMBS>>(&serialized[..]).unwrap();
216 assert_eq!(value, deserialized);
217 });
218 proptest!(|(value: Bits<BITS, LIMBS>)| {
219 let serialized = bincode::serialize(&value).unwrap();
220 let deserialized = bincode::deserialize::<Bits<BITS, LIMBS>>(&serialized[..]).unwrap();
221 assert_eq!(value, deserialized);
222 });
223 });
224 }
225
226 #[test]
227 fn test_serde_invalid_size_error() {
228 const_for!(BITS in SIZES {
231 const LIMBS: usize = nlimbs(BITS);
232 let value = Uint::<BITS, LIMBS>::MAX;
233 let mut serialized = serde_json::to_string(&value).unwrap();
234
235 assert_eq!(&serialized[..3], "\"0x");
237 assert_eq!(&serialized[serialized.len() - 1..], "\"");
239
240 serialized.pop();
242 serialized.push('0');
243 serialized.push('"');
244 let deserialized = serde_json::from_str::<Uint<BITS, LIMBS>>(&serialized);
245 assert!(deserialized.is_err(), "U{BITS} {serialized} => {deserialized:?}");
246 });
247 }
248}