oasis_borsh/de/
mod.rs

1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
2use std::io::{Cursor, Error, Read};
3use std::mem::{forget, size_of};
4
5mod hint;
6
7const ERROR_NOT_ALL_BYTES_READ: &str = "Not all bytes read";
8
9/// A data-structure that can be de-serialized from binary format by NBOR.
10pub trait BorshDeserialize: Sized {
11    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error>;
12
13    /// Deserialize this instance from a slice of bytes.
14    fn try_from_slice(v: &[u8]) -> Result<Self, Error> {
15        let mut c = Cursor::new(v);
16        let result = Self::deserialize(&mut c)?;
17        if c.position() != v.len() as u64 {
18            return Err(std::io::Error::new(
19                std::io::ErrorKind::InvalidData,
20                ERROR_NOT_ALL_BYTES_READ,
21            ));
22        }
23        Ok(result)
24    }
25}
26
27impl BorshDeserialize for () {
28    fn deserialize<R: Read>(_reader: &mut R) -> Result<Self, Error> {
29        Ok(())
30    }
31}
32
33impl BorshDeserialize for u8 {
34    #[inline]
35    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
36        let mut res = 0u8;
37        reader.read_exact(std::slice::from_mut(&mut res))?;
38        Ok(res)
39    }
40}
41
42macro_rules! impl_for_integer {
43    ($type: ident) => {
44        impl BorshDeserialize for $type {
45            #[inline]
46            fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
47                let mut data = [0u8; size_of::<$type>()];
48                reader.read_exact(&mut data)?;
49                Ok($type::from_le_bytes(data))
50            }
51        }
52    };
53}
54
55impl_for_integer!(i8);
56impl_for_integer!(i16);
57impl_for_integer!(i32);
58impl_for_integer!(i64);
59impl_for_integer!(i128);
60impl_for_integer!(u16);
61impl_for_integer!(u32);
62impl_for_integer!(u64);
63impl_for_integer!(u128);
64
65// Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86,
66// and vice-versa. We disallow NaNs to avoid this issue.
67macro_rules! impl_for_float {
68    ($type: ident, $int_type: ident) => {
69        impl BorshDeserialize for $type {
70            fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
71                let mut data = [0u8; size_of::<$type>()];
72                reader.read_exact(&mut data)?;
73                let res = $type::from_bits($int_type::from_le_bytes(data));
74                if res.is_nan() {
75                    return Err(std::io::Error::new(
76                        std::io::ErrorKind::InvalidInput,
77                        "For portability reasons we do not allow to deserialize NaNs.",
78                    ));
79                }
80                Ok(res)
81            }
82        }
83    };
84}
85
86impl_for_float!(f32, u32);
87impl_for_float!(f64, u64);
88
89impl BorshDeserialize for bool {
90    #[inline]
91    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
92        let mut buf = [0u8];
93        reader.read_exact(&mut buf)?;
94        Ok(buf[0] == 1)
95    }
96}
97
98impl<T> BorshDeserialize for Option<T>
99where
100    T: BorshDeserialize,
101{
102    #[inline]
103    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
104        let mut flag = [0u8];
105        reader.read_exact(&mut flag)?;
106        if flag[0] == 0 {
107            Ok(None)
108        } else {
109            Ok(Some(T::deserialize(reader)?))
110        }
111    }
112}
113
114impl<T, E> BorshDeserialize for Result<T, E>
115where
116    T: BorshDeserialize,
117    E: BorshDeserialize,
118{
119    #[inline]
120    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
121        let mut flag = [0u8];
122        reader.read_exact(&mut flag)?;
123        Ok(if flag[0] == 0 {
124            Ok(T::deserialize(reader)?)
125        } else {
126            Err(E::deserialize(reader)?)
127        })
128    }
129}
130
131impl BorshDeserialize for String {
132    #[inline]
133    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
134        let len = u32::deserialize(reader)?;
135        // TODO(16): return capacity allocation when we have the size of the buffer left from the reader.
136        let mut result = Vec::with_capacity(hint::cautious::<u8>(len));
137        for _ in 0..len {
138            result.push(u8::deserialize(reader)?);
139        }
140        String::from_utf8(result)
141            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err.to_string()))
142    }
143}
144
145#[cfg(feature = "std")]
146impl<T> BorshDeserialize for Vec<T>
147where
148    T: BorshDeserialize,
149{
150    #[inline]
151    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
152        let len = u32::deserialize(reader)?;
153        if size_of::<T>() == 0 {
154            let mut result = Vec::new();
155            result.push(T::deserialize(reader)?);
156
157            let p = result.as_mut_ptr();
158            unsafe {
159                forget(result);
160                let len = len as usize;
161                let result = Vec::from_raw_parts(p, len, len);
162                Ok(result)
163            }
164        } else {
165            // TODO(16): return capacity allocation when we can safely do that.
166            let mut result = Vec::with_capacity(hint::cautious::<T>(len));
167            for _ in 0..len {
168                result.push(T::deserialize(reader)?);
169            }
170            Ok(result)
171        }
172    }
173}
174
175#[cfg(feature = "std")]
176impl<T, S> BorshDeserialize for HashSet<T, S>
177where
178    T: BorshDeserialize + Eq + std::hash::Hash,
179    S: std::hash::BuildHasher + Default,
180{
181    #[inline]
182    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
183        let vec = <Vec<T>>::deserialize(reader)?;
184        Ok(vec.into_iter().collect())
185    }
186}
187
188#[cfg(feature = "std")]
189impl<K, V, S> BorshDeserialize for HashMap<K, V, S>
190where
191    K: BorshDeserialize + Eq + std::hash::Hash,
192    V: BorshDeserialize,
193    S: std::hash::BuildHasher + Default,
194{
195    #[inline]
196    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
197        let len = u32::deserialize(reader)?;
198        // TODO(16): return capacity allocation when we can safely do that.
199        let mut result = HashMap::default();
200        for _ in 0..len {
201            let key = K::deserialize(reader)?;
202            let value = V::deserialize(reader)?;
203            result.insert(key, value);
204        }
205        Ok(result)
206    }
207}
208
209#[cfg(feature = "std")]
210impl<T> BorshDeserialize for BTreeSet<T>
211where
212    T: BorshDeserialize + Ord,
213{
214    #[inline]
215    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
216        let vec = <Vec<T>>::deserialize(reader)?;
217        Ok(vec.into_iter().collect())
218    }
219}
220
221#[cfg(feature = "std")]
222impl<K, V> BorshDeserialize for BTreeMap<K, V>
223where
224    K: BorshDeserialize + Ord,
225    V: BorshDeserialize,
226{
227    #[inline]
228    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
229        let len = u32::deserialize(reader)?;
230        let mut result = BTreeMap::new();
231        for _ in 0..len {
232            let key = K::deserialize(reader)?;
233            let value = V::deserialize(reader)?;
234            result.insert(key, value);
235        }
236        Ok(result)
237    }
238}
239
240#[cfg(feature = "std")]
241impl BorshDeserialize for std::net::SocketAddr {
242    #[inline]
243    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
244        let kind = u8::deserialize(reader)?;
245        match kind {
246            0 => std::net::SocketAddrV4::deserialize(reader).map(std::net::SocketAddr::V4),
247            1 => std::net::SocketAddrV6::deserialize(reader).map(std::net::SocketAddr::V6),
248            value => Err(std::io::Error::new(
249                std::io::ErrorKind::InvalidInput,
250                format!("Invalid SocketAddr variant: {}", value),
251            )),
252        }
253    }
254}
255
256#[cfg(feature = "std")]
257impl BorshDeserialize for std::net::SocketAddrV4 {
258    #[inline]
259    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
260        let ip = std::net::Ipv4Addr::deserialize(reader)?;
261        let port = u16::deserialize(reader)?;
262        Ok(std::net::SocketAddrV4::new(ip, port))
263    }
264}
265
266#[cfg(feature = "std")]
267impl BorshDeserialize for std::net::SocketAddrV6 {
268    #[inline]
269    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
270        let ip = std::net::Ipv6Addr::deserialize(reader)?;
271        let port = u16::deserialize(reader)?;
272        Ok(std::net::SocketAddrV6::new(ip, port, 0, 0))
273    }
274}
275
276#[cfg(feature = "std")]
277impl BorshDeserialize for std::net::Ipv4Addr {
278    #[inline]
279    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
280        let mut buf = [0u8; 4];
281        reader.read_exact(&mut buf)?;
282        Ok(std::net::Ipv4Addr::from(buf))
283    }
284}
285
286#[cfg(feature = "std")]
287impl BorshDeserialize for std::net::Ipv6Addr {
288    #[inline]
289    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
290        let mut buf = [0u8; 16];
291        reader.read_exact(&mut buf)?;
292        Ok(std::net::Ipv6Addr::from(buf))
293    }
294}
295
296impl BorshDeserialize for Box<[u8]> {
297    fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
298        let len = u32::deserialize(reader)?;
299        // TODO(16): return capacity allocation when we can safely do that.
300        let mut result = Vec::with_capacity(hint::cautious::<u8>(len));
301        for _ in 0..len {
302            result.push(u8::deserialize(reader)?);
303        }
304        Ok(result.into_boxed_slice())
305    }
306}
307
308macro_rules! impl_arrays {
309    ($($len:expr => ($($n:expr)+))+) => {
310        $(
311            impl<T: BorshDeserialize> BorshDeserialize for [T; $len] {
312                #[inline]
313                fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
314                    // As byte arrays are packed in borsh, this generic implementation should
315                    // produce the same code as an unrolled `reader.read_exact($len)`.
316                    Ok([$(
317                        T::deserialize(reader)
318                        .map_err(|e|
319                            Error::new(
320                                std::io::ErrorKind::InvalidData,
321                                format!("error deserializing element at index {}: {}", $n, e)
322                            )
323                        )?
324                    ),+])
325                }
326            }
327        )+
328    };
329}
330
331impl<T: BorshDeserialize> BorshDeserialize for [T; 0] {
332    fn deserialize<R: Read>(_reader: &mut R) -> Result<Self, Error> {
333        Ok([])
334    }
335}
336
337oasis_borsh_derive::_gen_seq_macro! {
338    impl_arrays => (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 32 64 65)
339}
340
341macro_rules! impl_tuples {
342    ($($len:literal => ($($name:ident)+))+) => {
343        $(
344            impl<$($name: BorshDeserialize),+> BorshDeserialize for ($($name),+) {
345                fn deserialize<R: Read>(reader: &mut R) -> Result<Self, Error> {
346                    Ok(($($name::deserialize(reader)?,)+))
347                }
348            }
349        )*
350    }
351}
352
353oasis_borsh_derive::_gen_seq_macro! {
354    impl_tuples => T :: (2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
355}