1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +02:00

support reading unnamed structs

This commit is contained in:
Robin Appelman 2019-06-22 17:45:53 +02:00
commit e56f636905
2 changed files with 63 additions and 43 deletions

View file

@ -213,39 +213,44 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
let span = struct_name.span(); let span = struct_name.span();
match data { match data {
Data::Struct(DataStruct { Data::Struct(DataStruct { fields, .. }) => {
fields: Fields::Named(fields), let values = fields.iter().map(|f| {
..
}) => {
let definitions = fields.named.iter().map(|f| {
let name = &f.ident;
// Get attributes `#[..]` on each field // Get attributes `#[..]` on each field
let size = get_field_size(&f.attrs, f.span()); let size = get_field_size(&f.attrs, f.span());
let field_type = &f.ty; let field_type = &f.ty;
let span = f.span(); let span = f.span();
match size { match size {
Some(size) => { Some(size) => {
quote_spanned! {span=> quote_spanned! { span =>
let #name:#field_type = { {
let _size: usize = #size; let _size: usize = #size;
stream.read_sized(_size)? stream.read_sized::<#field_type>(_size)?
}; }
} }
} }
None => { None => {
quote_spanned! {span=> quote_spanned! { span =>
let #name:#field_type = stream.read()?; stream.read::<#field_type>()?
} }
} }
} }
}); });
match &fields {
Fields::Named(fields) => {
let definitions = fields.named.iter().zip(values).map(|(f, value)| {
let name = &f.ident;
quote_spanned! { f.span() =>
let #name = #value;
}
});
let struct_definition = fields.named.iter().map(|f| { let struct_definition = fields.named.iter().map(|f| {
let name = &f.ident; let name = &f.ident;
quote_spanned! {f.span()=> quote_spanned! { f.span() =>
#name, #name,
} }
}); });
quote_spanned! {span=> quote_spanned! { span =>
#(#definitions)* #(#definitions)*
Ok(#struct_name { Ok(#struct_name {
@ -253,12 +258,14 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
}) })
} }
} }
Data::Struct(DataStruct { Fields::Unnamed(_) => quote_spanned! { span =>
fields: Fields::Unit, Ok(#struct_name(
.. #(#values ,)*
}) => { ))
quote_spanned! {span=> },
Fields::Unit => quote_spanned! {span=>
Ok(#struct_name) Ok(#struct_name)
},
} }
} }
Data::Enum(data) => { Data::Enum(data) => {
@ -278,7 +285,7 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
let size = get_field_size(&variant.attrs, f.span()); let size = get_field_size(&variant.attrs, f.span());
match size { match size {
Some(size) => { Some(size) => {
quote_spanned! {span=> quote_spanned! { span =>
#struct_name::#variant_name({ #struct_name::#variant_name({
let _size:usize = #size; let _size:usize = #size;
stream.read_sized(_size)? stream.read_sized(_size)?
@ -286,7 +293,7 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
} }
} }
None => { None => {
quote_spanned! {span=> quote_spanned! { span =>
#struct_name::#variant_name(stream.read()?) #struct_name::#variant_name(stream.read()?)
} }
} }
@ -399,13 +406,10 @@ fn derive_bitsize_trait(
// Generate an expression to sum up the heap size of each field. // Generate an expression to sum up the heap size of each field.
fn bit_size_sum(data: Data) -> TokenStream { fn bit_size_sum(data: Data) -> TokenStream {
match data { match data {
Data::Struct(DataStruct { Data::Struct(DataStruct { fields, .. }) => {
fields: Fields::Named(fields), let recurse = fields.iter().map(|f| {
..
}) => {
let recurse = fields.named.into_iter().map(|f| {
let span = f.span(); let span = f.span();
let field_type = f.ty; let field_type = &f.ty;
match get_field_size(&f.attrs, span) { match get_field_size(&f.attrs, span) {
Some(size) => { Some(size) => {
quote_spanned! {span => quote_spanned! {span =>
@ -423,10 +427,6 @@ fn bit_size_sum(data: Data) -> TokenStream {
0 # ( + # recurse) * 0 # ( + # recurse) *
} }
} }
Data::Struct(DataStruct {
fields: Fields::Unit,
..
}) => quote!(0),
_ => unimplemented!(), _ => unimplemented!(),
} }
} }

View file

@ -265,6 +265,22 @@ fn test_read_rest_enum() {
assert_eq!(TestEnumRest::Asd, stream.read().unwrap()); assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
} }
#[derive(BitRead, PartialEq, Debug)]
struct UnnamedSize(u8, #[size = 5] String, bool);
fn test_unnamed_struct() {
let bytes = vec![
12, 'h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, 0, 0, 0, 0, 0, 0,
];
let buffer = BitBuffer::new(bytes, LittleEndian);
let mut stream = BitStream::from(buffer);
assert_eq!(
UnnamedSize(12, "hello".to_string(), false),
stream.read().unwrap()
);
}
#[derive(BitRead, BitSize, PartialEq, Debug)] #[derive(BitRead, BitSize, PartialEq, Debug)]
struct EmptyStruct; struct EmptyStruct;
@ -285,9 +301,13 @@ struct SizeStruct {
bar: bool, bar: bool,
} }
#[derive(BitSize)]
struct UnnamedSizeStruct(u8, #[size = 6] String, bool);
#[test] #[test]
fn test_bit_size() { fn test_bit_size() {
assert_eq!(bit_size_of::<SizeStruct>(), 8 + 8 * 6 + 1); assert_eq!(bit_size_of::<SizeStruct>(), 8 + 8 * 6 + 1);
assert_eq!(bit_size_of::<UnnamedSizeStruct>(), 8 + 8 * 6 + 1);
} }
#[derive(BitSizeSized)] #[derive(BitSizeSized)]