check size of items
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate proc_macro2;
|
||||
|
||||
use quote::{quote, format_ident};
|
||||
use proc_macro2::Span;
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{DeriveInput, Data::Enum, parse_macro_input};
|
||||
@@ -40,7 +35,7 @@ pub fn derive_parse_bin(input: TokenStream) -> TokenStream {
|
||||
syn::Data::Struct(struct_item) => {
|
||||
match struct_item.fields {
|
||||
syn::Fields::Named(fields_named) => {
|
||||
return derive_parse_bin_struct(&name, &fields_named.named);
|
||||
derive_parse_bin_struct(&name, &fields_named.named)
|
||||
},
|
||||
syn::Fields::Unnamed(fields_unnamed) => {
|
||||
if fields_unnamed.unnamed.len() != 1 {
|
||||
@@ -48,13 +43,13 @@ pub fn derive_parse_bin(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
let inner_type = fields_unnamed.unnamed.into_iter().next().unwrap().ty;
|
||||
return derive_parse_bin_alias(name, inner_type);
|
||||
derive_parse_bin_alias(name, inner_type)
|
||||
},
|
||||
_ => panic!("ParseBin on unit structs makes no sense!"),
|
||||
}
|
||||
},
|
||||
_ => panic!("ParseBin only works on structs so far!"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_parse_bin_alias(name: syn::Ident, ty: syn::Type) -> TokenStream {
|
||||
@@ -113,49 +108,48 @@ fn derive_parse_bin_struct<'a, T>(name: &syn::Ident, fields: T) -> TokenStream
|
||||
if let Some(varname) = veclen {
|
||||
let field_name_item = format_ident!("{}_item", field_name);
|
||||
|
||||
let field_type_item: &syn::Type = match &field_type {
|
||||
syn::Type::Path(tp) => {
|
||||
match tp.path.segments.iter().next() {
|
||||
Some(single) => {
|
||||
if &single.ident.to_string() == "Vec" {
|
||||
match &single.arguments {
|
||||
syn::PathArguments::AngleBracketed(args) => {
|
||||
match args.args.iter().next() {
|
||||
Some(firstarg) => {
|
||||
match firstarg {
|
||||
syn::GenericArgument::Type(ty) => {
|
||||
Some(ty)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}.expect("The len attribute is only allowed on type Vec<_>");
|
||||
enum FieldType<'a> {
|
||||
Vec(&'a syn::Type),
|
||||
CString,
|
||||
}
|
||||
|
||||
let syn::Type::Path(tp) = &field_type else { panic!() };
|
||||
let single = tp.path.segments.iter().next().unwrap();
|
||||
|
||||
let field_type = if &single.ident.to_string() == "Vec" {
|
||||
let syn::PathArguments::AngleBracketed(args) = &single.arguments else { panic!() };
|
||||
let firstarg = args.args.iter().next().unwrap();
|
||||
let syn::GenericArgument::Type(ty) = firstarg else { panic!() };
|
||||
FieldType::Vec(ty)
|
||||
} else if &single.ident.to_string() == "CString" {
|
||||
FieldType::CString
|
||||
} else {
|
||||
panic!("The len attribute is only allowed on Vec<_> or CString")
|
||||
};
|
||||
|
||||
let varname_ident = syn::Ident::new(&varname, Span::call_site());
|
||||
|
||||
parsing_statements.push(quote!{
|
||||
let mut #field_name = Vec::new();
|
||||
for i in 0 .. #varname_ident.0 as usize {
|
||||
let #field_name_item = <#field_type_item>::parse_len(&bytes[__parse_bin_derive_size..])?;
|
||||
__parse_bin_derive_size += #field_name_item.1;
|
||||
#field_name.push(#field_name_item.0);
|
||||
}
|
||||
});
|
||||
|
||||
combining_expressions.push(quote!(#field_name: #field_name));
|
||||
match field_type {
|
||||
FieldType::Vec(field_type_item) => {
|
||||
parsing_statements.push(quote!{
|
||||
let mut #field_name = Vec::new();
|
||||
for i in 0 .. #varname_ident.0 as usize {
|
||||
let #field_name_item = <#field_type_item>::parse_len(&bytes[__parse_bin_derive_size..])?;
|
||||
__parse_bin_derive_size += #field_name_item.1;
|
||||
#field_name.push(#field_name_item.0);
|
||||
}
|
||||
});
|
||||
combining_expressions.push(quote!(#field_name: #field_name));
|
||||
},
|
||||
FieldType::CString => {
|
||||
parsing_statements.push(quote!{
|
||||
let #field_name = CString::parse_len(&bytes[__parse_bin_derive_size .. __parse_bin_derive_size + #varname_ident.0 as usize])?;
|
||||
__parse_bin_derive_size += #varname_ident.0 as usize;
|
||||
});
|
||||
combining_expressions.push(quote!(#field_name: #field_name.0));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
parsing_statements.push(quote!{
|
||||
let #field_name = <#field_type>::parse_len(&bytes[__parse_bin_derive_size..])?;
|
||||
|
||||
Reference in New Issue
Block a user