borsh/ser/
helpers.rs

1use crate::BorshSerialize;
2use crate::__private::maybestd::vec::Vec;
3use crate::io::{ErrorKind, Result, Write};
4
5pub(super) const DEFAULT_SERIALIZER_CAPACITY: usize = 1024;
6
7/// Serialize an object into a vector of bytes.
8/// # Example
9///
10/// ```
11/// assert_eq!(vec![12, 0, 0, 0, 0, 0, 0, 0], borsh::to_vec(&12u64).unwrap());
12/// ```
13pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
14where
15    T: BorshSerialize + ?Sized,
16{
17    let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY);
18    value.serialize(&mut result)?;
19    Ok(result)
20}
21
22/// Serializes an object directly into a `Writer`.
23/// # Example
24///
25/// ```
26/// # #[cfg(feature = "std")]
27/// let stderr = std::io::stderr();
28/// # #[cfg(feature = "std")]
29/// assert_eq!((), borsh::to_writer(&stderr, "hello_0x0a").unwrap());
30/// ```
31pub fn to_writer<T, W: Write>(mut writer: W, value: &T) -> Result<()>
32where
33    T: BorshSerialize + ?Sized,
34{
35    value.serialize(&mut writer)
36}
37
38/// Serializes an object without allocation to compute and return its length
39/// # Example
40///
41/// ```
42/// use borsh::BorshSerialize;
43///
44/// /// derive is only available if borsh is built with `features = ["derive"]`
45/// # #[cfg(feature = "derive")]
46/// #[derive(BorshSerialize)]
47/// struct A {
48///     tag: String,
49///     value: u64,
50/// };
51///
52/// # #[cfg(feature = "derive")]
53/// let a = A { tag: "hello".to_owned(), value: 42 };
54///
55/// assert_eq!(8, borsh::object_length(&12u64).unwrap());
56/// # #[cfg(feature = "derive")]
57/// assert_eq!(17, borsh::object_length(&a).unwrap());
58/// ```
59pub fn object_length<T>(value: &T) -> Result<usize>
60where
61    T: BorshSerialize + ?Sized,
62{
63    // copy-paste of solution provided by @matklad
64    // in https://github.com/near/borsh-rs/issues/23#issuecomment-816633365
65    struct LengthWriter {
66        len: usize,
67    }
68    impl Write for LengthWriter {
69        #[inline]
70        fn write(&mut self, buf: &[u8]) -> Result<usize> {
71            let res = self.len.checked_add(buf.len());
72            self.len = match res {
73                Some(res) => res,
74                None => {
75                    return Err(ErrorKind::OutOfMemory.into());
76                }
77            };
78            Ok(buf.len())
79        }
80        #[inline]
81        fn flush(&mut self) -> Result<()> {
82            Ok(())
83        }
84    }
85    let mut w = LengthWriter { len: 0 };
86    value.serialize(&mut w)?;
87    Ok(w.len)
88}