diff --git a/consensus/ssz_derive/src/lib.rs b/consensus/ssz_derive/src/lib.rs index 40d63fd02..9f8270e6d 100644 --- a/consensus/ssz_derive/src/lib.rs +++ b/consensus/ssz_derive/src/lib.rs @@ -147,7 +147,7 @@ use darling::{FromDeriveInput, FromMeta}; use proc_macro::TokenStream; use quote::quote; use std::convert::TryInto; -use syn::{parse_macro_input, DataEnum, DataStruct, DeriveInput, Ident}; +use syn::{parse_macro_input, DataEnum, DataStruct, DeriveInput, Ident, Index}; /// The highest possible union selector value (higher values are reserved for backwards compatible /// extensions). @@ -442,11 +442,15 @@ fn ssz_encode_derive_struct_transparent( ); } - let (ty, ident, _field_opts) = ssz_fields + let (index, (ty, ident, _field_opts)) = ssz_fields .iter() - .find(|(_, _, field_opts)| !field_opts.skip_deserializing) + .enumerate() + .find(|(_, (_, _, field_opts))| !field_opts.skip_deserializing) .expect("\"transparent\" struct must have at least one non-skipped field"); + // Remove the `_usize` suffix from the value to avoid a compiler warning. + let index = Index::from(index); + let output = if let Some(field_name) = ident { quote! { impl #impl_generics ssz::Encode for #name #ty_generics #where_clause { @@ -479,11 +483,11 @@ fn ssz_encode_derive_struct_transparent( } fn ssz_bytes_len(&self) -> usize { - self.0.ssz_bytes_len() + self.#index.ssz_bytes_len() } fn ssz_append(&self, buf: &mut Vec) { - self.0.ssz_append(buf) + self.#index.ssz_append(buf) } } } diff --git a/consensus/ssz_derive/tests/tests.rs b/consensus/ssz_derive/tests/tests.rs index 2eeb3a48d..040d2a347 100644 --- a/consensus/ssz_derive/tests/tests.rs +++ b/consensus/ssz_derive/tests/tests.rs @@ -213,3 +213,24 @@ fn transparent_struct_newtype_skipped_field() { &vec![42_u8].as_ssz_bytes(), ); } + +#[derive(PartialEq, Debug, Encode, Decode)] +#[ssz(struct_behaviour = "transparent")] +struct TransparentStructNewTypeSkippedFieldReverse( + #[ssz(skip_serializing, skip_deserializing)] PhantomData, + Vec, +); + +impl TransparentStructNewTypeSkippedFieldReverse { + fn new(inner: Vec) -> Self { + Self(PhantomData, inner) + } +} + +#[test] +fn transparent_struct_newtype_skipped_field_reverse() { + assert_encode_decode( + &TransparentStructNewTypeSkippedFieldReverse::new(vec![42_u8]), + &vec![42_u8].as_ssz_bytes(), + ); +}