ssz: implement Encode and Decode for tuples
This commit is contained in:
parent
73c4171b52
commit
44ed3228b9
@ -41,6 +41,153 @@ impl_decodable_for_uint!(usize, 32);
|
|||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
impl_decodable_for_uint!(usize, 64);
|
impl_decodable_for_uint!(usize, 64);
|
||||||
|
|
||||||
|
macro_rules! impl_decode_for_tuples {
|
||||||
|
($(
|
||||||
|
$Tuple:ident {
|
||||||
|
$(($idx:tt) -> $T:ident)+
|
||||||
|
}
|
||||||
|
)+) => {
|
||||||
|
$(
|
||||||
|
impl<$($T: Decode),+> Decode for ($($T,)+) {
|
||||||
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
$(
|
||||||
|
<$T as Decode>::is_ssz_fixed_len() &&
|
||||||
|
)*
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssz_fixed_len() -> usize {
|
||||||
|
if <Self as Decode>::is_ssz_fixed_len() {
|
||||||
|
$(
|
||||||
|
<$T as Decode>::ssz_fixed_len() +
|
||||||
|
)*
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
BYTES_PER_LENGTH_OFFSET
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let mut builder = SszDecoderBuilder::new(bytes);
|
||||||
|
|
||||||
|
$(
|
||||||
|
builder.register_type::<$T>()?;
|
||||||
|
)*
|
||||||
|
|
||||||
|
let mut decoder = builder.build()?;
|
||||||
|
|
||||||
|
Ok(($(
|
||||||
|
decoder.decode_next::<$T>()?,
|
||||||
|
)*
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_decode_for_tuples! {
|
||||||
|
Tuple2 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
}
|
||||||
|
Tuple3 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
}
|
||||||
|
Tuple4 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
}
|
||||||
|
Tuple5 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
}
|
||||||
|
Tuple6 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
}
|
||||||
|
Tuple7 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
}
|
||||||
|
Tuple8 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
}
|
||||||
|
Tuple9 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
}
|
||||||
|
Tuple10 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
}
|
||||||
|
Tuple11 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
(10) -> K
|
||||||
|
}
|
||||||
|
Tuple12 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
(10) -> K
|
||||||
|
(11) -> L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Decode for bool {
|
impl Decode for bool {
|
||||||
fn is_ssz_fixed_len() -> bool {
|
fn is_ssz_fixed_len() -> bool {
|
||||||
true
|
true
|
||||||
@ -520,4 +667,15 @@ mod tests {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple() {
|
||||||
|
assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 0, 0, 0]), Ok((0, 0)));
|
||||||
|
assert_eq!(<(u16, u16)>::from_ssz_bytes(&[16, 0, 17, 0]), Ok((16, 17)));
|
||||||
|
assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 1, 2, 0]), Ok((256, 2)));
|
||||||
|
assert_eq!(
|
||||||
|
<(u16, u16)>::from_ssz_bytes(&[255, 255, 0, 0]),
|
||||||
|
Ok((65535, 0))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,154 @@ impl_encodable_for_uint!(usize, 32);
|
|||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
impl_encodable_for_uint!(usize, 64);
|
impl_encodable_for_uint!(usize, 64);
|
||||||
|
|
||||||
|
// Based on the `tuple_impls` macro from the standard library.
|
||||||
|
macro_rules! impl_encode_for_tuples {
|
||||||
|
($(
|
||||||
|
$Tuple:ident {
|
||||||
|
$(($idx:tt) -> $T:ident)+
|
||||||
|
}
|
||||||
|
)+) => {
|
||||||
|
$(
|
||||||
|
impl<$($T: Encode),+> Encode for ($($T,)+) {
|
||||||
|
fn is_ssz_fixed_len() -> bool {
|
||||||
|
$(
|
||||||
|
<$T as Encode>::is_ssz_fixed_len() &&
|
||||||
|
)*
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssz_fixed_len() -> usize {
|
||||||
|
if <Self as Encode>::is_ssz_fixed_len() {
|
||||||
|
$(
|
||||||
|
<$T as Encode>::ssz_fixed_len() +
|
||||||
|
)*
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
BYTES_PER_LENGTH_OFFSET
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
|
let offset = $(
|
||||||
|
<$T as Encode>::ssz_fixed_len() +
|
||||||
|
)*
|
||||||
|
0;
|
||||||
|
|
||||||
|
let mut encoder = SszEncoder::container(buf, offset);
|
||||||
|
|
||||||
|
$(
|
||||||
|
encoder.append(&self.$idx);
|
||||||
|
)*
|
||||||
|
|
||||||
|
encoder.finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_encode_for_tuples! {
|
||||||
|
Tuple2 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
}
|
||||||
|
Tuple3 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
}
|
||||||
|
Tuple4 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
}
|
||||||
|
Tuple5 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
}
|
||||||
|
Tuple6 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
}
|
||||||
|
Tuple7 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
}
|
||||||
|
Tuple8 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
}
|
||||||
|
Tuple9 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
}
|
||||||
|
Tuple10 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
}
|
||||||
|
Tuple11 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
(10) -> K
|
||||||
|
}
|
||||||
|
Tuple12 {
|
||||||
|
(0) -> A
|
||||||
|
(1) -> B
|
||||||
|
(2) -> C
|
||||||
|
(3) -> D
|
||||||
|
(4) -> E
|
||||||
|
(5) -> F
|
||||||
|
(6) -> G
|
||||||
|
(7) -> H
|
||||||
|
(8) -> I
|
||||||
|
(9) -> J
|
||||||
|
(10) -> K
|
||||||
|
(11) -> L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The SSZ "union" type.
|
/// The SSZ "union" type.
|
||||||
impl<T: Encode> Encode for Option<T> {
|
impl<T: Encode> Encode for Option<T> {
|
||||||
fn is_ssz_fixed_len() -> bool {
|
fn is_ssz_fixed_len() -> bool {
|
||||||
@ -292,4 +440,11 @@ mod tests {
|
|||||||
assert_eq!([1, 0, 0, 0].as_ssz_bytes(), vec![1, 0, 0, 0]);
|
assert_eq!([1, 0, 0, 0].as_ssz_bytes(), vec![1, 0, 0, 0]);
|
||||||
assert_eq!([1, 2, 3, 4].as_ssz_bytes(), vec![1, 2, 3, 4]);
|
assert_eq!([1, 2, 3, 4].as_ssz_bytes(), vec![1, 2, 3, 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple() {
|
||||||
|
assert_eq!((10u8, 11u8).as_ssz_bytes(), vec![10, 11]);
|
||||||
|
assert_eq!((10u32, 11u8).as_ssz_bytes(), vec![10, 0, 0, 0, 11]);
|
||||||
|
assert_eq!((10u8, 11u8, 12u8).as_ssz_bytes(), vec![10, 11, 12]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,4 +346,34 @@ mod round_trip {
|
|||||||
|
|
||||||
round_trip(vec);
|
round_trip(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple_u8_u16() {
|
||||||
|
let vec: Vec<(u8, u16)> = vec![
|
||||||
|
(0, 0),
|
||||||
|
(0, 1),
|
||||||
|
(1, 0),
|
||||||
|
(u8::max_value(), u16::max_value()),
|
||||||
|
(0, u16::max_value()),
|
||||||
|
(u8::max_value(), 0),
|
||||||
|
(42, 12301),
|
||||||
|
];
|
||||||
|
|
||||||
|
round_trip(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple_vec_vec() {
|
||||||
|
let vec: Vec<(u64, Vec<u8>, Vec<Vec<u16>>)> = vec![
|
||||||
|
(0, vec![], vec![vec![]]),
|
||||||
|
(99, vec![101], vec![vec![], vec![]]),
|
||||||
|
(
|
||||||
|
42,
|
||||||
|
vec![12, 13, 14],
|
||||||
|
vec![vec![99, 98, 97, 96], vec![42, 44, 46, 48, 50]],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
round_trip(vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user