Skip to main content

serde_human_bytes/
de.rs

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