serde_human_bytes/
de.rs

1use crate::{ByteArray, Bytes};
2use core::convert::TryInto;
3use core::fmt;
4use core::marker::PhantomData;
5use serde::de::{Error, Visitor};
6use serde::Deserializer;
7
8use crate::ByteBuf;
9
10use core::cmp;
11
12use alloc::borrow::Cow;
13use alloc::boxed::Box;
14use alloc::string::String;
15use alloc::vec::Vec;
16
17use serde::de::SeqAccess;
18
19pub(crate) fn deserialize_hex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
20where
21    D: Deserializer<'de>,
22{
23    let s: String = serde::Deserialize::deserialize(deserializer)?;
24    hex::decode(s).map_err(D::Error::custom)
25}
26
27/// Types that can be deserialized via `#[serde(with = "serde_human_bytes")]`.
28pub trait Deserialize<'de>: Sized {
29    #[allow(missing_docs)]
30    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31    where
32        D: Deserializer<'de>;
33}
34
35impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] {
36    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
37    where
38        D: Deserializer<'de>,
39    {
40        if deserializer.is_human_readable() {
41            // Not supported
42            Err(D::Error::custom(
43                "human readable mode is not supported for &[u8]",
44            ))
45        } else {
46            // serde::Deserialize for &[u8] is already optimized, so simply forward to that.
47            serde::Deserialize::deserialize(deserializer)
48        }
49    }
50}
51
52impl<'de> Deserialize<'de> for Vec<u8> {
53    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54    where
55        D: Deserializer<'de>,
56    {
57        if deserializer.is_human_readable() {
58            deserialize_hex(deserializer)
59        } else {
60            Deserialize::deserialize(deserializer).map(ByteBuf::into_vec)
61        }
62    }
63}
64
65impl<'de: 'a, 'a> Deserialize<'de> for &'a Bytes {
66    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67    where
68        D: Deserializer<'de>,
69    {
70        if deserializer.is_human_readable() {
71            Err(D::Error::custom(
72                "human readable mode is not supported for &Bytes",
73            ))
74        } else {
75            // serde::Deserialize for &[u8] is already optimized, so simply forward to that.
76            serde::Deserialize::deserialize(deserializer).map(Bytes::new)
77        }
78    }
79}
80
81impl<'de, const N: usize> Deserialize<'de> for [u8; N] {
82    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
83    where
84        D: Deserializer<'de>,
85    {
86        if deserializer.is_human_readable() {
87            deserialize_hex(deserializer)?
88                .try_into()
89                .map_err(|_| D::Error::custom("invalid array length"))
90        } else {
91            let arr: ByteArray<N> = serde::Deserialize::deserialize(deserializer)?;
92            Ok(*arr)
93        }
94    }
95}
96
97impl<'de, const N: usize> Deserialize<'de> for &'de [u8; N] {
98    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99    where
100        D: Deserializer<'de>,
101    {
102        if deserializer.is_human_readable() {
103            Err(D::Error::custom(
104                "human readable mode is not supported for &[u8; N]",
105            ))
106        } else {
107            let arr: &ByteArray<N> = serde::Deserialize::deserialize(deserializer)?;
108            Ok(arr)
109        }
110    }
111}
112
113impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
114    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
115    where
116        D: Deserializer<'de>,
117    {
118        if deserializer.is_human_readable() {
119            deserialize_hex(deserializer)?
120                .try_into()
121                .map(ByteArray::new)
122                .map_err(|_| D::Error::custom("invalid array length"))
123        } else {
124            // Via the serde::Deserialize impl for ByteArray.
125            serde::Deserialize::deserialize(deserializer)
126        }
127    }
128}
129
130impl<'de: 'a, 'a, const N: usize> Deserialize<'de> for &'a ByteArray<N> {
131    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
132    where
133        D: Deserializer<'de>,
134    {
135        if deserializer.is_human_readable() {
136            Err(D::Error::custom(
137                "human readable mode is not supported for &ByteArray<N>",
138            ))
139        } else {
140            // Via the serde::Deserialize impl for &ByteArray.
141            serde::Deserialize::deserialize(deserializer)
142        }
143    }
144}
145
146impl<'de> Deserialize<'de> for ByteBuf {
147    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148    where
149        D: Deserializer<'de>,
150    {
151        if deserializer.is_human_readable() {
152            deserialize_hex(deserializer).map(ByteBuf::from)
153        } else {
154            // Via the serde::Deserialize impl for ByteBuf.
155            serde::Deserialize::deserialize(deserializer)
156        }
157    }
158}
159
160impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> {
161    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
162    where
163        D: Deserializer<'de>,
164    {
165        struct CowVisitor;
166
167        impl<'de> Visitor<'de> for CowVisitor {
168            type Value = Cow<'de, [u8]>;
169
170            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
171                formatter.write_str("a byte array")
172            }
173
174            fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
175            where
176                E: Error,
177            {
178                Ok(Cow::Borrowed(v))
179            }
180
181            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
182            where
183                E: Error,
184            {
185                Ok(Cow::Borrowed(v.as_bytes()))
186            }
187
188            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
189            where
190                E: Error,
191            {
192                Ok(Cow::Owned(v.to_vec()))
193            }
194
195            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
196            where
197                E: Error,
198            {
199                Ok(Cow::Owned(v.as_bytes().to_vec()))
200            }
201
202            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
203            where
204                E: Error,
205            {
206                Ok(Cow::Owned(v))
207            }
208
209            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
210            where
211                E: Error,
212            {
213                Ok(Cow::Owned(v.into_bytes()))
214            }
215
216            fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
217            where
218                V: SeqAccess<'de>,
219            {
220                let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
221                let mut bytes = Vec::with_capacity(len);
222
223                while let Some(b) = visitor.next_element()? {
224                    bytes.push(b);
225                }
226
227                Ok(Cow::Owned(bytes))
228            }
229        }
230
231        if deserializer.is_human_readable() {
232            deserialize_hex(deserializer).map(Cow::Owned)
233        } else {
234            deserializer.deserialize_bytes(CowVisitor)
235        }
236    }
237}
238
239impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, Bytes> {
240    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
241    where
242        D: Deserializer<'de>,
243    {
244        if deserializer.is_human_readable() {
245            deserialize_hex(deserializer)
246                .map(ByteBuf::from)
247                .map(Cow::Owned)
248        } else {
249            let cow: Cow<[u8]> = Deserialize::deserialize(deserializer)?;
250            match cow {
251                Cow::Borrowed(bytes) => Ok(Cow::Borrowed(Bytes::new(bytes))),
252                Cow::Owned(bytes) => Ok(Cow::Owned(ByteBuf::from(bytes))),
253            }
254        }
255    }
256}
257
258impl<'de> Deserialize<'de> for Box<[u8]> {
259    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
260    where
261        D: Deserializer<'de>,
262    {
263        if deserializer.is_human_readable() {
264            deserialize_hex(deserializer).map(Vec::into_boxed_slice)
265        } else {
266            Deserialize::deserialize(deserializer).map(Vec::into_boxed_slice)
267        }
268    }
269}
270
271impl<'de> Deserialize<'de> for Box<Bytes> {
272    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
273    where
274        D: Deserializer<'de>,
275    {
276        if deserializer.is_human_readable() {
277            deserialize_hex(deserializer)
278                .map(Vec::into_boxed_slice)
279                .map(Into::into)
280        } else {
281            let bytes: Box<[u8]> = Deserialize::deserialize(deserializer)?;
282            Ok(bytes.into())
283        }
284    }
285}
286
287impl<'de, T> Deserialize<'de> for Option<T>
288where
289    T: Deserialize<'de>,
290{
291    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
292    where
293        D: Deserializer<'de>,
294    {
295        struct BytesVisitor<T> {
296            out: PhantomData<T>,
297        }
298
299        impl<'de, T> Visitor<'de> for BytesVisitor<T>
300        where
301            T: Deserialize<'de>,
302        {
303            type Value = Option<T>;
304
305            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
306                f.write_str("optional byte array")
307            }
308
309            fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
310                Ok(None)
311            }
312
313            fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
314                Ok(None)
315            }
316
317            fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
318            where
319                D: Deserializer<'de>,
320            {
321                T::deserialize(deserializer).map(Some)
322            }
323        }
324
325        let visitor = BytesVisitor { out: PhantomData };
326        deserializer.deserialize_option(visitor)
327    }
328}