diff --git a/Cargo.toml b/Cargo.toml index 2bef872..839e5d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,10 @@ criterion = "0.8" name = "arbitrary" required-features = ["arbitrary"] +[[test]] +name = "borsh" +required-features = ["borsh"] + [[test]] name = "bytes" required-features = ["bytes"] diff --git a/src/borsh.rs b/src/borsh.rs index 284e24e..81d3833 100644 --- a/src/borsh.rs +++ b/src/borsh.rs @@ -5,9 +5,12 @@ use { format }, borsh::{ + BorshDeserialize, BorshSchema, BorshSerialize, io::{ + Error, + ErrorKind, Result as Serial, Write }, @@ -15,12 +18,13 @@ use { Declaration, Definition } - } + }, + core::iter::repeat_with }; impl BorshSerialize for SmallVec { fn serialize(&self, writer: &mut Writer) -> Serial<()> { - self.len.value().serialize(writer)?; + (self.len.value() as u64).serialize(writer)?; for element in self { element.serialize(writer)?; } @@ -28,6 +32,18 @@ impl BorshSerialize for SmallVec BorshDeserialize for SmallVec { + fn deserialize_reader(reader: &mut R) -> Serial { + let length = u64::deserialize_reader(reader)?; + return repeat_with(|| Type::deserialize_reader(reader)) + .take(length.try_into().map_err(|_| Error::new( + ErrorKind::OutOfMemory, + "Cannot deserialize a sequence with more than usize::MAX elements in this machine" + ))?) + .collect(); + } +} + impl BorshSchema for SmallVec { fn declaration() -> Declaration { return format!("Vec<{}>", Type::declaration()); @@ -42,8 +58,8 @@ impl BorshSchema for SmallVec () { + let smallvec = SmallVec::::from([1, 2, 3]); + let bytes = to_vec(&smallvec).unwrap(); + assert_eq!(bytes, [3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]); + let new = SmallVec::::deserialize(&mut bytes.as_ref()).unwrap(); + assert_eq!(new, smallvec); +} + +#[test] +fn round_trip_zst() -> () { + let smallvec = SmallVec::<(), 5>::from([(); 0x100000]); + let bytes = to_vec(&smallvec).unwrap(); + assert_eq!(bytes, [0, 0, 16, 0, 0, 0, 0, 0]); + let new = SmallVec::<(), 100>::deserialize(&mut bytes.as_ref()).unwrap(); + assert_eq!(new, smallvec); +}