Simplify SOS vec decoding

This commit is contained in:
Paul Hauner 2019-05-03 14:02:00 +10:00
parent 6d721813f1
commit 90d8afd64b
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6

View File

@ -39,34 +39,34 @@ impl<T: Decodable> Decodable for Vec<T> {
} }
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
// Zero-bytes indicates an empty list.
if bytes.len() == 0 { if bytes.len() == 0 {
return Ok(vec![]); return Ok(vec![]);
} }
// The list is non-empty. // Decode a non-empty list differently, depending if the items in the vec are fixed-length
// or variable-length.
if T::is_ssz_fixed_len() { if T::is_ssz_fixed_len() {
Ok(bytes Ok(bytes
.chunks(T::ssz_fixed_len()) .chunks(T::ssz_fixed_len())
.map(|chunk| T::from_ssz_bytes(chunk)) .map(|chunk| T::from_ssz_bytes(chunk))
.collect::<Result<_, DecodeError>>()?) .collect::<Result<_, DecodeError>>()?)
} else { } else {
let (fixed, variable) = bytes.split_at(read_length(bytes)?); let mut next_variable_byte = read_offset(bytes)?;
let num_elems = fixed.len() / BYTES_PER_LENGTH_OFFSET; let mut values = Vec::with_capacity(next_variable_byte / BYTES_PER_LENGTH_OFFSET);
let mut offset = 0;
let mut values = vec![];
for i in 1..=num_elems { for i in 1..=values.capacity() {
let slice = if i == num_elems { let slice = if i == values.capacity() {
&variable[offset..] &bytes[next_variable_byte..]
} else { } else {
let chunk = let offset = decode_offset(
&bytes[i * BYTES_PER_LENGTH_OFFSET..(i + 1) * BYTES_PER_LENGTH_OFFSET]; &bytes[i * BYTES_PER_LENGTH_OFFSET..(i + 1) * BYTES_PER_LENGTH_OFFSET],
let start = offset; )?;
offset = decode_length(chunk)? - fixed.len(); let start = next_variable_byte;
next_variable_byte = offset;
&variable[start..offset] &bytes[start..next_variable_byte]
}; };
values.push(T::from_ssz_bytes(slice)?); values.push(T::from_ssz_bytes(slice)?);
@ -79,8 +79,8 @@ impl<T: Decodable> Decodable for Vec<T> {
/// Reads a `BYTES_PER_LENGTH_OFFSET`-byte length from `bytes`, where `bytes.len() >= /// Reads a `BYTES_PER_LENGTH_OFFSET`-byte length from `bytes`, where `bytes.len() >=
/// BYTES_PER_LENGTH_OFFSET`. /// BYTES_PER_LENGTH_OFFSET`.
fn read_length(bytes: &[u8]) -> Result<usize, DecodeError> { fn read_offset(bytes: &[u8]) -> Result<usize, DecodeError> {
decode_length(bytes.get(0..BYTES_PER_LENGTH_OFFSET).ok_or_else(|| { decode_offset(bytes.get(0..BYTES_PER_LENGTH_OFFSET).ok_or_else(|| {
DecodeError::InvalidLengthPrefix { DecodeError::InvalidLengthPrefix {
len: bytes.len(), len: bytes.len(),
expected: BYTES_PER_LENGTH_OFFSET, expected: BYTES_PER_LENGTH_OFFSET,
@ -90,7 +90,7 @@ fn read_length(bytes: &[u8]) -> Result<usize, DecodeError> {
/// Decode bytes as a little-endian usize, returning an `Err` if `bytes.len() != /// Decode bytes as a little-endian usize, returning an `Err` if `bytes.len() !=
/// BYTES_PER_LENGTH_OFFSET`. /// BYTES_PER_LENGTH_OFFSET`.
pub fn decode_length(bytes: &[u8]) -> Result<usize, DecodeError> { pub fn decode_offset(bytes: &[u8]) -> Result<usize, DecodeError> {
let len = bytes.len(); let len = bytes.len();
let expected = BYTES_PER_LENGTH_OFFSET; let expected = BYTES_PER_LENGTH_OFFSET;