mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-17 04:48:21 +00:00
Add ssz_fixed_len method to ssz::Encode
This commit is contained in:
@@ -27,6 +27,8 @@ pub trait Encode {
|
||||
BYTES_PER_LENGTH_OFFSET
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize;
|
||||
|
||||
/// Returns the full-form encoding of this object.
|
||||
///
|
||||
/// The default implementation of this method should suffice for most cases.
|
||||
|
||||
@@ -13,6 +13,10 @@ macro_rules! impl_encodable_for_uint {
|
||||
$bit_size / 8
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
$bit_size / 8
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(&self.to_le_bytes());
|
||||
}
|
||||
@@ -58,6 +62,23 @@ macro_rules! impl_encode_for_tuples {
|
||||
}
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
if <Self as Encode>::is_ssz_fixed_len() {
|
||||
<Self as Encode>::ssz_fixed_len()
|
||||
} else {
|
||||
let mut len = 0;
|
||||
$(
|
||||
len += if <$T as Encode>::is_ssz_fixed_len() {
|
||||
<$T as Encode>::ssz_fixed_len()
|
||||
} else {
|
||||
BYTES_PER_LENGTH_OFFSET +
|
||||
self.$idx.ssz_bytes_len()
|
||||
};
|
||||
)*
|
||||
len
|
||||
}
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
let offset = $(
|
||||
<$T as Encode>::ssz_fixed_len() +
|
||||
@@ -185,6 +206,19 @@ impl<T: Encode> Encode for Option<T> {
|
||||
false
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
if let Some(some) = self {
|
||||
let len = if <T as Encode>::is_ssz_fixed_len() {
|
||||
<T as Encode>::ssz_fixed_len()
|
||||
} else {
|
||||
some.ssz_bytes_len()
|
||||
};
|
||||
len + BYTES_PER_LENGTH_OFFSET
|
||||
} else {
|
||||
BYTES_PER_LENGTH_OFFSET
|
||||
}
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
match self {
|
||||
None => buf.append(&mut encode_union_index(0)),
|
||||
@@ -201,6 +235,16 @@ impl<T: Encode> Encode for Vec<T> {
|
||||
false
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
if <T as Encode>::is_ssz_fixed_len() {
|
||||
<T as Encode>::ssz_fixed_len() * self.len()
|
||||
} else {
|
||||
let mut len = self.into_iter().map(|item| item.ssz_bytes_len()).sum();
|
||||
len += BYTES_PER_LENGTH_OFFSET * self.len();
|
||||
len
|
||||
}
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
if T::is_ssz_fixed_len() {
|
||||
buf.reserve(T::ssz_fixed_len() * self.len());
|
||||
@@ -229,6 +273,10 @@ impl Encode for bool {
|
||||
1
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(&(*self as u8).to_le_bytes());
|
||||
}
|
||||
@@ -243,6 +291,10 @@ impl Encode for NonZeroUsize {
|
||||
<usize as Encode>::ssz_fixed_len()
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
std::mem::size_of::<usize>()
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
self.get().ssz_append(buf)
|
||||
}
|
||||
@@ -257,6 +309,10 @@ impl Encode for H256 {
|
||||
32
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
32
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(self.as_bytes());
|
||||
}
|
||||
@@ -271,6 +327,10 @@ impl Encode for U256 {
|
||||
32
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
32
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
let n = <Self as Encode>::ssz_fixed_len();
|
||||
let s = buf.len();
|
||||
@@ -289,6 +349,10 @@ impl Encode for U128 {
|
||||
16
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
16
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
let n = <Self as Encode>::ssz_fixed_len();
|
||||
let s = buf.len();
|
||||
@@ -309,6 +373,10 @@ macro_rules! impl_encodable_for_u8_array {
|
||||
$len
|
||||
}
|
||||
|
||||
fn ssz_bytes_len(&self) -> usize {
|
||||
$len
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
buf.extend_from_slice(&self[..]);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
mod decode;
|
||||
mod encode;
|
||||
mod macros;
|
||||
|
||||
pub use decode::{
|
||||
impls::decode_list_of_variable_length_items, Decode, DecodeError, SszDecoder, SszDecoderBuilder,
|
||||
|
||||
@@ -1,96 +1 @@
|
||||
/// Implements `Encode` for `$impl_type` using an implementation of `From<$impl_type> for
|
||||
/// $from_type`.
|
||||
///
|
||||
/// In effect, this allows for easy implementation of `Encode` for some type that implements a
|
||||
/// `From` conversion into another type that already has `Encode` implemented.
|
||||
#[macro_export]
|
||||
macro_rules! impl_encode_via_from {
|
||||
($impl_type: ty, $from_type: ty) => {
|
||||
impl ssz::Encode for $impl_type {
|
||||
fn is_ssz_fixed_len() -> bool {
|
||||
<$from_type as ssz::Encode>::is_ssz_fixed_len()
|
||||
}
|
||||
|
||||
fn ssz_fixed_len() -> usize {
|
||||
<$from_type as ssz::Encode>::ssz_fixed_len()
|
||||
}
|
||||
|
||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||
let conv: $from_type = self.clone().into();
|
||||
|
||||
conv.ssz_append(buf)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implements `Decode` for `$impl_type` using an implementation of `From<$impl_type> for
|
||||
/// $from_type`.
|
||||
///
|
||||
/// In effect, this allows for easy implementation of `Decode` for some type that implements a
|
||||
/// `From` conversion into another type that already has `Decode` implemented.
|
||||
#[macro_export]
|
||||
macro_rules! impl_decode_via_from {
|
||||
($impl_type: ty, $from_type: tt) => {
|
||||
impl ssz::Decode for $impl_type {
|
||||
fn is_ssz_fixed_len() -> bool {
|
||||
<$from_type as ssz::Decode>::is_ssz_fixed_len()
|
||||
}
|
||||
|
||||
fn ssz_fixed_len() -> usize {
|
||||
<$from_type as ssz::Decode>::ssz_fixed_len()
|
||||
}
|
||||
|
||||
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
$from_type::from_ssz_bytes(bytes).and_then(|dec| Ok(dec.into()))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use self::ssz::{Decode, Encode};
|
||||
use crate as ssz;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
struct Wrapper(u64);
|
||||
|
||||
impl From<u64> for Wrapper {
|
||||
fn from(x: u64) -> Wrapper {
|
||||
Wrapper(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Wrapper> for u64 {
|
||||
fn from(x: Wrapper) -> u64 {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
|
||||
impl_encode_via_from!(Wrapper, u64);
|
||||
impl_decode_via_from!(Wrapper, u64);
|
||||
|
||||
#[test]
|
||||
fn impl_encode_via_from() {
|
||||
let check_encode = |a: u64, b: Wrapper| assert_eq!(a.as_ssz_bytes(), b.as_ssz_bytes());
|
||||
|
||||
check_encode(0, Wrapper(0));
|
||||
check_encode(1, Wrapper(1));
|
||||
check_encode(42, Wrapper(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_decode_via_from() {
|
||||
let check_decode = |bytes: Vec<u8>| {
|
||||
let a = u64::from_ssz_bytes(&bytes).unwrap();
|
||||
let b = Wrapper::from_ssz_bytes(&bytes).unwrap();
|
||||
|
||||
assert_eq!(a, b.into())
|
||||
};
|
||||
|
||||
check_decode(vec![0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
check_decode(vec![1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
check_decode(vec![1, 0, 0, 0, 2, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user