ssz_rs 0.1.0

ethereum's simple serialize
Documentation
use crate::ser::BYTES_PER_LENGTH_OFFSET;
use crate::SimpleSerialize;
use thiserror::Error;

#[derive(Error, Debug)]
#[error("the value could not be deserialized: {0}")]
pub enum DeserializeError {
    #[error("expected further data when decoding")]
    InputTooShort,
    #[error("unexpected additional data provided when decoding")]
    ExtraInput,
    #[error("invalid data for expected type")]
    InvalidInput,
    #[error("{0}")]
    IOError(#[from] std::io::Error),
    #[error("the type for this value has a bound of {bound} but the value has {len} elements")]
    TypeBoundsViolated { bound: usize, len: usize },
    #[error("the type for this value has an illegal bound of {bound}")]
    IllegalType { bound: usize },
}

pub trait Deserialize {
    fn deserialize(encoding: &[u8]) -> Result<Self, DeserializeError>
    where
        Self: Sized;
}

fn deserialize_fixed_homogeneous_composite<T>(encoding: &[u8]) -> Result<Vec<T>, DeserializeError>
where
    T: SimpleSerialize,
{
    if encoding.len() % T::size_hint() != 0 {
        return Err(DeserializeError::InvalidInput);
    }

    let mut elements = vec![];
    for chunk in encoding.chunks_exact(T::size_hint()) {
        let element = T::deserialize(chunk)?;
        elements.push(element);
    }
    Ok(elements)
}

fn deserialize_variable_homogeneous_composite<T>(
    encoding: &[u8],
) -> Result<Vec<T>, DeserializeError>
where
    T: SimpleSerialize,
{
    let data_pointer = u32::deserialize(&encoding[..BYTES_PER_LENGTH_OFFSET])?;
    let data_pointer = data_pointer as usize;
    if encoding.len() < data_pointer {
        return Err(DeserializeError::InputTooShort);
    }

    let offsets = &mut encoding[..data_pointer]
        .chunks_exact(BYTES_PER_LENGTH_OFFSET)
        .map(|chunk| u32::deserialize(chunk).map(|offset| offset as usize))
        .collect::<Result<Vec<usize>, DeserializeError>>()?;
    offsets.push(encoding.len());

    let element_count = data_pointer as usize / BYTES_PER_LENGTH_OFFSET;
    let mut result = Vec::with_capacity(element_count);
    for span in offsets.windows(2) {
        let start = span[0];
        let end = span[1];
        let element = T::deserialize(&encoding[start..end])?;
        result.push(element);
    }
    Ok(result)
}

pub fn deserialize_homogeneous_composite<T>(encoding: &[u8]) -> Result<Vec<T>, DeserializeError>
where
    T: SimpleSerialize,
{
    if T::is_variable_size() {
        deserialize_variable_homogeneous_composite(encoding)
    } else {
        deserialize_fixed_homogeneous_composite(encoding)
    }
}