Add partial progress on sos
This commit is contained in:
parent
c5acbd978f
commit
3f9430ddff
@ -1,16 +1,33 @@
|
|||||||
use super::LENGTH_BYTES;
|
use super::*;
|
||||||
|
|
||||||
|
mod impls;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum DecodeError {
|
pub enum DecodeError {
|
||||||
TooShort,
|
// BytesTooShort { given: usize, expected: usize },
|
||||||
TooLong,
|
// BytesTooLong { given: usize, expected: usize },
|
||||||
Invalid,
|
InvalidByteLength { len: usize, expected: usize },
|
||||||
|
InvalidLengthPrefix { len: usize, expected: usize },
|
||||||
|
BytesInvalid(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Decodable: Sized {
|
pub trait Decodable: Sized {
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError>;
|
fn is_ssz_fixed_len() -> bool;
|
||||||
|
|
||||||
|
/// The number of bytes this object occupies in the fixed-length portion of the SSZ bytes.
|
||||||
|
///
|
||||||
|
/// By default, this is set to `BYTES_PER_LENGTH_OFFSET` which is suitable for variable length
|
||||||
|
/// objects, but not fixed-length objects. Fixed-length objects _must_ return a value which
|
||||||
|
/// represents their length.
|
||||||
|
fn ssz_fixed_len() -> usize {
|
||||||
|
BYTES_PER_LENGTH_OFFSET
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
/// Decode the given bytes for the given type
|
/// Decode the given bytes for the given type
|
||||||
///
|
///
|
||||||
/// The single ssz encoded value/container/list will be decoded as the given type,
|
/// The single ssz encoded value/container/list will be decoded as the given type,
|
||||||
@ -213,3 +230,4 @@ mod tests {
|
|||||||
assert_eq!(decoded, Err(DecodeError::TooShort));
|
assert_eq!(decoded, Err(DecodeError::TooShort));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
572
eth2/utils/ssz2/src/decode/impls.rs
Normal file
572
eth2/utils/ssz2/src/decode/impls.rs
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
macro_rules! impl_decodable_for_uint {
|
||||||
|
($type: ident, $bit_size: expr) => {
|
||||||
|
impl Decodable for $type {
|
||||||
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssz_fixed_len() -> usize {
|
||||||
|
$bit_size / 8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let len = bytes.len();
|
||||||
|
let expected = <Self as Decodable>::ssz_fixed_len();
|
||||||
|
|
||||||
|
if len != expected {
|
||||||
|
Err(DecodeError::InvalidByteLength { len, expected })
|
||||||
|
} else {
|
||||||
|
let mut array: [u8; $bit_size / 8] = std::default::Default::default();
|
||||||
|
array.clone_from_slice(bytes);
|
||||||
|
|
||||||
|
Ok(Self::from_le_bytes(array))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_decodable_for_uint!(u16, 16);
|
||||||
|
impl_decodable_for_uint!(u32, 32);
|
||||||
|
impl_decodable_for_uint!(u64, 64);
|
||||||
|
impl_decodable_for_uint!(usize, 64);
|
||||||
|
|
||||||
|
impl<T: Decodable> Decodable for Vec<T> {
|
||||||
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
if bytes.len() == 0 {
|
||||||
|
return Ok(vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if T::is_ssz_fixed_len() {
|
||||||
|
Ok(bytes
|
||||||
|
.chunks(T::ssz_fixed_len())
|
||||||
|
.map(|chunk| T::from_ssz_bytes(chunk))
|
||||||
|
.collect::<Result<_, DecodeError>>()?)
|
||||||
|
} else {
|
||||||
|
let (fixed, variable) = bytes.split_at(read_length(bytes)?);
|
||||||
|
|
||||||
|
dbg!(fixed);
|
||||||
|
dbg!(variable);
|
||||||
|
|
||||||
|
let num_elems = fixed.len() / BYTES_PER_LENGTH_OFFSET;
|
||||||
|
|
||||||
|
dbg!(num_elems);
|
||||||
|
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
let mut values = vec![];
|
||||||
|
|
||||||
|
for i in 1..=num_elems {
|
||||||
|
let chunk = &bytes[(i - 1) * BYTES_PER_LENGTH_OFFSET..i * BYTES_PER_LENGTH_OFFSET];
|
||||||
|
|
||||||
|
dbg!(offset);
|
||||||
|
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &variable[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
values.push(T::from_ssz_bytes(slice)?);
|
||||||
|
|
||||||
|
if i == num_elems {
|
||||||
|
let slice = &variable[offset..];
|
||||||
|
dbg!(slice);
|
||||||
|
values.push(T::from_ssz_bytes(slice)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(values)
|
||||||
|
|
||||||
|
/*
|
||||||
|
fixed
|
||||||
|
.chunks(BYTES_PER_LENGTH_OFFSET)
|
||||||
|
.skip(1)
|
||||||
|
.map(|chunk| {
|
||||||
|
let start = offset;
|
||||||
|
offset += decode_length(chunk)?;
|
||||||
|
Ok(start..offset)
|
||||||
|
})
|
||||||
|
.chain(vec![Ok(offset..variable.len())].into_iter())
|
||||||
|
.map(|range| T::from_ssz_bytes(&variable[range?]))
|
||||||
|
.collect()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
for i in 1..=num_elems {
|
||||||
|
let chunk = &bytes[i * BYTES_PER_LENGTH_OFFSET..(i + 1) * BYTES_PER_LENGTH_OFFSET];
|
||||||
|
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &variable[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
values.push(T::from_ssz_bytes(slice)?);
|
||||||
|
|
||||||
|
if i == num_elems {
|
||||||
|
let slice = &variable[offset..];
|
||||||
|
values.push(T::from_ssz_bytes(slice)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
(0..num_elems)
|
||||||
|
.into_iter()
|
||||||
|
.skip(1)
|
||||||
|
.map(|(i, chunk)| {
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &bytes[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
T::from_ssz_bytes(slice)
|
||||||
|
|
||||||
|
if i == num_elems {
|
||||||
|
let slice = &bytes[offset..];
|
||||||
|
T::from_ssz_bytes(slice)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
fixed
|
||||||
|
.chunks(BYTES_PER_LENGTH_OFFSET)
|
||||||
|
.skip(1)
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, chunk)| {
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &bytes[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
T::from_ssz_bytes(slice)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
|
||||||
|
fixed
|
||||||
|
.chunks(BYTES_PER_LENGTH_OFFSET)
|
||||||
|
.skip(1)
|
||||||
|
.map(|chunk| {
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &bytes[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
T::from_ssz_bytes(slice)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
// let mut values = vec![];
|
||||||
|
|
||||||
|
bytes
|
||||||
|
.get(0..offset)
|
||||||
|
.ok_or_else(|| DecodeError::InvalidByteLength {
|
||||||
|
expected: offset,
|
||||||
|
len: bytes.len(),
|
||||||
|
})?
|
||||||
|
.chunks(BYTES_PER_LENGTH_OFFSET)
|
||||||
|
.skip(1)
|
||||||
|
.map(|chunk| {
|
||||||
|
let end = offset + decode_length(chunk)?;
|
||||||
|
let slice = &bytes[offset..end];
|
||||||
|
offset += end;
|
||||||
|
|
||||||
|
T::from_ssz_bytes(slice)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
// .collect::<Result<Vec<&[u8]>, DecodeError>>()?;
|
||||||
|
|
||||||
|
let (fixed, variable) = bytes.split_at(read_length(bytes)?);
|
||||||
|
|
||||||
|
let mut offset = decode_length();
|
||||||
|
*/
|
||||||
|
|
||||||
|
//panic!("TODO")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a `BYTES_PER_LENGTH_OFFSET`-byte length from `bytes`, where `bytes.len() >=
|
||||||
|
/// BYTES_PER_LENGTH_OFFSET`.
|
||||||
|
fn read_length(bytes: &[u8]) -> Result<usize, DecodeError> {
|
||||||
|
decode_length(bytes.get(0..BYTES_PER_LENGTH_OFFSET).ok_or_else(|| {
|
||||||
|
DecodeError::InvalidLengthPrefix {
|
||||||
|
len: bytes.len(),
|
||||||
|
expected: BYTES_PER_LENGTH_OFFSET,
|
||||||
|
}
|
||||||
|
})?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode bytes as a little-endian usize, returning an `Err` if `bytes.len() !=
|
||||||
|
/// BYTES_PER_LENGTH_OFFSET`.
|
||||||
|
pub fn decode_length(bytes: &[u8]) -> Result<usize, DecodeError> {
|
||||||
|
let len = bytes.len();
|
||||||
|
let expected = BYTES_PER_LENGTH_OFFSET;
|
||||||
|
|
||||||
|
if len != expected {
|
||||||
|
Err(DecodeError::InvalidLengthPrefix { len, expected })
|
||||||
|
} else {
|
||||||
|
let mut array: [u8; BYTES_PER_LENGTH_OFFSET] = std::default::Default::default();
|
||||||
|
array.clone_from_slice(bytes);
|
||||||
|
|
||||||
|
Ok(u32::from_le_bytes(array) as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
use super::decode::decode_ssz_list;
|
||||||
|
use super::ethereum_types::{Address, H256};
|
||||||
|
use super::{Decodable, DecodeError};
|
||||||
|
|
||||||
|
macro_rules! impl_decodable_for_uint {
|
||||||
|
($type: ident, $bit_size: expr) => {
|
||||||
|
impl Decodable for $type {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
assert!((0 < $bit_size) & ($bit_size <= 64) & ($bit_size % 8 == 0));
|
||||||
|
let max_bytes = $bit_size / 8;
|
||||||
|
if bytes.len() >= (index + max_bytes) {
|
||||||
|
let end_bytes = index + max_bytes;
|
||||||
|
let mut result: $type = 0;
|
||||||
|
for (i, byte) in bytes.iter().enumerate().take(end_bytes).skip(index) {
|
||||||
|
let offset = (i - index) * 8;
|
||||||
|
result |= ($type::from(*byte)) << offset;
|
||||||
|
}
|
||||||
|
Ok((result, end_bytes))
|
||||||
|
} else {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_decodable_for_u8_array {
|
||||||
|
($len: expr) => {
|
||||||
|
impl Decodable for [u8; $len] {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
if index + $len > bytes.len() {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
} else {
|
||||||
|
let mut array: [u8; $len] = [0; $len];
|
||||||
|
array.copy_from_slice(&bytes[index..index + $len]);
|
||||||
|
|
||||||
|
Ok((array, index + $len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_decodable_for_uint!(u16, 16);
|
||||||
|
impl_decodable_for_uint!(u32, 32);
|
||||||
|
impl_decodable_for_uint!(u64, 64);
|
||||||
|
impl_decodable_for_uint!(usize, 64);
|
||||||
|
|
||||||
|
impl_decodable_for_u8_array!(4);
|
||||||
|
|
||||||
|
impl Decodable for u8 {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
if index >= bytes.len() {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
} else {
|
||||||
|
Ok((bytes[index], index + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for bool {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
if index >= bytes.len() {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
} else {
|
||||||
|
let result = match bytes[index] {
|
||||||
|
0b0000_0000 => false,
|
||||||
|
0b0000_0001 => true,
|
||||||
|
_ => return Err(DecodeError::Invalid),
|
||||||
|
};
|
||||||
|
Ok((result, index + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for H256 {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
if bytes.len() < 32 || bytes.len() - 32 < index {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
} else {
|
||||||
|
Ok((H256::from_slice(&bytes[index..(index + 32)]), index + 32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Address {
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
if bytes.len() < 20 || bytes.len() - 20 < index {
|
||||||
|
Err(DecodeError::TooShort)
|
||||||
|
} else {
|
||||||
|
Ok((Address::from_slice(&bytes[index..(index + 20)]), index + 20))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Decodable for Vec<T>
|
||||||
|
where
|
||||||
|
T: Decodable,
|
||||||
|
{
|
||||||
|
fn from_ssz_bytes(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
||||||
|
decode_ssz_list(bytes, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_h256() {
|
||||||
|
/*
|
||||||
|
* Input is exact length
|
||||||
|
*/
|
||||||
|
let input = vec![42_u8; 32];
|
||||||
|
let (decoded, i) = H256::from_ssz_bytes(&input).unwrap();
|
||||||
|
assert_eq!(decoded.as_bytes(), &input[..]);
|
||||||
|
assert_eq!(i, 32);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input is too long
|
||||||
|
*/
|
||||||
|
let mut input = vec![42_u8; 32];
|
||||||
|
input.push(12);
|
||||||
|
let (decoded, i) = H256::from_ssz_bytes(&input, 0).unwrap();
|
||||||
|
assert_eq!(decoded.as_bytes(), &input[0..32]);
|
||||||
|
assert_eq!(i, 32);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input is too short
|
||||||
|
*/
|
||||||
|
let input = vec![42_u8; 31];
|
||||||
|
let res = H256::from_ssz_bytes(&input, 0);
|
||||||
|
assert_eq!(res, Err(DecodeError::TooShort));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_vec_u16() {
|
||||||
|
assert_eq!(<Vec<u16>>::from_ssz_bytes(&[0, 0, 0, 0]), Ok(vec![0, 0]));
|
||||||
|
assert_eq!(
|
||||||
|
<Vec<u16>>::from_ssz_bytes(&[0, 0, 1, 0, 2, 0, 3, 0]),
|
||||||
|
Ok(vec![0, 1, 2, 3])
|
||||||
|
);
|
||||||
|
/*
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[255]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
given: 1,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
given: 0,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[0, 1, 2]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
given: 3,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_u16() {
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[0, 0]), Ok(0));
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
|
||||||
|
assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[255]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
len: 1,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
len: 0,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<u16>::from_ssz_bytes(&[0, 1, 2]),
|
||||||
|
Err(DecodeError::InvalidByteLength {
|
||||||
|
len: 3,
|
||||||
|
expected: 2
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_u32() {
|
||||||
|
let ssz = vec![0, 0, 0, 0];
|
||||||
|
let (result, index): (u32, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
assert_eq!(index, 4);
|
||||||
|
|
||||||
|
let ssz = vec![0, 1, 0, 0];
|
||||||
|
let (result, index): (u32, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 4);
|
||||||
|
assert_eq!(result, 256);
|
||||||
|
|
||||||
|
let ssz = vec![255, 255, 255, 0, 1, 0, 0];
|
||||||
|
let (result, index): (u32, usize) = <_>::from_ssz_bytes(&ssz, 3).unwrap();
|
||||||
|
assert_eq!(index, 7);
|
||||||
|
assert_eq!(result, 256);
|
||||||
|
|
||||||
|
let ssz = vec![0, 1, 200, 0];
|
||||||
|
let (result, index): (u32, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 4);
|
||||||
|
assert_eq!(result, 13107456);
|
||||||
|
|
||||||
|
let ssz = vec![255, 255, 255, 255];
|
||||||
|
let (result, index): (u32, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 4);
|
||||||
|
assert_eq!(result, 4294967295);
|
||||||
|
|
||||||
|
let ssz = vec![1, 0, 0];
|
||||||
|
let result: Result<(u32, usize), DecodeError> = <_>::from_ssz_bytes(&ssz);
|
||||||
|
assert_eq!(result, Err(DecodeError::TooShort));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_u64() {
|
||||||
|
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let (result, index): (u64, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 8);
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
|
||||||
|
let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255];
|
||||||
|
let (result, index): (u64, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 8);
|
||||||
|
assert_eq!(result, 18446744073709551615);
|
||||||
|
|
||||||
|
let ssz = vec![0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 255];
|
||||||
|
let (result, index): (u64, usize) = <_>::from_ssz_bytes(&ssz, 3).unwrap();
|
||||||
|
assert_eq!(index, 11);
|
||||||
|
assert_eq!(result, 18374686479671623680);
|
||||||
|
|
||||||
|
let ssz = vec![0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let result: Result<(u64, usize), DecodeError> = <_>::from_ssz_bytes(&ssz);
|
||||||
|
assert_eq!(result, Err(DecodeError::TooShort));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_ssz_bytes_usize() {
|
||||||
|
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let (result, index): (usize, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 8);
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
|
||||||
|
let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255];
|
||||||
|
let (result, index): (usize, usize) = <_>::from_ssz_bytes(&ssz, 3).unwrap();
|
||||||
|
assert_eq!(index, 11);
|
||||||
|
assert_eq!(result, 18446744073709551615);
|
||||||
|
|
||||||
|
let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255, 255];
|
||||||
|
let (result, index): (usize, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 8);
|
||||||
|
assert_eq!(result, 18446744073709551615);
|
||||||
|
|
||||||
|
let ssz = vec![0, 0, 0, 0, 0, 0, 1];
|
||||||
|
let result: Result<(usize, usize), DecodeError> = <_>::from_ssz_bytes(&ssz);
|
||||||
|
assert_eq!(result, Err(DecodeError::TooShort));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_ssz_bounds() {
|
||||||
|
let err: Result<(u16, usize), DecodeError> = <_>::from_ssz_bytes(&vec![1], 2);
|
||||||
|
assert_eq!(err, Err(DecodeError::TooShort));
|
||||||
|
|
||||||
|
let err: Result<(u16, usize), DecodeError> = <_>::from_ssz_bytes(&vec![0, 0, 0, 0], 3);
|
||||||
|
assert_eq!(err, Err(DecodeError::TooShort));
|
||||||
|
|
||||||
|
let result: u16 = <_>::from_ssz_bytes(&vec![0, 0, 0, 1, 0], 3).unwrap().0;
|
||||||
|
assert_eq!(result, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_ssz_bool() {
|
||||||
|
let ssz = vec![0b0000_0000, 0b0000_0001];
|
||||||
|
let (result, index): (bool, usize) = <_>::from_ssz_bytes(&ssz).unwrap();
|
||||||
|
assert_eq!(index, 1);
|
||||||
|
assert_eq!(result, false);
|
||||||
|
|
||||||
|
let (result, index): (bool, usize) = <_>::from_ssz_bytes(&ssz, 1).unwrap();
|
||||||
|
assert_eq!(index, 2);
|
||||||
|
assert_eq!(result, true);
|
||||||
|
|
||||||
|
let ssz = vec![0b0100_0000];
|
||||||
|
let result: Result<(bool, usize), DecodeError> = <_>::from_ssz_bytes(&ssz);
|
||||||
|
assert_eq!(result, Err(DecodeError::Invalid));
|
||||||
|
|
||||||
|
let ssz = vec![];
|
||||||
|
let result: Result<(bool, usize), DecodeError> = <_>::from_ssz_bytes(&ssz);
|
||||||
|
assert_eq!(result, Err(DecodeError::TooShort));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn decode_ssz_list_underflow() {
|
||||||
|
// SSZ encoded (u16::[1, 1, 1], u16::2)
|
||||||
|
let mut encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2, 0];
|
||||||
|
let (decoded_array, i): (Vec<u16>, usize) = <_>::from_ssz_bytes(&encoded, 0).unwrap();
|
||||||
|
let (decoded_u16, i): (u16, usize) = <_>::from_ssz_bytes(&encoded, i).unwrap();
|
||||||
|
assert_eq!(decoded_array, vec![1, 1, 1]);
|
||||||
|
assert_eq!(decoded_u16, 2);
|
||||||
|
assert_eq!(i, 12);
|
||||||
|
|
||||||
|
// Underflow
|
||||||
|
encoded[0] = 4; // change length to 4 from 6
|
||||||
|
let (decoded_array, i): (Vec<u16>, usize) = <_>::from_ssz_bytes(&encoded, 0).unwrap();
|
||||||
|
let (decoded_u16, _): (u16, usize) = <_>::from_ssz_bytes(&encoded, i).unwrap();
|
||||||
|
assert_eq!(decoded_array, vec![1, 1]);
|
||||||
|
assert_eq!(decoded_u16, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_too_long() {
|
||||||
|
let encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2];
|
||||||
|
let decoded_array: Result<Vec<u16>, DecodeError> = decode(&encoded);
|
||||||
|
assert_eq!(decoded_array, Err(DecodeError::TooLong));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_u8_array() {
|
||||||
|
let ssz = vec![0, 1, 2, 3];
|
||||||
|
let result: [u8; 4] = decode(&ssz).unwrap();
|
||||||
|
assert_eq!(result.len(), 4);
|
||||||
|
assert_eq!(result, [0, 1, 2, 3]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use super::{Encodable, SszStream};
|
use super::*;
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
|
|
||||||
macro_rules! impl_encodable_for_uint {
|
macro_rules! impl_encodable_for_uint {
|
||||||
@ -31,13 +31,30 @@ impl<T: Encodable> Encodable for Vec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn as_ssz_bytes(&self) -> Vec<u8> {
|
||||||
let mut stream = SszStream::new();
|
if T::is_ssz_fixed_len() {
|
||||||
|
let mut bytes = Vec::with_capacity(T::ssz_fixed_len() * self.len());
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
stream.append(item)
|
bytes.append(&mut item.as_ssz_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes
|
||||||
|
} else {
|
||||||
|
let mut offset = self.len() * BYTES_PER_LENGTH_OFFSET;
|
||||||
|
let mut fixed = Vec::with_capacity(offset);
|
||||||
|
let mut variable = vec![];
|
||||||
|
|
||||||
|
for item in self {
|
||||||
|
fixed.append(&mut encode_length(offset));
|
||||||
|
let mut bytes = item.as_ssz_bytes();
|
||||||
|
offset += bytes.len();
|
||||||
|
variable.append(&mut bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed.append(&mut variable);
|
||||||
|
|
||||||
|
fixed
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.drain()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +144,7 @@ mod tests {
|
|||||||
use crate::ssz_encode;
|
use crate::ssz_encode;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vec_of_u8() {
|
fn vec_of_u8() {
|
||||||
let vec: Vec<u8> = vec![];
|
let vec: Vec<u8> = vec![];
|
||||||
assert_eq!(vec.as_ssz_bytes(), vec![]);
|
assert_eq!(vec.as_ssz_bytes(), vec![]);
|
||||||
|
|
||||||
@ -139,19 +156,22 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vec_of_vec_of_u8() {
|
fn vec_of_vec_of_u8() {
|
||||||
let vec: Vec<Vec<u8>> = vec![vec![]];
|
let vec: Vec<Vec<u8>> = vec![vec![]];
|
||||||
assert_eq!(vec.as_ssz_bytes(), vec![0, 0, 0, 0]);
|
assert_eq!(vec.as_ssz_bytes(), vec![4, 0, 0, 0]);
|
||||||
|
|
||||||
|
let vec: Vec<Vec<u8>> = vec![vec![], vec![]];
|
||||||
|
assert_eq!(vec.as_ssz_bytes(), vec![8, 0, 0, 0, 8, 0, 0, 0]);
|
||||||
|
|
||||||
let vec: Vec<Vec<u8>> = vec![vec![0, 1, 2], vec![11, 22, 33]];
|
let vec: Vec<Vec<u8>> = vec![vec![0, 1, 2], vec![11, 22, 33]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec.as_ssz_bytes(),
|
vec.as_ssz_bytes(),
|
||||||
vec![3, 0, 0, 0, 3, 0, 0, 0, 0, 1, 2, 11, 22, 33]
|
vec![8, 0, 0, 0, 11, 0, 0, 0, 0, 1, 2, 11, 22, 33]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_u8() {
|
fn ssz_encode_u8() {
|
||||||
let x: u8 = 0;
|
let x: u8 = 0;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -174,7 +194,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_u16() {
|
fn ssz_encode_u16() {
|
||||||
let x: u16 = 1;
|
let x: u16 = 1;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -197,7 +217,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_u32() {
|
fn ssz_encode_u32() {
|
||||||
let x: u32 = 1;
|
let x: u32 = 1;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -225,7 +245,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_u64() {
|
fn ssz_encode_u64() {
|
||||||
let x: u64 = 1;
|
let x: u64 = 1;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -248,7 +268,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_usize() {
|
fn ssz_encode_usize() {
|
||||||
let x: usize = 1;
|
let x: usize = 1;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -272,7 +292,7 @@ mod tests {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_h256() {
|
fn ssz_encode_h256() {
|
||||||
let h = H256::zero();
|
let h = H256::zero();
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&h);
|
ssz.append(&h);
|
||||||
@ -280,7 +300,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_mixed() {
|
fn ssz_mixed() {
|
||||||
let mut stream = SszStream::new();
|
let mut stream = SszStream::new();
|
||||||
|
|
||||||
let h = H256::zero();
|
let h = H256::zero();
|
||||||
@ -301,7 +321,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_bool() {
|
fn ssz_encode_bool() {
|
||||||
let x: bool = false;
|
let x: bool = false;
|
||||||
let mut ssz = SszStream::new();
|
let mut ssz = SszStream::new();
|
||||||
ssz.append(&x);
|
ssz.append(&x);
|
||||||
@ -314,7 +334,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ssz_encode_u8_array() {
|
fn ssz_encode_u8_array() {
|
||||||
let x: [u8; 4] = [0, 1, 7, 8];
|
let x: [u8; 4] = [0, 1, 7, 8];
|
||||||
let ssz = ssz_encode(&x);
|
let ssz = ssz_encode(&x);
|
||||||
assert_eq!(ssz, vec![0, 1, 7, 8]);
|
assert_eq!(ssz, vec![0, 1, 7, 8]);
|
||||||
|
@ -1,306 +0,0 @@
|
|||||||
use super::decode::decode_ssz_list;
|
|
||||||
use super::ethereum_types::{Address, H256};
|
|
||||||
use super::{Decodable, DecodeError};
|
|
||||||
|
|
||||||
macro_rules! impl_decodable_for_uint {
|
|
||||||
($type: ident, $bit_size: expr) => {
|
|
||||||
impl Decodable for $type {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
assert!((0 < $bit_size) & ($bit_size <= 64) & ($bit_size % 8 == 0));
|
|
||||||
let max_bytes = $bit_size / 8;
|
|
||||||
if bytes.len() >= (index + max_bytes) {
|
|
||||||
let end_bytes = index + max_bytes;
|
|
||||||
let mut result: $type = 0;
|
|
||||||
for (i, byte) in bytes.iter().enumerate().take(end_bytes).skip(index) {
|
|
||||||
let offset = (i - index) * 8;
|
|
||||||
result |= ($type::from(*byte)) << offset;
|
|
||||||
}
|
|
||||||
Ok((result, end_bytes))
|
|
||||||
} else {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_decodable_for_u8_array {
|
|
||||||
($len: expr) => {
|
|
||||||
impl Decodable for [u8; $len] {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
if index + $len > bytes.len() {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
} else {
|
|
||||||
let mut array: [u8; $len] = [0; $len];
|
|
||||||
array.copy_from_slice(&bytes[index..index + $len]);
|
|
||||||
|
|
||||||
Ok((array, index + $len))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_decodable_for_uint!(u16, 16);
|
|
||||||
impl_decodable_for_uint!(u32, 32);
|
|
||||||
impl_decodable_for_uint!(u64, 64);
|
|
||||||
impl_decodable_for_uint!(usize, 64);
|
|
||||||
|
|
||||||
impl_decodable_for_u8_array!(4);
|
|
||||||
|
|
||||||
impl Decodable for u8 {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
if index >= bytes.len() {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
} else {
|
|
||||||
Ok((bytes[index], index + 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for bool {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
if index >= bytes.len() {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
} else {
|
|
||||||
let result = match bytes[index] {
|
|
||||||
0b0000_0000 => false,
|
|
||||||
0b0000_0001 => true,
|
|
||||||
_ => return Err(DecodeError::Invalid),
|
|
||||||
};
|
|
||||||
Ok((result, index + 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for H256 {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
if bytes.len() < 32 || bytes.len() - 32 < index {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
} else {
|
|
||||||
Ok((H256::from_slice(&bytes[index..(index + 32)]), index + 32))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for Address {
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
if bytes.len() < 20 || bytes.len() - 20 < index {
|
|
||||||
Err(DecodeError::TooShort)
|
|
||||||
} else {
|
|
||||||
Ok((Address::from_slice(&bytes[index..(index + 20)]), index + 20))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Decodable for Vec<T>
|
|
||||||
where
|
|
||||||
T: Decodable,
|
|
||||||
{
|
|
||||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
|
|
||||||
decode_ssz_list(bytes, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::super::{decode, DecodeError};
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ssz_decode_h256() {
|
|
||||||
/*
|
|
||||||
* Input is exact length
|
|
||||||
*/
|
|
||||||
let input = vec![42_u8; 32];
|
|
||||||
let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
|
|
||||||
assert_eq!(decoded.as_bytes(), &input[..]);
|
|
||||||
assert_eq!(i, 32);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input is too long
|
|
||||||
*/
|
|
||||||
let mut input = vec![42_u8; 32];
|
|
||||||
input.push(12);
|
|
||||||
let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
|
|
||||||
assert_eq!(decoded.as_bytes(), &input[0..32]);
|
|
||||||
assert_eq!(i, 32);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input is too short
|
|
||||||
*/
|
|
||||||
let input = vec![42_u8; 31];
|
|
||||||
let res = H256::ssz_decode(&input, 0);
|
|
||||||
assert_eq!(res, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ssz_decode_u16() {
|
|
||||||
let ssz = vec![0, 0];
|
|
||||||
|
|
||||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
assert_eq!(index, 2);
|
|
||||||
|
|
||||||
let ssz = vec![16, 0];
|
|
||||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(result, 16);
|
|
||||||
assert_eq!(index, 2);
|
|
||||||
|
|
||||||
let ssz = vec![0, 1];
|
|
||||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(result, 256);
|
|
||||||
assert_eq!(index, 2);
|
|
||||||
|
|
||||||
let ssz = vec![255, 255];
|
|
||||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 2);
|
|
||||||
assert_eq!(result, 65535);
|
|
||||||
|
|
||||||
let ssz = vec![1];
|
|
||||||
let result: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ssz_decode_u32() {
|
|
||||||
let ssz = vec![0, 0, 0, 0];
|
|
||||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
assert_eq!(index, 4);
|
|
||||||
|
|
||||||
let ssz = vec![0, 1, 0, 0];
|
|
||||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 4);
|
|
||||||
assert_eq!(result, 256);
|
|
||||||
|
|
||||||
let ssz = vec![255, 255, 255, 0, 1, 0, 0];
|
|
||||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 3).unwrap();
|
|
||||||
assert_eq!(index, 7);
|
|
||||||
assert_eq!(result, 256);
|
|
||||||
|
|
||||||
let ssz = vec![0, 1, 200, 0];
|
|
||||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 4);
|
|
||||||
assert_eq!(result, 13107456);
|
|
||||||
|
|
||||||
let ssz = vec![255, 255, 255, 255];
|
|
||||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 4);
|
|
||||||
assert_eq!(result, 4294967295);
|
|
||||||
|
|
||||||
let ssz = vec![1, 0, 0];
|
|
||||||
let result: Result<(u32, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ssz_decode_u64() {
|
|
||||||
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
let (result, index): (u64, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 8);
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
|
|
||||||
let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255];
|
|
||||||
let (result, index): (u64, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 8);
|
|
||||||
assert_eq!(result, 18446744073709551615);
|
|
||||||
|
|
||||||
let ssz = vec![0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 255];
|
|
||||||
let (result, index): (u64, usize) = <_>::ssz_decode(&ssz, 3).unwrap();
|
|
||||||
assert_eq!(index, 11);
|
|
||||||
assert_eq!(result, 18374686479671623680);
|
|
||||||
|
|
||||||
let ssz = vec![0, 0, 0, 0, 0, 0, 0];
|
|
||||||
let result: Result<(u64, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_ssz_decode_usize() {
|
|
||||||
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
let (result, index): (usize, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 8);
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
|
|
||||||
let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255];
|
|
||||||
let (result, index): (usize, usize) = <_>::ssz_decode(&ssz, 3).unwrap();
|
|
||||||
assert_eq!(index, 11);
|
|
||||||
assert_eq!(result, 18446744073709551615);
|
|
||||||
|
|
||||||
let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255, 255];
|
|
||||||
let (result, index): (usize, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 8);
|
|
||||||
assert_eq!(result, 18446744073709551615);
|
|
||||||
|
|
||||||
let ssz = vec![0, 0, 0, 0, 0, 0, 1];
|
|
||||||
let result: Result<(usize, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_decode_ssz_bounds() {
|
|
||||||
let err: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&vec![1], 2);
|
|
||||||
assert_eq!(err, Err(DecodeError::TooShort));
|
|
||||||
|
|
||||||
let err: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&vec![0, 0, 0, 0], 3);
|
|
||||||
assert_eq!(err, Err(DecodeError::TooShort));
|
|
||||||
|
|
||||||
let result: u16 = <_>::ssz_decode(&vec![0, 0, 0, 1, 0], 3).unwrap().0;
|
|
||||||
assert_eq!(result, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_decode_ssz_bool() {
|
|
||||||
let ssz = vec![0b0000_0000, 0b0000_0001];
|
|
||||||
let (result, index): (bool, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
|
||||||
assert_eq!(index, 1);
|
|
||||||
assert_eq!(result, false);
|
|
||||||
|
|
||||||
let (result, index): (bool, usize) = <_>::ssz_decode(&ssz, 1).unwrap();
|
|
||||||
assert_eq!(index, 2);
|
|
||||||
assert_eq!(result, true);
|
|
||||||
|
|
||||||
let ssz = vec![0b0100_0000];
|
|
||||||
let result: Result<(bool, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::Invalid));
|
|
||||||
|
|
||||||
let ssz = vec![];
|
|
||||||
let result: Result<(bool, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
|
||||||
assert_eq!(result, Err(DecodeError::TooShort));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_decode_ssz_list_underflow() {
|
|
||||||
// SSZ encoded (u16::[1, 1, 1], u16::2)
|
|
||||||
let mut encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2, 0];
|
|
||||||
let (decoded_array, i): (Vec<u16>, usize) = <_>::ssz_decode(&encoded, 0).unwrap();
|
|
||||||
let (decoded_u16, i): (u16, usize) = <_>::ssz_decode(&encoded, i).unwrap();
|
|
||||||
assert_eq!(decoded_array, vec![1, 1, 1]);
|
|
||||||
assert_eq!(decoded_u16, 2);
|
|
||||||
assert_eq!(i, 12);
|
|
||||||
|
|
||||||
// Underflow
|
|
||||||
encoded[0] = 4; // change length to 4 from 6
|
|
||||||
let (decoded_array, i): (Vec<u16>, usize) = <_>::ssz_decode(&encoded, 0).unwrap();
|
|
||||||
let (decoded_u16, _): (u16, usize) = <_>::ssz_decode(&encoded, i).unwrap();
|
|
||||||
assert_eq!(decoded_array, vec![1, 1]);
|
|
||||||
assert_eq!(decoded_u16, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_decode_too_long() {
|
|
||||||
let encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2];
|
|
||||||
let decoded_array: Result<Vec<u16>, DecodeError> = decode(&encoded);
|
|
||||||
assert_eq!(decoded_array, Err(DecodeError::TooLong));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_decode_u8_array() {
|
|
||||||
let ssz = vec![0, 1, 2, 3];
|
|
||||||
let result: [u8; 4] = decode(&ssz).unwrap();
|
|
||||||
assert_eq!(result.len(), 4);
|
|
||||||
assert_eq!(result, [0, 1, 2, 3]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,8 +13,10 @@ extern crate ethereum_types;
|
|||||||
|
|
||||||
pub mod decode;
|
pub mod decode;
|
||||||
*/
|
*/
|
||||||
|
mod decode;
|
||||||
mod encode;
|
mod encode;
|
||||||
|
|
||||||
|
pub use decode::{Decodable, DecodeError};
|
||||||
pub use encode::{Encodable, SszStream};
|
pub use encode::{Encodable, SszStream};
|
||||||
|
|
||||||
pub const BYTES_PER_LENGTH_OFFSET: usize = 4;
|
pub const BYTES_PER_LENGTH_OFFSET: usize = 4;
|
||||||
|
22
eth2/utils/ssz2/tests/tests.rs
Normal file
22
eth2/utils/ssz2/tests/tests.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use ssz2::{Decodable, Encodable};
|
||||||
|
|
||||||
|
fn round_trip<T: Encodable + Decodable + std::fmt::Debug + PartialEq>(item: T) {
|
||||||
|
let encoded = &item.as_ssz_bytes();
|
||||||
|
dbg!(encoded);
|
||||||
|
assert_eq!(T::from_ssz_bytes(&encoded), Ok(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_u16_round_trip() {
|
||||||
|
round_trip::<Vec<u16>>(vec![]);
|
||||||
|
round_trip::<Vec<u16>>(vec![255]);
|
||||||
|
round_trip::<Vec<u16>>(vec![0, 1, 2]);
|
||||||
|
round_trip::<Vec<u16>>(vec![100; 64]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_of_vec_u16_round_trip() {
|
||||||
|
// round_trip::<Vec<Vec<u16>>>(vec![]);
|
||||||
|
round_trip::<Vec<Vec<u16>>>(vec![vec![]]);
|
||||||
|
// round_trip::<Vec<Vec<u16>>>(vec![vec![], vec![]]);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user