Skip to content

Commit c9c698d

Browse files
FuuzetsuLokathor
andauthored
Add optional support for borsh serialisation (#186)
Co-authored-by: Lokathor <[email protected]>
1 parent 30aa5d4 commit c9c698d

File tree

6 files changed

+152
-3
lines changed

6 files changed

+152
-3
lines changed

Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ tinyvec_macros = { version = "0.1", optional = true }
1616
serde = { version = "1.0", optional = true, default-features = false }
1717
# Provides derived `Arbitrary` implementations
1818
arbitrary = { version = "1", optional = true }
19+
# Provides `BorshSerialize` and `BorshDeserialize implementations
20+
borsh = { version = "1.2.0", optional = true, default-features = false }
1921
# Implements the trait `Array` for `GenericArray` struct.
2022
generic-array = { version = "1.1.1", optional = true, default-features = false }
2123

24+
2225
[features]
2326
default = []
2427

@@ -74,11 +77,11 @@ experimental_write_impl = []
7477
real_blackbox = ["criterion/real_blackbox"]
7578

7679
[package.metadata.docs.rs]
77-
features = ["alloc", "std", "grab_spare_slice", "latest_stable_rust", "serde"]
78-
rustdoc-args = ["--cfg", "docs_rs"]
80+
features = ["alloc", "std", "grab_spare_slice", "latest_stable_rust", "serde", "borsh"]
81+
rustdoc-args = ["--cfg","docs_rs"]
7982

8083
[package.metadata.playground]
81-
features = ["alloc", "std", "grab_spare_slice", "latest_stable_rust", "serde"]
84+
features = ["alloc", "std", "grab_spare_slice", "latest_stable_rust", "serde", "borsh"]
8285

8386
[profile.bench]
8487
debug = 2

src/arrayvec.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,53 @@ where
219219
}
220220
}
221221

222+
#[cfg(feature = "borsh")]
223+
#[cfg_attr(docs_rs, doc(cfg(feature = "borsh")))]
224+
impl<A: Array> borsh::BorshSerialize for ArrayVec<A>
225+
where
226+
<A as Array>::Item: borsh::BorshSerialize,
227+
{
228+
fn serialize<W: borsh::io::Write>(
229+
&self, writer: &mut W,
230+
) -> borsh::io::Result<()> {
231+
<usize as borsh::BorshSerialize>::serialize(&self.len(), writer)?;
232+
for elem in self.iter() {
233+
<<A as Array>::Item as borsh::BorshSerialize>::serialize(elem, writer)?;
234+
}
235+
Ok(())
236+
}
237+
}
238+
239+
#[cfg(feature = "borsh")]
240+
#[cfg_attr(docs_rs, doc(cfg(feature = "borsh")))]
241+
impl<A: Array> borsh::BorshDeserialize for ArrayVec<A>
242+
where
243+
<A as Array>::Item: borsh::BorshDeserialize,
244+
{
245+
fn deserialize_reader<R: borsh::io::Read>(
246+
reader: &mut R,
247+
) -> borsh::io::Result<Self> {
248+
let len = <usize as borsh::BorshDeserialize>::deserialize_reader(reader)?;
249+
let mut new_arrayvec = Self::default();
250+
251+
for idx in 0..len {
252+
let value =
253+
<<A as Array>::Item as borsh::BorshDeserialize>::deserialize_reader(
254+
reader,
255+
)?;
256+
if idx >= new_arrayvec.capacity() {
257+
return Err(borsh::io::Error::new(
258+
borsh::io::ErrorKind::InvalidData,
259+
"invalid ArrayVec length",
260+
));
261+
}
262+
new_arrayvec.push(value)
263+
}
264+
265+
Ok(new_arrayvec)
266+
}
267+
}
268+
222269
#[cfg(feature = "arbitrary")]
223270
#[cfg_attr(docs_rs, doc(cfg(feature = "arbitrary")))]
224271
impl<'a, A> arbitrary::Arbitrary<'a> for ArrayVec<A>

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
//! * `serde` provides a `Serialize` and `Deserialize` implementation for
5050
//! [`TinyVec`] and [`ArrayVec`] types, provided the inner item also has an
5151
//! implementation.
52+
//! * `borsh` provides a `BorshSerialize` and `BorshDeserialize` implementation
53+
//! for [`TinyVec`] and [`ArrayVec`] types, provided the inner item also has
54+
//! an implementation.
5255
//!
5356
//! ## API
5457
//! The general goal of the crate is that, as much as possible, the vecs here

src/tinyvec.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,47 @@ where
221221
}
222222
}
223223

