use borsh::{BorshDeserialize, BorshSerialize};
use std::fmt::Debug;
use std::io::Write;
use std::ops::{Deref, DerefMut};
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RemainderVec<T: BorshSerialize + BorshDeserialize>(Vec<T>);
impl<T> Deref for RemainderVec<T>
where
T: BorshSerialize + BorshDeserialize,
{
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for RemainderVec<T>
where
T: BorshSerialize + BorshDeserialize,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Debug for RemainderVec<T>
where
T: BorshSerialize + BorshDeserialize + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", self.0))
}
}
impl<T> BorshDeserialize for RemainderVec<T>
where
T: BorshSerialize + BorshDeserialize,
{
fn deserialize(buffer: &mut &[u8]) -> borsh::maybestd::io::Result<Self> {
let mut items: Vec<T> = Vec::new();
while let Ok(item) = T::deserialize(buffer) {
items.push(item);
}
Ok(Self(items))
}
}
impl<T> BorshSerialize for RemainderVec<T>
where
T: BorshSerialize + BorshDeserialize,
{
fn serialize<W: Write>(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> {
for item in self.0.iter() {
item.serialize(writer)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_data() {
let mut data = [0u8; 24];
data[0..8].copy_from_slice(u64::to_le_bytes(5).as_slice());
data[8..16].copy_from_slice(u64::to_le_bytes(15).as_slice());
data[16..].copy_from_slice(u64::to_le_bytes(7).as_slice());
let vec = RemainderVec::<u64>::try_from_slice(&data).unwrap();
assert_eq!(vec.len(), 3);
assert_eq!(vec.as_slice(), &[5, 15, 7]);
}
#[test]
fn serialize_data() {
let values = (0..10).collect::<Vec<u32>>();
let source = RemainderVec::<u32>(values);
let mut data = [0u8; 40];
source.serialize(&mut data.as_mut_slice()).unwrap();
let restored = RemainderVec::<u32>::try_from_slice(&data).unwrap();
assert_eq!(restored.len(), source.len());
assert_eq!(restored.as_slice(), source.as_slice());
}
#[test]
fn fail_deserialize_invalid_data_length() {
let mut data = [0u8; 28];
data[0..8].copy_from_slice(u64::to_le_bytes(5).as_slice());
data[8..16].copy_from_slice(u64::to_le_bytes(15).as_slice());
data[16..24].copy_from_slice(u64::to_le_bytes(7).as_slice());
let error = RemainderVec::<u64>::try_from_slice(&data).unwrap_err();
assert_eq!(error.kind(), borsh::maybestd::io::ErrorKind::InvalidData);
}
}