Skip to content

Commit

Permalink
Refactor Serde Tests to not require JSON; fix edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicholas Rodrigues Lordello committed Aug 29, 2023
1 parent e072b41 commit e8469ce
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 133 deletions.
5 changes: 0 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,3 @@ macros = ["ethnum-macros"]
ethnum-intrinsics = { version = "=1.1.0", path = "intrinsics", optional = true }
ethnum-macros = { version = "=1.1.0", path = "macros", optional = true }
serde = { version = "1", default-features = false, optional = true }

[dev-dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
bincode = "1"
293 changes: 199 additions & 94 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ pub mod bytes {
use core::{
fmt::{self, Formatter},
marker::PhantomData,
mem::{self, MaybeUninit},
};
use serde::{
de::{self, Deserializer, Visitor},
Expand Down Expand Up @@ -397,12 +398,27 @@ pub mod bytes {
where
S: de::SeqAccess<'de>,
{
let mut bytes: [u8; 32] = [0; 32];
match seq.size_hint() {
Some(len) if len != 32 => {
return Err(de::Error::invalid_length(len, &self))
}
_ => {}
}

let mut bytes = [MaybeUninit::<u8>::uninit(); 32];
for i in 0..32 {
bytes[i] = seq
.next_element()?
.ok_or(de::Error::invalid_length(i, &self))?;
bytes[i].write(
seq.next_element()?
.ok_or(de::Error::invalid_length(i, &self))?,
);
}
if seq.next_element::<u8>()?.is_some() {
return Err(de::Error::invalid_length(33, &self));
}

// SAFETY: all bytes have been initialized in for loop.
let bytes = unsafe { mem::transmute(bytes) };

Ok(T::from_bytes(bytes))
}
}
Expand Down Expand Up @@ -483,6 +499,7 @@ pub mod compressed_bytes {
use core::{
fmt::{self, Formatter},
marker::PhantomData,
mem::MaybeUninit,
};
use serde::{
de::{self, Deserializer, Visitor},
Expand Down Expand Up @@ -529,6 +546,36 @@ pub mod compressed_bytes {

Ok(T::from_bytes(bytes))
}

fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: de::SeqAccess<'de>,
{
match seq.size_hint() {
Some(len) if len > 32 => return Err(de::Error::invalid_length(len, &self)),
_ => {}
}

let mut bytes = [MaybeUninit::<u8>::uninit(); 32];
let mut i = 0;
while i < 32 {
let b = match seq.next_element()? {
Some(b) => b,
None => break,
};
bytes[i].write(b);
i += 1;
}
if i == 32 && seq.next_element::<u8>()?.is_some() {
return Err(de::Error::invalid_length(33, &self));
}

// SAFETY: bytes up to `i` have been initialized in while
// loop.
let bytes = unsafe { &*(&bytes[..i] as *const _ as *const _) };

self.visit_bytes(bytes)
}
}

#[doc(hidden)]
Expand Down Expand Up @@ -859,6 +906,26 @@ mod tests {
}};
}

macro_rules! assert_de_bytes {
($method:expr, $src:expr; eq: $exp:expr) => {{
let src = $src;
let exp = $exp;

assert_eq!(de!($method, src.as_slice()), exp);

let seq =
value::SeqDeserializer::<_, value::Error>::new(src.into_iter());
assert_eq!(($method)(seq).unwrap(), exp);
}};
($method:expr, $src:expr; err) => {{
let src = $src;
assert!(de!(err; $method, src.as_slice()));
let seq =
value::SeqDeserializer::<_, value::Error>::new(src.into_iter());
assert!(($method)(seq).is_err());
}};
}

assert_eq!(
de!(
I256::deserialize,
Expand Down Expand Up @@ -1017,134 +1084,172 @@ mod tests {
de!(err; permissive::deserialize::<U256, _>, "0x10000000000000000000000000000000000000000000000000000000000000000")
);

assert_eq!(
de!(bytes::le::deserialize::<U256, _>, [0x00; 32].as_slice()),
U256::ZERO
assert_de_bytes!(
bytes::le::deserialize::<U256, _>, [0x00; 32];
eq: U256::ZERO
);
assert_eq!(
de!(bytes::le::deserialize::<U256, _>, [0xff; 32].as_slice()),
U256::MAX
assert_de_bytes!(
bytes::le::deserialize::<U256, _>, [0xff; 32];
eq: U256::MAX
);

assert_de_bytes!(
bytes::le::deserialize::<I256, _>, [0x00; 32];
eq: I256::ZERO
);
assert_de_bytes!(
bytes::le::deserialize::<I256, _>, [0xff; 32];
eq: I256::new(-1)
);

let forty_two = {
let mut v = [0x00; 32];
v[0] = 0x2a;
v
};
assert_eq!(
de!(bytes::le::deserialize::<U256, _>, forty_two.as_slice()),
U256::new(42)
assert_de_bytes!(
bytes::le::deserialize::<U256, _>, forty_two;
eq: U256::new(42)
);
assert_eq!(
de!(bytes::le::deserialize::<I256, _>, [0x00; 32].as_slice()),
I256::ZERO
assert_de_bytes!(
bytes::le::deserialize::<I256, _>, forty_two;
eq: I256::new(42)
);
assert_eq!(
de!(bytes::le::deserialize::<I256, _>, [0xff; 32].as_slice()),
I256::new(-1)

assert_de_bytes!(
bytes::le::deserialize::<U256, _>, [0xff; 31];
err
);
assert_de_bytes!(
bytes::le::deserialize::<U256, _>, [0xff; 33];
err
);
assert_de_bytes!(
bytes::le::deserialize::<I256, _>, [0xff; 31];
err
);
assert_de_bytes!(
bytes::le::deserialize::<I256, _>, [0xff; 33];
err
);

assert_eq!(
de!(bytes::be::deserialize::<U256, _>, [0x00; 32].as_slice()),
U256::ZERO
assert_de_bytes!(
bytes::be::deserialize::<U256, _>, [0x00; 32];
eq: U256::ZERO
);
assert_eq!(
de!(bytes::be::deserialize::<U256, _>, [0xff; 32].as_slice()),
U256::MAX
assert_de_bytes!(
bytes::be::deserialize::<U256, _>, [0xff; 32];
eq: U256::MAX
);

assert_de_bytes!(
bytes::be::deserialize::<I256, _>, [0x00; 32];
eq: I256::ZERO
);
assert_de_bytes!(
bytes::be::deserialize::<I256, _>, [0xff; 32];
eq: I256::new(-1)
);

let forty_two = {
let mut v = [0x00; 32];
v[31] = 0x2a;
v
};
assert_eq!(
de!(bytes::be::deserialize::<U256, _>, forty_two.as_slice()),
U256::new(42)
assert_de_bytes!(
bytes::be::deserialize::<U256, _>, forty_two;
eq: U256::new(42)
);
assert_eq!(
de!(bytes::be::deserialize::<I256, _>, [0x00; 32].as_slice()),
I256::ZERO
assert_de_bytes!(
bytes::be::deserialize::<I256, _>, forty_two;
eq: I256::new(42)
);
assert_eq!(
de!(bytes::be::deserialize::<I256, _>, [0xff; 32].as_slice()),
I256::new(-1)

assert_de_bytes!(
bytes::be::deserialize::<U256, _>, [0xff; 31];
err
);
assert_de_bytes!(
bytes::be::deserialize::<U256, _>, [0xff; 33];
err
);
assert_de_bytes!(
bytes::be::deserialize::<I256, _>, [0xff; 31];
err
);
assert_de_bytes!(
bytes::be::deserialize::<I256, _>, [0xff; 33];
err
);

assert_eq!(
de!(compressed_bytes::le::deserialize::<U256, _>, [].as_slice()),
U256::ZERO
assert_de_bytes!(
compressed_bytes::le::deserialize::<U256, _>, [];
eq: U256::ZERO
);
assert_eq!(
de!(
compressed_bytes::le::deserialize::<U256, _>,
[0xff; 32].as_slice()
),
U256::MAX
assert_de_bytes!(
compressed_bytes::le::deserialize::<U256, _>, [0xff; 32];
eq: U256::MAX
);

assert_eq!(
de!(
compressed_bytes::le::deserialize::<U256, _>,
[0x2a].as_slice()
),
U256::new(42)
assert_de_bytes!(
compressed_bytes::le::deserialize::<U256, _>, [0x2a];
eq: U256::new(42)
);
assert_eq!(
de!(
compressed_bytes::le::deserialize::<U256, _>,
[0xee, 0xff].as_slice()
),
U256::new(0xffee),
assert_de_bytes!(
compressed_bytes::le::deserialize::<U256, _>, [0xee, 0xff];
eq: U256::new(0xffee)
);
assert_eq!(
de!(compressed_bytes::le::deserialize::<I256, _>, [].as_slice()),
I256::ZERO
assert_de_bytes!(
compressed_bytes::le::deserialize::<I256, _>, [];
eq: I256::ZERO
);
assert_eq!(
de!(
compressed_bytes::le::deserialize::<I256, _>,
[0xff].as_slice()
),
I256::new(-1)
assert_de_bytes!(
compressed_bytes::le::deserialize::<I256, _>, [0xff];
eq: I256::new(-1)
);

assert_eq!(
de!(compressed_bytes::be::deserialize::<U256, _>, [].as_slice()),
U256::ZERO
assert_de_bytes!(
compressed_bytes::le::deserialize::<U256, _>, [0xff; 33];
err
);
assert_eq!(
de!(
compressed_bytes::be::deserialize::<U256, _>,
[0xff; 32].as_slice()
),
U256::MAX
assert_de_bytes!(
compressed_bytes::le::deserialize::<I256, _>, [0xff; 33];
err
);

assert_eq!(
de!(
compressed_bytes::be::deserialize::<U256, _>,
[0x2a].as_slice()
),
U256::new(42)
assert_de_bytes!(
compressed_bytes::be::deserialize::<U256, _>, [];
eq: U256::ZERO
);
assert_eq!(
de!(
compressed_bytes::be::deserialize::<U256, _>,
[0xff, 0xee].as_slice()
),
U256::new(0xffee),
assert_de_bytes!(
compressed_bytes::be::deserialize::<U256, _>, [0xff; 32];
eq: U256::MAX
);
assert_eq!(
de!(compressed_bytes::be::deserialize::<I256, _>, [].as_slice()),
I256::ZERO

assert_de_bytes!(
compressed_bytes::be::deserialize::<U256, _>, [0x2a];
eq: U256::new(42)
);
assert_eq!(
de!(
compressed_bytes::be::deserialize::<I256, _>,
[0xff].as_slice()
),
I256::new(-1)
assert_de_bytes!(
compressed_bytes::be::deserialize::<U256, _>, [0xff, 0xee];
eq: U256::new(0xffee)
);
assert_de_bytes!(
compressed_bytes::be::deserialize::<I256, _>, [];
eq: I256::ZERO
);
assert_de_bytes!(
compressed_bytes::be::deserialize::<I256, _>, [0xfe];
eq: I256::new(-2)
);

assert_de_bytes!(
compressed_bytes::be::deserialize::<U256, _>, [0xff; 33];
err
);
assert_de_bytes!(
compressed_bytes::be::deserialize::<I256, _>, [0xff; 33];
err
);
}

Expand Down
Loading

0 comments on commit e8469ce

Please sign in to comment.