oasis_borsh/ser/
mod.rs

1use std::collections::{BTreeMap, HashMap, HashSet};
2use std::io::{Error, Write};
3
4const DEFAULT_SERIALIZER_CAPACITY: usize = 1024;
5
6/// A data-structure that can be serialized into binary format by NBOR.
7pub trait BorshSerialize {
8    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error>;
9
10    /// Serialize this instance into a vector of bytes.
11    fn try_to_vec(&self) -> Result<Vec<u8>, Error> {
12        let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY);
13        self.serialize(&mut result)?;
14        Ok(result)
15    }
16}
17
18impl BorshSerialize for () {
19    fn serialize<W: Write>(&self, _writer: &mut W) -> Result<(), Error> {
20        Ok(())
21    }
22}
23
24impl BorshSerialize for u8 {
25    #[inline]
26    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
27        writer.write_all(std::slice::from_ref(self))
28    }
29}
30
31macro_rules! impl_for_integer {
32    ($type: ident) => {
33        impl BorshSerialize for $type {
34            #[inline]
35            fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
36                writer.write_all(&self.to_le_bytes())
37            }
38        }
39    };
40}
41
42impl_for_integer!(i8);
43impl_for_integer!(i16);
44impl_for_integer!(i32);
45impl_for_integer!(i64);
46impl_for_integer!(i128);
47impl_for_integer!(u16);
48impl_for_integer!(u32);
49impl_for_integer!(u64);
50impl_for_integer!(u128);
51
52// Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86,
53// and vice-versa. We disallow NaNs to avoid this issue.
54macro_rules! impl_for_float {
55    ($type: ident) => {
56        impl BorshSerialize for $type {
57            #[inline]
58            fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
59                assert!(
60                    !self.is_nan(),
61                    "For portability reasons we do not allow to serialize NaNs."
62                );
63                writer.write_all(&self.to_bits().to_le_bytes())
64            }
65        }
66    };
67}
68
69impl_for_float!(f32);
70impl_for_float!(f64);
71
72impl BorshSerialize for bool {
73    #[inline]
74    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
75        (if *self { 1u8 } else { 0u8 }).serialize(writer)
76    }
77}
78
79impl<T> BorshSerialize for Option<T>
80where
81    T: BorshSerialize,
82{
83    #[inline]
84    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
85        match self {
86            None => 0u8.serialize(writer),
87            Some(value) => {
88                1u8.serialize(writer)?;
89                value.serialize(writer)
90            }
91        }
92    }
93}
94
95impl<T, E> BorshSerialize for Result<T, E>
96where
97    T: BorshSerialize,
98    E: BorshSerialize,
99{
100    #[inline]
101    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
102        match self {
103            Ok(value) => {
104                0u8.serialize(writer)?;
105                value.serialize(writer)
106            },
107            Err(value) => {
108                1u8.serialize(writer)?;
109                value.serialize(writer)
110            }
111        }
112    }
113}
114
115impl BorshSerialize for String {
116    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
117        self.as_bytes().serialize(writer)
118    }
119}
120
121impl BorshSerialize for &str {
122    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
123        self.as_bytes().serialize(writer)
124    }
125}
126
127#[cfg(feature = "std")]
128impl<T: BorshSerialize> BorshSerialize for Vec<T> {
129    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
130        self.as_slice().serialize(writer)
131    }
132}
133
134impl<T> BorshSerialize for [T]
135where
136    T: BorshSerialize,
137{
138    #[inline]
139    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
140        writer.write_all(&(self.len() as u32).to_le_bytes())?;
141        for item in self {
142            item.serialize(writer)?;
143        }
144        Ok(())
145    }
146}
147
148
149impl<T> BorshSerialize for &[T]
150where
151    T: BorshSerialize,
152{
153    #[inline]
154    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
155        writer.write_all(&(self.len() as u32).to_le_bytes())?;
156        for item in self.iter() {
157            item.serialize(writer)?;
158        }
159        Ok(())
160    }
161}
162
163impl<T: BorshSerialize> BorshSerialize for &T {
164    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
165        (*self).serialize(writer)
166    }
167}
168
169#[cfg(feature = "std")]
170impl<T, S> BorshSerialize for HashSet<T, S>
171where
172    T: BorshSerialize + PartialOrd,
173    S: std::hash::BuildHasher,
174{
175    #[inline]
176    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
177        let mut vec = self.iter().collect::<Vec<_>>();
178        vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
179        (vec.len() as u32).serialize(writer)?;
180        for item in vec {
181            item.serialize(writer)?;
182        }
183        Ok(())
184    }
185}
186
187#[cfg(feature = "std")]
188impl<K, V, S> BorshSerialize for HashMap<K, V, S>
189where
190    K: BorshSerialize + PartialOrd,
191    V: BorshSerialize,
192    S: std::hash::BuildHasher,
193{
194    #[inline]
195    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
196        let mut vec = self.iter().collect::<Vec<_>>();
197        vec.sort_by(|(a, _), (b, _)| a.partial_cmp(b).unwrap());
198        (vec.len() as u32).serialize(writer)?;
199        for (key, value) in vec {
200            key.serialize(writer)?;
201            value.serialize(writer)?;
202        }
203        Ok(())
204    }
205}
206
207#[cfg(feature = "std")]
208impl<K, V> BorshSerialize for BTreeMap<K, V>
209where
210    K: BorshSerialize + PartialOrd,
211    V: BorshSerialize,
212{
213    #[inline]
214    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
215        (self.len() as u32).serialize(writer)?;
216        for (key, value) in self.iter() {
217            key.serialize(writer)?;
218            value.serialize(writer)?;
219        }
220        Ok(())
221    }
222}
223
224#[cfg(feature = "std")]
225impl BorshSerialize for std::net::SocketAddr {
226    #[inline]
227    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
228        match *self {
229            std::net::SocketAddr::V4(ref addr) => {
230                0u8.serialize(writer)?;
231                addr.serialize(writer)
232            }
233            std::net::SocketAddr::V6(ref addr) => {
234                1u8.serialize(writer)?;
235                addr.serialize(writer)
236            }
237        }
238    }
239}
240
241#[cfg(feature = "std")]
242impl BorshSerialize for std::net::SocketAddrV4 {
243    #[inline]
244    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
245        self.ip().serialize(writer)?;
246        self.port().serialize(writer)
247    }
248}
249
250#[cfg(feature = "std")]
251impl BorshSerialize for std::net::SocketAddrV6 {
252    #[inline]
253    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
254        self.ip().serialize(writer)?;
255        self.port().serialize(writer)
256    }
257}
258
259#[cfg(feature = "std")]
260impl BorshSerialize for std::net::Ipv4Addr {
261    #[inline]
262    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
263        writer.write_all(&self.octets())
264    }
265}
266
267#[cfg(feature = "std")]
268impl BorshSerialize for std::net::Ipv6Addr {
269    #[inline]
270    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
271        writer.write_all(&self.octets())
272    }
273}
274
275impl BorshSerialize for Box<[u8]> {
276    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
277        (self.len() as u32).serialize(writer)?;
278        writer.write_all(self)
279    }
280}
281
282impl<T: BorshSerialize> BorshSerialize for Box<T> {
283    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
284        (&**self).serialize(writer)
285    }
286}
287
288macro_rules! impl_arrays {
289    ($($len:expr)+) => {
290    $(
291      impl<T> BorshSerialize for [T; $len]
292      where T: BorshSerialize
293      {
294        #[inline]
295        fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
296            for el in self.iter() {
297                el.serialize(writer)?;
298            }
299            Ok(())
300        }
301      }
302      )+
303    };
304}
305
306impl_arrays!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 32 64 65);
307
308macro_rules! impl_tuple {
309    ($($idx:tt $name:ident)+) => {
310      impl<$($name),+> BorshSerialize for ($($name),+)
311      where $($name: BorshSerialize,)+
312      {
313        #[inline]
314        fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
315            $(self.$idx.serialize(writer)?;)+
316            Ok(())
317        }
318      }
319    };
320}
321
322impl_tuple!(0 T0 1 T1);
323impl_tuple!(0 T0 1 T1 2 T2);
324impl_tuple!(0 T0 1 T1 2 T2 3 T3);
325impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4);
326impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5);
327impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6);
328impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7);
329impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8);
330impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9);
331impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10);
332impl_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);
333impl_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);
334impl_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);
335impl_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);
336impl_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);
337impl_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);
338impl_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);
339impl_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);
340impl_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);