borsh/ser/
mod.rs

1use core::convert::TryFrom;
2use core::mem::size_of;
3
4use crate::maybestd::{
5    borrow::{Cow, ToOwned},
6    boxed::Box,
7    collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
8    io::{ErrorKind, Result, Write},
9    string::String,
10    vec::Vec,
11};
12
13const DEFAULT_SERIALIZER_CAPACITY: usize = 1024;
14
15/// A data-structure that can be serialized into binary format by NBOR.
16pub trait BorshSerialize {
17    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()>;
18
19    /// Serialize this instance into a vector of bytes.
20    fn try_to_vec(&self) -> Result<Vec<u8>> {
21        let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY);
22        self.serialize(&mut result)?;
23        Ok(result)
24    }
25
26    /// Whether Self is u8.
27    /// NOTE: `Vec<u8>` is the most common use-case for serialization and deserialization, it's
28    /// worth handling it as a special case to improve performance.
29    /// It's a workaround for specific `Vec<u8>` implementation versus generic `Vec<T>`
30    /// implementation. See https://github.com/rust-lang/rfcs/pull/1210 for details.
31    #[inline]
32    fn is_u8() -> bool {
33        false
34    }
35}
36
37impl BorshSerialize for u8 {
38    #[inline]
39    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
40        writer.write_all(core::slice::from_ref(self))
41    }
42
43    #[inline]
44    fn is_u8() -> bool {
45        true
46    }
47}
48
49macro_rules! impl_for_integer {
50    ($type: ident) => {
51        impl BorshSerialize for $type {
52            #[inline]
53            fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
54                let bytes = self.to_le_bytes();
55                writer.write_all(&bytes)
56            }
57        }
58    };
59}
60
61impl_for_integer!(i8);
62impl_for_integer!(i16);
63impl_for_integer!(i32);
64impl_for_integer!(i64);
65impl_for_integer!(i128);
66impl_for_integer!(u16);
67impl_for_integer!(u32);
68impl_for_integer!(u64);
69impl_for_integer!(u128);
70
71// Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86,
72// and vice-versa. We disallow NaNs to avoid this issue.
73macro_rules! impl_for_float {
74    ($type: ident) => {
75        impl BorshSerialize for $type {
76            #[inline]
77            fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
78                assert!(
79                    !self.is_nan(),
80                    "For portability reasons we do not allow to serialize NaNs."
81                );
82                writer.write_all(&self.to_bits().to_le_bytes())
83            }
84        }
85    };
86}
87
88impl_for_float!(f32);
89impl_for_float!(f64);
90
91impl BorshSerialize for bool {
92    #[inline]
93    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
94        (if *self { 1u8 } else { 0u8 }).serialize(writer)
95    }
96}
97
98impl<T> BorshSerialize for Option<T>
99where
100    T: BorshSerialize,
101{
102    #[inline]
103    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
104        match self {
105            None => 0u8.serialize(writer),
106            Some(value) => {
107                1u8.serialize(writer)?;
108                value.serialize(writer)
109            }
110        }
111    }
112}
113
114impl<T, E> BorshSerialize for core::result::Result<T, E>
115where
116    T: BorshSerialize,
117    E: BorshSerialize,
118{
119    #[inline]
120    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
121        match self {
122            Err(e) => {
123                0u8.serialize(writer)?;
124                e.serialize(writer)
125            }
126            Ok(v) => {
127                1u8.serialize(writer)?;
128                v.serialize(writer)
129            }
130        }
131    }
132}
133
134impl BorshSerialize for str {
135    #[inline]
136    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
137        self.as_bytes().serialize(writer)
138    }
139}
140
141impl BorshSerialize for String {
142    #[inline]
143    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
144        self.as_bytes().serialize(writer)
145    }
146}
147
148/// Helper method that is used to serialize a slice of data (without the length marker).
149#[inline]
150fn serialize_slice<T: BorshSerialize, W: Write>(data: &[T], writer: &mut W) -> Result<()> {
151    if T::is_u8() && size_of::<T>() == size_of::<u8>() {
152        // The code below uses unsafe memory representation from `&[T]` to `&[u8]`.
153        // The size of the memory should match because `size_of::<T>() == size_of::<u8>()`.
154        //
155        // `T::is_u8()` is a workaround for not being able to implement `Vec<u8>` separately.
156        let buf = unsafe { core::slice::from_raw_parts(data.as_ptr() as *const u8, data.len()) };
157        writer.write_all(buf)?;
158    } else {
159        for item in data {
160            item.serialize(writer)?;
161        }
162    }
163    Ok(())
164}
165
166impl<T> BorshSerialize for [T]
167where
168    T: BorshSerialize,
169{
170    #[inline]
171    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
172        writer.write_all(
173            &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidInput)?).to_le_bytes(),
174        )?;
175        serialize_slice(self, writer)
176    }
177}
178
179impl<T: BorshSerialize + ?Sized> BorshSerialize for &T {
180    #[inline]
181    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
182        (*self).serialize(writer)
183    }
184}
185
186impl<T> BorshSerialize for Cow<'_, T>
187where
188    T: BorshSerialize + ToOwned + ?Sized,
189{
190    #[inline]
191    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
192        self.as_ref().serialize(writer)
193    }
194}
195
196impl<T> BorshSerialize for Vec<T>
197where
198    T: BorshSerialize,
199{
200    #[inline]
201    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
202        self.as_slice().serialize(writer)
203    }
204}
205
206impl<T> BorshSerialize for VecDeque<T>
207where
208    T: BorshSerialize,
209{
210    #[inline]
211    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
212        writer.write_all(
213            &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidInput)?).to_le_bytes(),
214        )?;
215        let slices = self.as_slices();
216        serialize_slice(slices.0, writer)?;
217        serialize_slice(slices.1, writer)
218    }
219}
220
221impl<T> BorshSerialize for LinkedList<T>
222where
223    T: BorshSerialize,
224{
225    #[inline]
226    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
227        writer.write_all(
228            &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidInput)?).to_le_bytes(),
229        )?;
230        for item in self {
231            item.serialize(writer)?;
232        }
233        Ok(())
234    }
235}
236
237impl<T> BorshSerialize for BinaryHeap<T>
238where
239    T: BorshSerialize,
240{
241    #[inline]
242    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
243        // It could have been just `self.as_slice().serialize(writer)`, but there is no
244        // `as_slice()` method:
245        // https://internals.rust-lang.org/t/should-i-add-as-slice-method-to-binaryheap/13816
246        writer.write_all(
247            &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidInput)?).to_le_bytes(),
248        )?;
249        for item in self {
250            item.serialize(writer)?;
251        }
252        Ok(())
253    }
254}
255
256impl<K, V> BorshSerialize for HashMap<K, V>
257where
258    K: BorshSerialize + PartialOrd,
259    V: BorshSerialize,
260{
261    #[inline]
262    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
263        let mut vec = self.iter().collect::<Vec<_>>();
264        vec.sort_by(|(a, _), (b, _)| a.partial_cmp(b).unwrap());
265        u32::try_from(vec.len())
266            .map_err(|_| ErrorKind::InvalidInput)?
267            .serialize(writer)?;
268        for (key, value) in vec {
269            key.serialize(writer)?;
270            value.serialize(writer)?;
271        }
272        Ok(())
273    }
274}
275
276impl<T> BorshSerialize for HashSet<T>
277where
278    T: BorshSerialize + PartialOrd,
279{
280    #[inline]
281    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
282        let mut vec = self.iter().collect::<Vec<_>>();
283        vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
284        u32::try_from(vec.len())
285            .map_err(|_| ErrorKind::InvalidInput)?
286            .serialize(writer)?;
287        for item in vec {
288            item.serialize(writer)?;
289        }
290        Ok(())
291    }
292}
293
294impl<K, V> BorshSerialize for BTreeMap<K, V>
295where
296    K: BorshSerialize,
297    V: BorshSerialize,
298{
299    #[inline]
300    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
301        // NOTE: BTreeMap iterates over the entries that are sorted by key, so the serialization
302        // result will be consistent without a need to sort the entries as we do for HashMap
303        // serialization.
304        u32::try_from(self.len())
305            .map_err(|_| ErrorKind::InvalidInput)?
306            .serialize(writer)?;
307        for (key, value) in self {
308            key.serialize(writer)?;
309            value.serialize(writer)?;
310        }
311        Ok(())
312    }
313}
314
315impl<T> BorshSerialize for BTreeSet<T>
316where
317    T: BorshSerialize,
318{
319    #[inline]
320    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
321        // NOTE: BTreeSet iterates over the items that are sorted, so the serialization result will
322        // be consistent without a need to sort the entries as we do for HashSet serialization.
323        u32::try_from(self.len())
324            .map_err(|_| ErrorKind::InvalidInput)?
325            .serialize(writer)?;
326        for item in self {
327            item.serialize(writer)?;
328        }
329        Ok(())
330    }
331}
332
333#[cfg(feature = "std")]
334impl BorshSerialize for std::net::SocketAddr {
335    #[inline]
336    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
337        match *self {
338            std::net::SocketAddr::V4(ref addr) => {
339                0u8.serialize(writer)?;
340                addr.serialize(writer)
341            }
342            std::net::SocketAddr::V6(ref addr) => {
343                1u8.serialize(writer)?;
344                addr.serialize(writer)
345            }
346        }
347    }
348}
349
350#[cfg(feature = "std")]
351impl BorshSerialize for std::net::SocketAddrV4 {
352    #[inline]
353    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
354        self.ip().serialize(writer)?;
355        self.port().serialize(writer)
356    }
357}
358
359#[cfg(feature = "std")]
360impl BorshSerialize for std::net::SocketAddrV6 {
361    #[inline]
362    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
363        self.ip().serialize(writer)?;
364        self.port().serialize(writer)
365    }
366}
367
368#[cfg(feature = "std")]
369impl BorshSerialize for std::net::Ipv4Addr {
370    #[inline]
371    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
372        writer.write_all(&self.octets())
373    }
374}
375
376#[cfg(feature = "std")]
377impl BorshSerialize for std::net::Ipv6Addr {
378    #[inline]
379    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
380        writer.write_all(&self.octets())
381    }
382}
383
384impl<T: BorshSerialize + ?Sized> BorshSerialize for Box<T> {
385    fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
386        self.as_ref().serialize(writer)
387    }
388}
389
390macro_rules! impl_arrays {
391    ($($len:expr)+) => {
392    $(
393        impl<T> BorshSerialize for [T; $len]
394        where T: BorshSerialize
395        {
396            #[inline]
397            fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
398                if T::is_u8() && size_of::<T>() == size_of::<u8>() {
399                    // The code below uses unsafe memory representation from `&[T]` to `&[u8]`.
400                    // The size of the memory should match because `size_of::<T>() == size_of::<u8>()`.
401                    //
402                    // `T::is_u8()` is a workaround for not being able to implement `[u8; *]` separately.
403                    let buf = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
404                    writer.write_all(buf)?;
405                } else {
406                    for el in self.iter() {
407                        el.serialize(writer)?;
408                    }
409                }
410                Ok(())
411            }
412        }
413    )+
414    };
415}
416
417impl<T> BorshSerialize for [T; 0]
418where
419    T: BorshSerialize,
420{
421    #[inline]
422    fn serialize<W: Write>(&self, _writer: &mut W) -> Result<()> {
423        Ok(())
424    }
425}
426
427impl_arrays!(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 64 65 128 256 512 1024 2048);
428
429impl BorshSerialize for () {
430    fn serialize<W: Write>(&self, _writer: &mut W) -> Result<()> {
431        Ok(())
432    }
433}
434
435macro_rules! impl_tuple {
436    ($($idx:tt $name:ident)+) => {
437      impl<$($name),+> BorshSerialize for ($($name),+)
438      where $($name: BorshSerialize,)+
439      {
440        #[inline]
441        fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
442            $(self.$idx.serialize(writer)?;)+
443            Ok(())
444        }
445      }
446    };
447}
448
449impl_tuple!(0 T0 1 T1);
450impl_tuple!(0 T0 1 T1 2 T2);
451impl_tuple!(0 T0 1 T1 2 T2 3 T3);
452impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4);
453impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5);
454impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6);
455impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7);
456impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8);
457impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9);
458impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10);
459impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11);
460impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12);
461impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13);
462impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14);
463impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15);
464impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16);
465impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16 17 T17);
466impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16 17 T17 18 T18);
467impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16 17 T17 18 T18 19 T19);