Skip to main content

nimiq_serde/
lib.rs

1use std::{error::Error, fmt, io, io::Write, ops};
2
3pub use nimiq_serde_derive::{SerializedMaxSize, SerializedSize};
4pub use postcard::{fixint, FixedSizeByteArray};
5use serde::{
6    de::{Deserializer, Error as _},
7    ser::Serializer,
8};
9pub use serde_derive::{Deserialize, Serialize};
10
11/// Deserialization error.
12///
13/// This error is mostly a wrapper over `postcard::Error` but adds more
14/// variants.
15#[derive(Eq, PartialEq)]
16pub struct DeserializeError(DeserializeErrorInner);
17
18#[derive(Eq, PartialEq)]
19enum DeserializeErrorInner {
20    Postcard(postcard::Error),
21    ExtraData,
22}
23
24impl DeserializeError {
25    fn from(error: postcard::Error) -> DeserializeError {
26        DeserializeError(DeserializeErrorInner::Postcard(error))
27    }
28
29    /// Returns a 'Bad enumeration' error
30    pub fn bad_enum() -> DeserializeError {
31        DeserializeError(DeserializeErrorInner::Postcard(
32            postcard::Error::DeserializeBadEnum,
33        ))
34    }
35    /// Returns an 'Unexpected end' error.
36    pub fn unexpected_end() -> DeserializeError {
37        DeserializeError(DeserializeErrorInner::Postcard(
38            postcard::Error::DeserializeUnexpectedEnd,
39        ))
40    }
41    /// Returns a 'Bad encoding' error.
42    pub fn bad_encoding() -> DeserializeError {
43        DeserializeError(DeserializeErrorInner::Postcard(
44            postcard::Error::DeserializeBadEncoding,
45        ))
46    }
47    /// Returns a 'Serde custom' error.
48    pub fn serde_custom() -> DeserializeError {
49        DeserializeError(DeserializeErrorInner::Postcard(
50            postcard::Error::SerdeDeCustom,
51        ))
52    }
53    /// Returns a 'Extra data at the end' error.
54    pub fn extra_data() -> DeserializeError {
55        DeserializeError(DeserializeErrorInner::ExtraData)
56    }
57}
58
59impl fmt::Debug for DeserializeError {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        match &self.0 {
62            DeserializeErrorInner::Postcard(inner) => inner.fmt(f),
63            DeserializeErrorInner::ExtraData => f.debug_tuple("ExtraData").finish(),
64        }
65    }
66}
67
68impl fmt::Display for DeserializeError {
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        match &self.0 {
71            DeserializeErrorInner::Postcard(inner) => inner.fmt(f),
72            DeserializeErrorInner::ExtraData => "extra data at the end".fmt(f),
73        }
74    }
75}
76
77impl Error for DeserializeError {}
78
79/// Types implementing this trait have a constant binary serialization size.
80///
81/// It can be `#[derive]`d using the [`SerializedSize`] derive macro.
82pub trait SerializedSize {
83    /// Size in bytes of the serialization.
84    const SIZE: usize;
85}
86/// Types implementing this trait have a maximum binary serialization size.
87///
88/// It can be `#[derive]`d using the [`SerializedMaxSize`] derive macro.
89pub trait SerializedMaxSize {
90    /// Maximum size in bytes of the serialization.
91    const MAX_SIZE: usize;
92}
93
94/// Types implementing this trait have an alternative fixed-size serialization length.
95pub trait SerializedFixedSize {
96    /// Size in bytes of the alternate, fixed-size serialization.
97    const FIXED_SIZE: usize;
98}
99
100impl<T: SerializedSize> SerializedMaxSize for T {
101    const MAX_SIZE: usize = T::SIZE;
102}
103
104#[rustfmt::skip]
105#[allow(unused_qualifications)] // Remove with a MSVR >= 1.80
106#[allow(clippy::manual_div_ceil)] // Breaks integer type inference.
107mod integer_impls {
108    use super::SerializedFixedSize;
109    use super::SerializedMaxSize;
110    use super::SerializedSize;
111    use std::mem;
112
113    impl SerializedSize for bool { const SIZE: usize = 1; }
114
115    impl SerializedSize for i8 { const SIZE: usize = 1; }
116    impl SerializedSize for u8 { const SIZE: usize = 1; }
117
118    impl SerializedMaxSize for i16 { const MAX_SIZE: usize = (16 + 6) / 7; }
119    impl SerializedMaxSize for u16 { const MAX_SIZE: usize = (16 + 6) / 7; }
120    impl SerializedMaxSize for i32 { const MAX_SIZE: usize = (32 + 6) / 7; }
121    impl SerializedMaxSize for u32 { const MAX_SIZE: usize = (32 + 6) / 7; }
122    impl SerializedMaxSize for i64 { const MAX_SIZE: usize = (64 + 6) / 7; }
123    impl SerializedMaxSize for u64 { const MAX_SIZE: usize = (64 + 6) / 7; }
124
125    impl SerializedFixedSize for i16 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
126    impl SerializedFixedSize for u16 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
127    impl SerializedFixedSize for i32 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
128    impl SerializedFixedSize for u32 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
129    impl SerializedFixedSize for i64 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
130    impl SerializedFixedSize for u64 { const FIXED_SIZE: usize = mem::size_of::<Self>(); }
131}
132
133impl<T: SerializedMaxSize> SerializedMaxSize for Option<T> {
134    const MAX_SIZE: usize = option_max_size(T::MAX_SIZE);
135}
136
137impl<T: SerializedMaxSize, E: SerializedMaxSize> SerializedMaxSize for Result<T, E> {
138    const MAX_SIZE: usize = 1 + max(T::MAX_SIZE, E::MAX_SIZE);
139}
140
141impl<T: SerializedMaxSize> SerializedMaxSize for ops::Range<T> {
142    const MAX_SIZE: usize = 2 * T::MAX_SIZE;
143}
144
145impl<const NUM: usize, T: SerializedMaxSize> SerializedMaxSize for [T; NUM] {
146    const MAX_SIZE: usize = NUM * T::MAX_SIZE;
147}
148
149pub trait SerializeSeqMaxSize {
150    type Element;
151}
152
153impl<T> SerializeSeqMaxSize for Vec<T> {
154    type Element = T;
155}
156
157/// Maximum size in bytes for a integer value in binary serialization, given its maximum value.
158pub const fn uint_max_size(max_value: u64) -> usize {
159    let bits = match max_value.checked_ilog2() {
160        Some(n) => n + 1,
161        None => 1,
162    };
163    bits.div_ceil(7) as usize
164}
165
166/// Maximum size in bytes for an `Option<T>` value in binary serialization.
167///
168/// `inner_size` is the maximum size of its inner value `T`.
169pub const fn option_max_size(inner_size: usize) -> usize {
170    1 + inner_size
171}
172
173/// Maximum size in bytes for a `Vec<T>` value in binary serialization.
174///
175/// `inner_size` is the maximum size of its inner value `T`. `max_elems` is the maximum number of
176/// elements in that `Vec<T>`.
177pub const fn seq_max_size(inner_size: usize, max_elems: usize) -> usize {
178    uint_max_size(max_elems as u64) + inner_size * max_elems
179}
180
181pub const fn max(a: usize, b: usize) -> usize {
182    if a >= b {
183        a
184    } else {
185        b
186    }
187}
188
189/// The Nimiq human readable array serialization helper trait
190///
191/// ```
192/// # use serde::{Serialize, Deserialize};
193/// # use nimiq_serde::HexArray;
194/// #[derive(Serialize, Deserialize)]
195/// struct S {
196///     #[serde(with = "HexArray")]
197///     arr: [u8; 64],
198/// }
199/// ```
200pub trait HexArray<'de>: Sized {
201    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
202    where
203        S: Serializer;
204    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205    where
206        D: Deserializer<'de>;
207}
208
209impl<'de, const N: usize> HexArray<'de> for [u8; N] {
210    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
211    where
212        S: Serializer,
213    {
214        if serializer.is_human_readable() {
215            serializer.serialize_str(&hex::encode(self))
216        } else {
217            serde::Serialize::serialize(&FixedSizeByteArray::from(*self), serializer)
218        }
219    }
220
221    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222    where
223        D: Deserializer<'de>,
224    {
225        use serde::Deserialize as _;
226        if deserializer.is_human_readable() {
227            let mut out = [0u8; N];
228            hex::decode_to_slice(String::deserialize(deserializer)?, &mut out)
229                .map_err(|_| D::Error::custom("Couldn't decode hex string"))?;
230            Ok(out)
231        } else {
232            Ok(
233                <FixedSizeByteArray<N> as serde::Deserialize>::deserialize(deserializer)?
234                    .into_inner(),
235            )
236        }
237    }
238}
239
240pub trait Serialize: serde::Serialize {
241    fn serialize_to_writer<W: Write>(&self, writer: &mut W) -> io::Result<usize> {
242        struct Wrapper<'a, 'b, W: Write> {
243            inner: &'a mut W,
244            written: &'b mut usize,
245            error: &'b mut Option<io::Error>,
246        }
247        impl<W: Write> postcard::ser_flavors::Flavor for Wrapper<'_, '_, W> {
248            type Output = ();
249            fn try_push(&mut self, data: u8) -> postcard::Result<()> {
250                self.try_extend(&[data])
251            }
252            fn try_extend(&mut self, data: &[u8]) -> postcard::Result<()> {
253                assert!(self.error.is_none());
254                *self.written += data.len();
255                match self.inner.write_all(data) {
256                    Ok(()) => Ok(()),
257                    Err(e) => {
258                        *self.error = Some(e);
259                        Err(postcard::Error::SerializeBufferFull)
260                    }
261                }
262            }
263            fn finalize(self) -> postcard::Result<()> {
264                Ok(())
265            }
266        }
267        let mut written = 0;
268        let mut error = None;
269        let wrapper = Wrapper {
270            inner: writer,
271            written: &mut written,
272            error: &mut error,
273        };
274        match postcard::serialize_with_flavor(self, wrapper) {
275            Ok(()) => Ok(written),
276            Err(e) => Err(io::Error::other(e)),
277        }
278    }
279    fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<usize> {
280        self.serialize_to_writer(writer)
281    }
282    fn serialize_to_vec(&self) -> Vec<u8> {
283        postcard::to_allocvec(self).unwrap()
284    }
285    fn serialized_size(&self) -> usize {
286        let size = postcard::ser_flavors::Size::default();
287        postcard::serialize_with_flavor(self, size).unwrap()
288    }
289}
290
291pub trait Deserialize: serde::de::DeserializeOwned {
292    /// Deserialize from bytes. Extra data may remain at the end.
293    fn deserialize_from_vec(bytes: &[u8]) -> Result<Self, DeserializeError> {
294        postcard::from_bytes(bytes).map_err(DeserializeError::from)
295    }
296    /// Deserialize from bytes. Extra data is returned.
297    fn deserialize_take(bytes: &[u8]) -> Result<(Self, &[u8]), DeserializeError> {
298        postcard::take_from_bytes(bytes).map_err(DeserializeError::from)
299    }
300    /// Deserialize from bytes. Extra data is an error.
301    fn deserialize_all(bytes: &[u8]) -> Result<Self, DeserializeError> {
302        let (result, rest) = Self::deserialize_take(bytes)?;
303        if !rest.is_empty() {
304            return Err(DeserializeError::extra_data());
305        }
306        Ok(result)
307    }
308}
309
310impl<T: serde::Serialize> Serialize for T {}
311
312impl<T: serde::de::DeserializeOwned> Deserialize for T {}
313
314#[cfg(test)]
315mod test {
316    use super::{Deserialize, DeserializeError};
317
318    #[test]
319    fn deserialize_all() {
320        let bytes = b"\x12\x34";
321        assert_eq!(u8::deserialize_from_vec(bytes), Ok(0x12));
322        assert_eq!(u8::deserialize_take(bytes), Ok((0x12, &b"\x34"[..])));
323        assert_eq!(
324            u8::deserialize_all(bytes),
325            Err(DeserializeError::extra_data()),
326        );
327    }
328}