use borsh::{BorshDeserialize, BorshSerialize};
const ERROR_NOT_ALL_BYTES_READ: &str = "Not all bytes read";
const ERROR_UNEXPECTED_LENGTH_OF_INPUT: &str = "Unexpected length of input";
#[derive(BorshSerialize, BorshDeserialize, Debug)]
struct Serializable {
item1: i32,
item2: String,
item3: f64,
}
#[test]
fn test_custom_reader() {
let s = Serializable {
item1: 100,
item2: "foo".into(),
item3: 1.2345,
};
let bytes = s.try_to_vec().unwrap();
let mut reader = CustomReader {
data: bytes,
read_index: 0,
};
let de: Serializable = BorshDeserialize::deserialize_reader(&mut reader).unwrap();
assert_eq!(de.item1, s.item1);
assert_eq!(de.item2, s.item2);
assert_eq!(de.item3, s.item3);
}
#[test]
fn test_custom_reader_with_insufficient_data() {
let s = Serializable {
item1: 100,
item2: "foo".into(),
item3: 1.2345,
};
let mut bytes = s.try_to_vec().unwrap();
bytes.pop().unwrap();
let mut reader = CustomReader {
data: bytes,
read_index: 0,
};
assert_eq!(
<Serializable as BorshDeserialize>::deserialize_reader(&mut reader)
.unwrap_err()
.to_string(),
ERROR_UNEXPECTED_LENGTH_OF_INPUT
);
}
#[test]
fn test_custom_reader_with_too_much_data() {
let s = Serializable {
item1: 100,
item2: "foo".into(),
item3: 1.2345,
};
let mut bytes = s.try_to_vec().unwrap();
bytes.push(1);
let mut reader = CustomReader {
data: bytes,
read_index: 0,
};
assert_eq!(
<Serializable as BorshDeserialize>::try_from_reader(&mut reader)
.unwrap_err()
.to_string(),
ERROR_NOT_ALL_BYTES_READ
);
}
struct CustomReader {
data: Vec<u8>,
read_index: usize,
}
impl borsh::maybestd::io::Read for CustomReader {
fn read(&mut self, buf: &mut [u8]) -> borsh::maybestd::io::Result<usize> {
let len = buf.len().min(self.data.len() - self.read_index);
buf[0..len].copy_from_slice(&self.data[self.read_index..self.read_index + len]);
self.read_index += len;
Ok(len)
}
}
#[test]
fn test_custom_reader_that_doesnt_fill_slices() {
let s = Serializable {
item1: 100,
item2: "foo".into(),
item3: 1.2345,
};
let bytes = s.try_to_vec().unwrap();
let mut reader = CustomReaderThatDoesntFillSlices {
data: bytes,
read_index: 0,
};
let de: Serializable = BorshDeserialize::deserialize_reader(&mut reader).unwrap();
assert_eq!(de.item1, s.item1);
assert_eq!(de.item2, s.item2);
assert_eq!(de.item3, s.item3);
}
struct CustomReaderThatDoesntFillSlices {
data: Vec<u8>,
read_index: usize,
}
impl borsh::maybestd::io::Read for CustomReaderThatDoesntFillSlices {
fn read(&mut self, buf: &mut [u8]) -> borsh::maybestd::io::Result<usize> {
let len = buf.len().min(self.data.len() - self.read_index);
let len = if len <= 1 { len } else { len / 2 };
buf[0..len].copy_from_slice(&self.data[self.read_index..self.read_index + len]);
self.read_index += len;
Ok(len)
}
}
#[test]
fn test_custom_reader_that_fails_preserves_error_information() {
let mut reader = CustomReaderThatFails;
let err = <Serializable as BorshDeserialize>::try_from_reader(&mut reader).unwrap_err();
assert_eq!(err.to_string(), "I don't like to run");
assert_eq!(
err.kind(),
borsh::maybestd::io::ErrorKind::ConnectionAborted
);
}
struct CustomReaderThatFails;
impl borsh::maybestd::io::Read for CustomReaderThatFails {
fn read(&mut self, _buf: &mut [u8]) -> borsh::maybestd::io::Result<usize> {
Err(borsh::maybestd::io::Error::new(
borsh::maybestd::io::ErrorKind::ConnectionAborted,
"I don't like to run",
))
}
}