224+
#[cfg(feature = "borsh")]
225+
#[cfg_attr(docs_rs, doc(cfg(feature = "borsh")))]
226+
impl<A: Array> borsh::BorshSerialize for TinyVec<A>
227+
where
228+
<A as Array>::Item: borsh::BorshSerialize,
229+
{
230+
fn serialize<W: borsh::io::Write>(
231+
&self, writer: &mut W,
232+
) -> borsh::io::Result<()> {
233+
<usize as borsh::BorshSerialize>::serialize(&self.len(), writer)?;
234+
for elem in self.iter() {
235+
<<A as Array>::Item as borsh::BorshSerialize>::serialize(elem, writer)?;
236+
}
237+
Ok(())
238+
}
239+
}
240+
241+
#[cfg(feature = "borsh")]
242+
#[cfg_attr(docs_rs, doc(cfg(feature = "borsh")))]
243+
impl<A: Array> borsh::BorshDeserialize for TinyVec<A>
244+
where
245+
<A as Array>::Item: borsh::BorshDeserialize,
246+
{
247+
fn deserialize_reader<R: borsh::io::Read>(
248+
reader: &mut R,
249+
) -> borsh::io::Result<Self> {
250+
let len = <usize as borsh::BorshDeserialize>::deserialize_reader(reader)?;
251+
let mut new_tinyvec = Self::with_capacity(len);
252+
253+
for _ in 0..len {
254+
new_tinyvec.push(
255+
<<A as Array>::Item as borsh::BorshDeserialize>::deserialize_reader(
256+
reader,
257+
)?,
258+
)
259+
}
260+
261+
Ok(new_tinyvec)
262+
}
263+
}
264+
224265
#[cfg(feature = "arbitrary")]
225266
#[cfg_attr(docs_rs, doc(cfg(feature = "arbitrary")))]
226267
impl<'a, A> arbitrary::Arbitrary<'a> for TinyVec<A>

tests/arrayvec.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,28 @@ fn ArrayVec_ser_de() {
447447
);
448448
}
449449

450+
#[cfg(feature = "borsh")]
451+
#[test]
452+
fn ArrayVec_borsh_de_empty() {
453+
let tv: ArrayVec<[i32; 0]> = Default::default();
454+
let buffer = borsh::to_vec(&tv).unwrap();
455+
let des: ArrayVec<[i32; 0]> = borsh::from_slice(&buffer).unwrap();
456+
assert_eq!(tv, des);
457+
}
458+
459+
#[cfg(feature = "borsh")]
460+
#[test]
461+
fn ArrayVec_borsh_de() {
462+
let mut tv: ArrayVec<[i32; 4]> = Default::default();
463+
tv.push(1);
464+
tv.push(2);
465+
tv.push(3);
466+
tv.push(4);
467+
let buffer = borsh::to_vec(&tv).unwrap();
468+
let des: ArrayVec<[i32; 4]> = borsh::from_slice(&buffer).unwrap();
469+
assert_eq!(tv, des);
470+
}
471+
450472
#[test]
451473
fn ArrayVec_try_from_slice() {
452474
use std::convert::TryFrom;

tests/tinyvec.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,39 @@ fn TinyVec_ser_de_heap() {
443443
);
444444
}
445445

446+
#[cfg(feature = "borsh")]
447+
#[test]
448+
fn TinyVec_borsh_de_empty() {
449+
let tv: ArrayVec<[i32; 0]> = Default::default();
450+
let buffer = borsh::to_vec(&tv).unwrap();
451+
let des: ArrayVec<[i32; 0]> = borsh::from_slice(&buffer).unwrap();
452+
assert_eq!(tv, des);
453+
}
454+
455+
#[cfg(feature = "borsh")]
456+
#[test]
457+
fn TinyVec_borsh_de() {
458+
let mut tv: ArrayVec<[i32; 4]> = Default::default();
459+
tv.push(1);
460+
tv.push(2);
461+
tv.push(3);
462+
tv.push(4);
463+
let buffer = borsh::to_vec(&tv).unwrap();
464+
let des: ArrayVec<[i32; 4]> = borsh::from_slice(&buffer).unwrap();
465+
assert_eq!(tv, des);
466+
}
467+
468+
#[cfg(feature = "borsh")]
469+
#[test]
470+
fn TinyVec_borsh_de_heap() {
471+
let mut tv: TinyVec<[i32; 4]> = tiny_vec![1, 2, 3, 4];
472+
tv.move_to_the_heap();
473+
474+
let buffer = borsh::to_vec(&tv).unwrap();
475+
let des: TinyVec<[i32; 4]> = borsh::from_slice(&buffer).unwrap();
476+
assert_eq!(tv, des);
477+
}
478+
446479
#[test]
447480
fn TinyVec_pretty_debug() {
448481
let tv: TinyVec<[i32; 6]> = tiny_vec![1, 2, 3];

0 commit comments

Comments
 (0)