common: Change unpack_unchecked api
This commit is contained in:
parent
ce2e10d0e9
commit
75f36c4a49
|
@ -11,13 +11,16 @@ pub trait Pack<'a>: serde::Serialize + serde::Deserialize<'a> {
|
||||||
fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError>;
|
fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError>;
|
||||||
|
|
||||||
/// Deserializes `src` into Self. The deserialized object need not
|
/// Deserializes `src` into Self. The deserialized object need not
|
||||||
/// use all the bytes in `src`. This is the case, for example,
|
/// use all the bytes in `src` and should mutate the slice so that
|
||||||
/// when encoding variable length data, say, when one has a src
|
/// it's new len() becomes the size of the bytes deserialized.
|
||||||
/// array of all zeroes, and a Self that has a Vec<u64>.
|
///
|
||||||
|
/// This is the case, for example, when encoding variable length data,
|
||||||
|
/// say, when one has a src array of all zeroes, and a Self that has a
|
||||||
|
/// Vec<u64>.
|
||||||
///
|
///
|
||||||
/// Use care when using this directly. If using fixed length structs
|
/// Use care when using this directly. If using fixed length structs
|
||||||
/// always use the `unpack` method, instead.
|
/// always use the `unpack` method, instead.
|
||||||
fn unpack_unchecked(src: &[u8]) -> Result<Self, ProgramError>;
|
fn unpack_unchecked(src: &mut &[u8]) -> Result<Self, ProgramError>;
|
||||||
|
|
||||||
/// Returns the size of the byte array required to serialize Self.
|
/// Returns the size of the byte array required to serialize Self.
|
||||||
fn size(&self) -> Result<u64, ProgramError>;
|
fn size(&self) -> Result<u64, ProgramError>;
|
||||||
|
@ -25,8 +28,9 @@ pub trait Pack<'a>: serde::Serialize + serde::Deserialize<'a> {
|
||||||
/// Analogue to pack, performing a check on the size of the given byte
|
/// Analogue to pack, performing a check on the size of the given byte
|
||||||
/// array.
|
/// array.
|
||||||
fn unpack(src: &[u8]) -> Result<Self, ProgramError> {
|
fn unpack(src: &[u8]) -> Result<Self, ProgramError> {
|
||||||
Pack::unpack_unchecked(src).and_then(|r: Self| {
|
let mut src_mut = src.as_ref();
|
||||||
if r.size()? != src.len() as u64 {
|
Pack::unpack_unchecked(&mut src_mut).and_then(|r: Self| {
|
||||||
|
if src_mut.len() != 0 {
|
||||||
return Err(ProgramError::InvalidAccountData);
|
return Err(ProgramError::InvalidAccountData);
|
||||||
}
|
}
|
||||||
Ok(r)
|
Ok(r)
|
||||||
|
@ -49,7 +53,7 @@ pub trait Pack<'a>: serde::Serialize + serde::Deserialize<'a> {
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Self) -> Result<U, ProgramError>,
|
F: FnMut(&mut Self) -> Result<U, ProgramError>,
|
||||||
{
|
{
|
||||||
let mut t = Self::unpack_unchecked(input)?;
|
let mut t = Self::unpack_unchecked(&mut input.as_ref())?;
|
||||||
let u = f(&mut t)?;
|
let u = f(&mut t)?;
|
||||||
Self::pack(t, input)?;
|
Self::pack(t, input)?;
|
||||||
Ok(u)
|
Ok(u)
|
||||||
|
@ -75,9 +79,11 @@ macro_rules! packable {
|
||||||
}
|
}
|
||||||
serum_common::pack::into_bytes(&src, dst)
|
serum_common::pack::into_bytes(&src, dst)
|
||||||
}
|
}
|
||||||
fn unpack_unchecked(src: &[u8]) -> Result<$my_struct, ProgramError> {
|
|
||||||
serum_common::pack::from_bytes::<$my_struct>(src)
|
fn unpack_unchecked(src: &mut &[u8]) -> Result<$my_struct, ProgramError> {
|
||||||
|
serum_common::pack::from_reader(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> Result<u64, ProgramError> {
|
fn size(&self) -> Result<u64, ProgramError> {
|
||||||
serum_common::pack::bytes_size(&self)
|
serum_common::pack::bytes_size(&self)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +105,7 @@ where
|
||||||
let cursor = std::io::Cursor::new(dst);
|
let cursor = std::io::Cursor::new(dst);
|
||||||
bincode::serialize_into(cursor, i).map_err(|_| ProgramError::InvalidAccountData)
|
bincode::serialize_into(cursor, i).map_err(|_| ProgramError::InvalidAccountData)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_bytes<'a, T>(data: &'a [u8]) -> Result<T, ProgramError>
|
pub fn from_bytes<'a, T>(data: &'a [u8]) -> Result<T, ProgramError>
|
||||||
where
|
where
|
||||||
T: serde::de::Deserialize<'a>,
|
T: serde::de::Deserialize<'a>,
|
||||||
|
@ -106,6 +113,14 @@ where
|
||||||
bincode::deserialize(data).map_err(|_| ProgramError::InvalidAccountData)
|
bincode::deserialize(data).map_err(|_| ProgramError::InvalidAccountData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_reader<'a, T, R>(rdr: R) -> Result<T, ProgramError>
|
||||||
|
where
|
||||||
|
R: std::io::Read,
|
||||||
|
T: serde::de::DeserializeOwned,
|
||||||
|
{
|
||||||
|
bincode::deserialize_from(rdr).map_err(|_| ProgramError::InvalidAccountData)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bytes_size<T: ?Sized>(value: &T) -> Result<u64, ProgramError>
|
pub fn bytes_size<T: ?Sized>(value: &T) -> Result<u64, ProgramError>
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
|
@ -137,40 +152,53 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn unpack_too_small() {
|
fn unpack_too_small() {
|
||||||
let data = vec![0; 8];
|
let data = vec![0; 8];
|
||||||
let result = TestStruct::unpack(&data);
|
let r = TestStruct::unpack(&data);
|
||||||
match result {
|
assert_eq!(r.unwrap_err(), ProgramError::InvalidAccountData);
|
||||||
Ok(_) => panic!("expect error"),
|
|
||||||
Err(e) => assert_eq!(e, ProgramError::InvalidAccountData),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unpack_too_large() {
|
fn unpack_too_large() {
|
||||||
let data = vec![0; 100];
|
let data = vec![0; 100];
|
||||||
let result = TestStruct::unpack(&data);
|
let r = TestStruct::unpack(&data);
|
||||||
match result {
|
assert_eq!(r.unwrap_err(), ProgramError::InvalidAccountData);
|
||||||
Ok(_) => panic!("expect error"),
|
|
||||||
Err(e) => assert_eq!(e, ProgramError::InvalidAccountData),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pack_too_small() {
|
fn pack_too_small() {
|
||||||
let mut data = vec![0; 8];
|
let mut data = vec![0; 8];
|
||||||
let result = TestStruct::pack(Default::default(), &mut data);
|
let r = TestStruct::pack(Default::default(), &mut data);
|
||||||
match result {
|
assert_eq!(r.unwrap_err(), ProgramError::InvalidAccountData);
|
||||||
Ok(_) => panic!("expect error"),
|
|
||||||
Err(e) => assert_eq!(e, ProgramError::InvalidAccountData),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pack_too_large() {
|
fn pack_too_large() {
|
||||||
let mut data = vec![0; 100];
|
let mut data = vec![0; 100];
|
||||||
let result = TestStruct::pack(Default::default(), &mut data);
|
let r = TestStruct::pack(Default::default(), &mut data);
|
||||||
match result {
|
assert_eq!(r.unwrap_err(), ProgramError::InvalidAccountData);
|
||||||
Ok(_) => panic!("expect error"),
|
}
|
||||||
Err(e) => assert_eq!(e, ProgramError::InvalidAccountData),
|
|
||||||
}
|
mod dyn_size {
|
||||||
|
use super::*;
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct VarLenStruct {
|
||||||
|
a: u64,
|
||||||
|
v: Vec<u64>,
|
||||||
|
}
|
||||||
|
packable!(VarLenStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn var_len_struct_unpack_unchecked() {
|
||||||
|
let mut data = [0; 100].as_ref();
|
||||||
|
let r = dyn_size::VarLenStruct::unpack_unchecked(&mut data);
|
||||||
|
assert!(r.is_ok());
|
||||||
|
assert_eq!(data.len(), 84);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn var_len_struct_unpack_checked() {
|
||||||
|
let data = [0; 100].as_ref();
|
||||||
|
let r = dyn_size::VarLenStruct::unpack(&data);
|
||||||
|
assert_eq!(r.unwrap_err(), ProgramError::InvalidAccountData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue