bramble_data/
custom.rs

1//! Custom serialization utilities
2
3/// (De)serializes `Option<()>` as either null (for `None`) or true (for `Some(())`).
4pub mod option_unit_as_null_or_true {
5    use serde::{de, ser, Deserialize, Serialize};
6
7    #[doc(hidden)]
8    pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
9    where
10        S: ser::Serializer,
11    {
12        match value {
13            None => ().serialize(ser),
14            Some(()) => true.serialize(ser),
15        }
16    }
17
18    #[doc(hidden)]
19    pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
20    where
21        D: de::Deserializer<'de>,
22    {
23        match OptionAsNullOrTrue::deserialize(de)? {
24            OptionAsNullOrTrue::Null(()) => Ok(None),
25            OptionAsNullOrTrue::True(true) => Ok(Some(())),
26            _ => Err(de::Error::invalid_value(
27                de::Unexpected::Bool(false),
28                &"null or true",
29            )),
30        }
31    }
32
33    #[derive(Deserialize)]
34    #[serde(untagged)]
35    enum OptionAsNullOrTrue {
36        Null(()),
37        True(bool),
38    }
39}
40
41/// (De)serializes `Option<()>` as a boolean (false for `None`, true for `Some(())`).
42pub mod option_unit_as_bool {
43    use serde::{de, ser, Deserialize, Serialize};
44
45    #[doc(hidden)]
46    pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
47    where
48        S: ser::Serializer,
49    {
50        value.is_some().serialize(ser)
51    }
52
53    #[doc(hidden)]
54    pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
55    where
56        D: de::Deserializer<'de>,
57    {
58        Ok(if bool::deserialize(de)? {
59            Some(())
60        } else {
61            None
62        })
63    }
64}
65
66/// (De)serializes `Option<()>` as a list (empty for `None`, singleton null for `Some(())`).
67pub mod option_unit_as_list {
68    use serde::{de, ser, Deserialize, Serialize};
69
70    #[doc(hidden)]
71    pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
72    where
73        S: ser::Serializer,
74    {
75        OptionAsList { unit: *value }.serialize(ser)
76    }
77
78    #[doc(hidden)]
79    pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
80    where
81        D: de::Deserializer<'de>,
82    {
83        let o = OptionAsList::deserialize(de)?;
84        Ok(o.unit)
85    }
86
87    #[derive(Serialize, Deserialize)]
88    struct OptionAsList {
89        #[serde(default)]
90        #[serde(skip_serializing_if = "Option::is_none")]
91        #[serde(deserialize_with = "deserialize_prefer_some")]
92        unit: Option<()>,
93    }
94
95    fn deserialize_prefer_some<'de, D>(de: D) -> Result<Option<()>, D::Error>
96    where
97        D: de::Deserializer<'de>,
98    {
99        let _ = <()>::deserialize(de)?;
100        Ok(Some(()))
101    }
102}
103
104/// (De)serializes `u64` as an `i64` offset by 2^31.
105pub mod u64_as_i64 {
106    use serde::{de, ser, Deserialize, Serialize};
107
108    #[doc(hidden)]
109    pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
110    where
111        S: ser::Serializer,
112    {
113        i64::from_be_bytes(value.to_be_bytes()).serialize(ser)
114    }
115
116    #[doc(hidden)]
117    pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
118    where
119        D: de::Deserializer<'de>,
120    {
121        let value = i64::deserialize(de)?;
122        Ok(u64::from_be_bytes(value.to_be_bytes()))
123    }
124}
125
126/// (De)serializes `u64` as raw bytes.
127pub mod u64_as_bytes {
128    use super::array_as_bytes::ByteArrayVisitor;
129    use serde::{de, ser};
130
131    #[doc(hidden)]
132    pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
133    where
134        S: ser::Serializer,
135    {
136        ser.serialize_bytes(&value.to_be_bytes())
137    }
138
139    #[doc(hidden)]
140    pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
141    where
142        D: de::Deserializer<'de>,
143    {
144        let bytes = de.deserialize_bytes(ByteArrayVisitor::default())?;
145        Ok(u64::from_be_bytes(bytes))
146    }
147}
148
149/// (De)serializes `u64` as `i64` if it fits, otherwise as raw bytes.
150pub mod u64_as_i64_or_bytes {
151    use serde::{de, ser, Deserialize};
152
153    #[doc(hidden)]
154    pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
155    where
156        S: ser::Serializer,
157    {
158        if *value > i64::MAX as u64 {
159            super::u64_as_bytes::serialize(value, ser)
160        } else {
161            super::u64_as_i64::serialize(value, ser)
162        }
163    }
164
165    #[doc(hidden)]
166    pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
167    where
168        D: de::Deserializer<'de>,
169    {
170        match U64AsI64OrRaw::deserialize(de)? {
171            U64AsI64OrRaw::I64(value) if value <= i64::MAX as u64 => Ok(value as u64),
172            U64AsI64OrRaw::Raw(value) if value > i64::MAX as u64 => Ok(value),
173            _ => Err(de::Error::invalid_value(
174                de::Unexpected::Other("out-of-bounds i64 or raw"),
175                &"i64 >= 0 or raw <= i64::MAX",
176            )),
177        }
178    }
179
180    #[derive(Deserialize)]
181    #[serde(untagged)]
182    enum U64AsI64OrRaw {
183        I64(u64),
184        #[serde(with = "super::u64_as_bytes")]
185        Raw(u64),
186    }
187}
188
189/// (De)serializes arrays as raw bytes.
190pub mod array_as_bytes {
191    use serde::{de, ser};
192    use std::{fmt, marker::PhantomData};
193
194    #[doc(hidden)]
195    pub trait CopyFromSlice: Default {
196        const LENGTH: usize;
197        fn copy_from_slice(&mut self, slice: &[u8]);
198    }
199
200    macro_rules! copy_from_slice_array_impl {
201        ($n:literal) => {
202            impl CopyFromSlice for [u8; $n] {
203                const LENGTH: usize = $n;
204                fn copy_from_slice(&mut self, slice: &[u8]) {
205                    <[u8]>::copy_from_slice(self, slice)
206                }
207            }
208        };
209    }
210
211    copy_from_slice_array_impl!(0);
212    copy_from_slice_array_impl!(1);
213    copy_from_slice_array_impl!(2);
214    copy_from_slice_array_impl!(3);
215    copy_from_slice_array_impl!(4);
216    copy_from_slice_array_impl!(5);
217    copy_from_slice_array_impl!(6);
218    copy_from_slice_array_impl!(7);
219    copy_from_slice_array_impl!(8);
220    copy_from_slice_array_impl!(9);
221    copy_from_slice_array_impl!(10);
222    copy_from_slice_array_impl!(11);
223    copy_from_slice_array_impl!(12);
224    copy_from_slice_array_impl!(13);
225    copy_from_slice_array_impl!(14);
226    copy_from_slice_array_impl!(15);
227    copy_from_slice_array_impl!(16);
228    copy_from_slice_array_impl!(17);
229    copy_from_slice_array_impl!(18);
230    copy_from_slice_array_impl!(19);
231    copy_from_slice_array_impl!(20);
232    copy_from_slice_array_impl!(21);
233    copy_from_slice_array_impl!(22);
234    copy_from_slice_array_impl!(23);
235    copy_from_slice_array_impl!(24);
236    copy_from_slice_array_impl!(25);
237    copy_from_slice_array_impl!(26);
238    copy_from_slice_array_impl!(27);
239    copy_from_slice_array_impl!(28);
240    copy_from_slice_array_impl!(29);
241    copy_from_slice_array_impl!(30);
242    copy_from_slice_array_impl!(31);
243    copy_from_slice_array_impl!(32);
244
245    #[derive(Default)]
246    pub(crate) struct ByteArrayVisitor<T>
247    where
248        T: CopyFromSlice,
249    {
250        array: PhantomData<T>,
251    }
252
253    impl<'de, T> de::Visitor<'de> for ByteArrayVisitor<T>
254    where
255        T: CopyFromSlice,
256    {
257        type Value = T;
258
259        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
260            formatter.write_str("byte array")
261        }
262
263        fn visit_bytes<E>(self, bytes: &[u8]) -> Result<T, E>
264        where
265            E: de::Error,
266        {
267            if bytes.len() != T::LENGTH {
268                return Err(de::Error::invalid_length(bytes.len(), &"array size"));
269            }
270            let mut buf = T::default();
271            buf.copy_from_slice(bytes);
272            Ok(buf)
273        }
274
275        fn visit_byte_buf<E>(self, bytes: Vec<u8>) -> Result<T, E>
276        where
277            E: de::Error,
278        {
279            self.visit_bytes(&bytes)
280        }
281    }
282
283    #[doc(hidden)]
284    pub fn serialize<S, T>(value: &T, ser: S) -> Result<S::Ok, S::Error>
285    where
286        S: ser::Serializer,
287        T: AsRef<[u8]>,
288    {
289        ser.serialize_bytes(value.as_ref())
290    }
291
292    #[doc(hidden)]
293    pub fn deserialize<'de, D, T>(de: D) -> Result<T, D::Error>
294    where
295        D: de::Deserializer<'de>,
296        T: CopyFromSlice,
297    {
298        de.deserialize_bytes(ByteArrayVisitor::default())
299    }
300}
301
302#[cfg(test)]
303mod test {
304    use super::*;
305    use crate::from_slice;
306    use crate::to_vec;
307    use hex_literal::hex;
308    use serde::{Deserialize, Serialize};
309
310    #[test]
311    fn customize_option_unit() {
312        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
313        struct Test {
314            #[serde(with = "option_unit_as_null_or_true")]
315            a0: Option<()>,
316            #[serde(with = "option_unit_as_null_or_true")]
317            a1: Option<()>,
318            #[serde(with = "option_unit_as_bool")]
319            b0: Option<()>,
320            #[serde(with = "option_unit_as_bool")]
321            b1: Option<()>,
322            #[serde(with = "option_unit_as_list")]
323            c0: Option<()>,
324            #[serde(with = "option_unit_as_list")]
325            c1: Option<()>,
326        }
327        let input = Test {
328            a0: None,
329            a1: Some(()),
330            b0: None,
331            b1: Some(()),
332            c0: None,
333            c1: Some(()),
334        };
335        let buf = to_vec(&input).unwrap();
336        assert_eq!(
337            hex!("60 00 11 10 11 60 80 60 00 80 80").as_ref(),
338            buf.as_slice()
339        );
340
341        let output = from_slice(&buf).unwrap();
342
343        assert_eq!(input, output);
344    }
345
346    #[test]
347    fn customize_u64() {
348        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
349        struct Test {
350            #[serde(with = "u64_as_i64")]
351            a0: u64,
352            #[serde(with = "u64_as_i64")]
353            a1: u64,
354            #[serde(with = "u64_as_bytes")]
355            b0: u64,
356            #[serde(with = "u64_as_bytes")]
357            b1: u64,
358            #[serde(with = "u64_as_i64_or_bytes")]
359            c0: u64,
360            #[serde(with = "u64_as_i64_or_bytes")]
361            c1: u64,
362        }
363        let input = Test {
364            a0: 17,
365            a1: 0x8765432101234567,
366            b0: 17,
367            b1: 0x8765432101234567,
368            c0: 17,
369            c1: 0x8765432101234567,
370        };
371        let buf = to_vec(&input).unwrap();
372        assert_eq!(
373            hex!("60 2111 288765432101234567 51080000000000000011 51088765432101234567 2111 51088765432101234567 80").as_ref(),
374            buf.as_slice()
375        );
376
377        let output = from_slice(&buf).unwrap();
378
379        assert_eq!(input, output);
380    }
381}