Update SSZ derive macro, create failing test
This commit is contained in:
		
							parent
							
								
									b5d9157722
								
							
						
					
					
						commit
						c5f00d1666
					
				| @ -1,5 +1,5 @@ | ||||
| use ssz::{Decodable, Encodable}; | ||||
| use ssz_derive::Encode; | ||||
| use ssz_derive::{Decode, Encode}; | ||||
| 
 | ||||
| fn round_trip<T: Encodable + Decodable + std::fmt::Debug + PartialEq>(items: Vec<T>) { | ||||
|     for item in items { | ||||
| @ -40,7 +40,7 @@ fn vec_of_vec_u16_round_trip() { | ||||
|     round_trip(items); | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Encode)] | ||||
| #[derive(Debug, PartialEq, Encode, Decode)] | ||||
| struct FixedLen { | ||||
|     a: u16, | ||||
|     b: u64, | ||||
| @ -72,7 +72,18 @@ fn fixed_len_struct_encoding() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Encode)] | ||||
| #[test] | ||||
| fn vec_of_fixed_len_struct() { | ||||
|     let items: Vec<FixedLen> = vec![ | ||||
|         FixedLen { a: 0, b: 0, c: 0 }, | ||||
|         FixedLen { a: 1, b: 1, c: 1 }, | ||||
|         FixedLen { a: 1, b: 0, c: 1 }, | ||||
|     ]; | ||||
| 
 | ||||
|     round_trip(items); | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Encode, Decode)] | ||||
| struct VariableLen { | ||||
|     a: u16, | ||||
|     b: Vec<u16>, | ||||
| @ -119,15 +130,30 @@ fn variable_len_struct_encoding() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| #[test] | ||||
| fn vec_of_fixed_len_struct() { | ||||
|     let items: Vec<FixedLen> = vec![ | ||||
|         FixedLen { a: 0, b: 0, c: 0 }, | ||||
|         FixedLen { a: 1, b: 1, c: 1 }, | ||||
|         FixedLen { a: 1, b: 0, c: 1 }, | ||||
| fn vec_of_variable_len_struct() { | ||||
|     let items: Vec<VariableLen> = vec![ | ||||
|         VariableLen { | ||||
|             a: 0, | ||||
|             b: vec![], | ||||
|             c: 0, | ||||
|         }, | ||||
|         VariableLen { | ||||
|             a: 255, | ||||
|             b: vec![0, 1, 2, 3], | ||||
|             c: 99, | ||||
|         }, | ||||
|         VariableLen { | ||||
|             a: 255, | ||||
|             b: vec![0], | ||||
|             c: 99, | ||||
|         }, | ||||
|         VariableLen { | ||||
|             a: 50, | ||||
|             b: vec![0], | ||||
|             c: 0, | ||||
|         }, | ||||
|     ]; | ||||
| 
 | ||||
|     round_trip(items); | ||||
| } | ||||
| */ | ||||
|  | ||||
| @ -1,26 +1,11 @@ | ||||
| #![recursion_limit="128"] | ||||
| 
 | ||||
| extern crate proc_macro; | ||||
| 
 | ||||
| use proc_macro::TokenStream; | ||||
| use quote::quote; | ||||
| use syn::{parse_macro_input, DeriveInput}; | ||||
| 
 | ||||
| /* | ||||
| /// Returns a Vec of `syn::Ident` for each named field in the struct.
 | ||||
| ///
 | ||||
| /// # Panics
 | ||||
| /// Any unnamed struct field (like in a tuple struct) will raise a panic at compile time.
 | ||||
| fn get_named_field_idents<'a>(struct_data: &'a syn::DataStruct) -> Vec<&'a syn::Ident> { | ||||
|     struct_data | ||||
|         .fields | ||||
|         .iter() | ||||
|         .map(|f| match &f.ident { | ||||
|             Some(ref ident) => ident, | ||||
|             _ => panic!("ssz_derive only supports named struct fields."), | ||||
|         }) | ||||
|         .collect() | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| /// Returns a Vec of `syn::Ident` for each named field in the struct, whilst filtering out fields
 | ||||
| /// that should not be serialized.
 | ||||
| ///
 | ||||
| @ -45,12 +30,9 @@ fn get_serializable_named_field_idents<'a>( | ||||
|         .collect() | ||||
| } | ||||
| 
 | ||||
| /// Returns a Vec of `syn::Ident` for each named field in the struct, whilst filtering out fields
 | ||||
| /// Returns a Vec of `syn::Type` for each named field in the struct, whilst filtering out fields
 | ||||
| /// that should not be serialized.
 | ||||
| ///
 | ||||
| /// # Panics
 | ||||
| /// Any unnamed struct field (like in a tuple struct) will raise a panic at compile time.
 | ||||
| fn get_serializable_named_field_types<'a>(struct_data: &'a syn::DataStruct) -> Vec<&'a syn::Type> { | ||||
| fn get_serializable_field_types<'a>(struct_data: &'a syn::DataStruct) -> Vec<&'a syn::Type> { | ||||
|     struct_data | ||||
|         .fields | ||||
|         .iter() | ||||
| @ -97,7 +79,7 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream { | ||||
|     }; | ||||
| 
 | ||||
|     let field_idents = get_serializable_named_field_idents(&struct_data); | ||||
|     let field_types_a = get_serializable_named_field_types(&struct_data); | ||||
|     let field_types_a = get_serializable_field_types(&struct_data); | ||||
|     let field_types_b = field_types_a.clone(); | ||||
| 
 | ||||
|     let output = quote! { | ||||
| @ -110,7 +92,7 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream { | ||||
|             } | ||||
| 
 | ||||
|             fn ssz_fixed_len() -> usize { | ||||
|                 if Self::is_ssz_fixed_len() { | ||||
|                 if <Self as Encodable>::is_ssz_fixed_len() { | ||||
|                     #( | ||||
|                         <#field_types_b as ssz::Encodable>::ssz_fixed_len() + | ||||
|                     )* | ||||
| @ -134,7 +116,6 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream { | ||||
|     output.into() | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| /// Returns true if some field has an attribute declaring it should not be deserialized.
 | ||||
| ///
 | ||||
| /// The field attribute is: `#[ssz(skip_deserializing)]`
 | ||||
| @ -161,21 +142,38 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream { | ||||
|         _ => panic!("ssz_derive only supports structs."), | ||||
|     }; | ||||
| 
 | ||||
|     let all_idents = get_named_field_idents(&struct_data); | ||||
|     let mut register_types = vec![]; | ||||
|     let mut decodes = vec![]; | ||||
|     let mut is_fixed_lens = vec![]; | ||||
|     let mut fixed_lens = vec![]; | ||||
| 
 | ||||
|     // Build quotes for fields that should be deserialized and those that should be built from
 | ||||
|     // `Default`.
 | ||||
|     let mut quotes = vec![]; | ||||
|     for field in &struct_data.fields { | ||||
|         match &field.ident { | ||||
|             Some(ref ident) => { | ||||
|                 if should_skip_deserializing(field) { | ||||
|                     quotes.push(quote! { | ||||
|                         let #ident = <_>::default(); | ||||
|                     // Field should not be deserialized; use a `Default` impl to instantiate.
 | ||||
|                     decodes.push(quote! { | ||||
|                         #ident: <_>::default(), | ||||
|                     }); | ||||
|                 } else { | ||||
|                     quotes.push(quote! { | ||||
|                         let (#ident, i) = <_>::ssz_decode(bytes, i)?; | ||||
|                     let ty = &field.ty; | ||||
| 
 | ||||
|                     register_types.push(quote! { | ||||
|                         builder.register_type::<#ty>()?; | ||||
|                     }); | ||||
| 
 | ||||
|                     decodes.push(quote! { | ||||
|                         #ident: decoder.decode_next()? | ||||
|                     }); | ||||
| 
 | ||||
|                     is_fixed_lens.push(quote! { | ||||
|                         <#ty as ssz::Decodable>::is_ssz_fixed_len() | ||||
|                     }); | ||||
| 
 | ||||
|                     fixed_lens.push(quote! { | ||||
|                         <#ty as ssz::Decodable>::ssz_fixed_len() | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
| @ -185,22 +183,40 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream { | ||||
| 
 | ||||
|     let output = quote! { | ||||
|         impl ssz::Decodable for #name { | ||||
|             fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), ssz::DecodeError> { | ||||
|             fn is_ssz_fixed_len() -> bool { | ||||
|                 #( | ||||
|                     #quotes | ||||
|                     #is_fixed_lens && | ||||
|                 )* | ||||
|                     true | ||||
|             } | ||||
| 
 | ||||
|             fn ssz_fixed_len() -> usize { | ||||
|                 if <Self as ssz::Decodable>::is_ssz_fixed_len() { | ||||
|                     #( | ||||
|                         #fixed_lens + | ||||
|                     )* | ||||
|                         0 | ||||
|                 } else { | ||||
|                     ssz::BYTES_PER_LENGTH_OFFSET | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> { | ||||
|                 let mut builder = ssz::SszDecoderBuilder::new(bytes); | ||||
| 
 | ||||
|                 #( | ||||
|                     #register_types | ||||
|                 )* | ||||
| 
 | ||||
|                 Ok(( | ||||
|                     Self { | ||||
|                         #( | ||||
|                             #all_idents, | ||||
|                         )* | ||||
|                     }, | ||||
|                     i | ||||
|                 )) | ||||
|                 let mut decoder = builder.build()?; | ||||
| 
 | ||||
|                 Ok(Self { | ||||
|                     #( | ||||
|                         #decodes, | ||||
|                     )* | ||||
|                 }) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|     output.into() | ||||
| } | ||||
| */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user