mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
support reading Unit structs
This commit is contained in:
parent
0898cb6b5d
commit
896dff8367
2 changed files with 78 additions and 58 deletions
|
|
@ -183,8 +183,9 @@ fn derive_bitread_trait(
|
||||||
.push(parse_quote!(_E: ::bitstream_reader::Endianness));
|
.push(parse_quote!(_E: ::bitstream_reader::Endianness));
|
||||||
}
|
}
|
||||||
let (impl_generics, _, _) = trait_generics.split_for_impl();
|
let (impl_generics, _, _) = trait_generics.split_for_impl();
|
||||||
|
let span = input.span();
|
||||||
|
|
||||||
let parse = parse(&input.data, &name, &input.attrs);
|
let parse = parse(input.data, &name, &input.attrs);
|
||||||
|
|
||||||
let endianness_placeholder = endianness.unwrap_or("_E".to_owned());
|
let endianness_placeholder = endianness.unwrap_or("_E".to_owned());
|
||||||
let trait_def_str = format!(
|
let trait_def_str = format!(
|
||||||
|
|
@ -193,7 +194,7 @@ fn derive_bitread_trait(
|
||||||
);
|
);
|
||||||
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
|
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
|
||||||
|
|
||||||
let endianness_ident = Ident::new(&endianness_placeholder, input.span());
|
let endianness_ident = Ident::new(&endianness_placeholder, span);
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
|
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
|
||||||
|
|
@ -208,11 +209,14 @@ fn derive_bitread_trait(
|
||||||
proc_macro::TokenStream::from(expanded)
|
proc_macro::TokenStream::from(expanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream {
|
fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream {
|
||||||
match *data {
|
let span = struct_name.span();
|
||||||
Data::Struct(ref data) => {
|
|
||||||
match data.fields {
|
match data {
|
||||||
Fields::Named(ref fields) => {
|
Data::Struct(DataStruct {
|
||||||
|
fields: Fields::Named(fields),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
let definitions = fields.named.iter().map(|f| {
|
let definitions = fields.named.iter().map(|f| {
|
||||||
let name = &f.ident;
|
let name = &f.ident;
|
||||||
// Get attributes `#[..]` on each field
|
// Get attributes `#[..]` on each field
|
||||||
|
|
@ -241,7 +245,6 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
|
||||||
#name,
|
#name,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let span = data.struct_token.span();
|
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#(#definitions)*
|
#(#definitions)*
|
||||||
|
|
||||||
|
|
@ -250,10 +253,15 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
Data::Struct(DataStruct {
|
||||||
|
fields: Fields::Unit,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
quote_spanned! {span=>
|
||||||
|
Ok(#struct_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::Enum(ref data) => {
|
Data::Enum(data) => {
|
||||||
let discriminant_bits: u64 = get_attribute_value(attrs, &["discriminant_bits"]).expect(
|
let discriminant_bits: u64 = get_attribute_value(attrs, &["discriminant_bits"]).expect(
|
||||||
"'discriminant_bits' attribute is required when deriving `BinRead` for enums",
|
"'discriminant_bits' attribute is required when deriving `BinRead` for enums",
|
||||||
);
|
);
|
||||||
|
|
@ -325,22 +333,22 @@ fn get_field_size(attrs: &[Attribute], span: Span) -> Option<TokenStream> {
|
||||||
get_attribute_value(attrs, &["size"])
|
get_attribute_value(attrs, &["size"])
|
||||||
.map(|size_lit| match size_lit {
|
.map(|size_lit| match size_lit {
|
||||||
Lit::Int(size) => {
|
Lit::Int(size) => {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span =>
|
||||||
#size
|
# size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Lit::Str(size_field) => {
|
Lit::Str(size_field) => {
|
||||||
let size = parse_str::<Expr>(&size_field.value()).unwrap();
|
let size = parse_str::<Expr>(&size_field.value()).unwrap();
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span =>
|
||||||
(#size) as usize
|
( # size) as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Unsupported value for size attribute"),
|
_ => panic!("Unsupported value for size attribute"),
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
get_attribute_value::<Lit>(attrs, &["size_bits"]).map(|size_bits_lit| {
|
get_attribute_value::<Lit>(attrs, &["size_bits"]).map(|size_bits_lit| {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span =>
|
||||||
stream.read_int::<usize>(#size_bits_lit)?
|
stream.read_int::< usize > (# size_bits_lit) ?
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -376,9 +384,9 @@ fn derive_bitsize_trait(
|
||||||
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
|
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
|
impl # impl_generics # trait_def for # name # ty_generics # where_clause {
|
||||||
fn bit_size(#extra_param) -> usize {
|
fn bit_size( # extra_param) -> usize {
|
||||||
#sum
|
# sum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -400,19 +408,19 @@ fn bit_size_sum(data: Data) -> TokenStream {
|
||||||
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 =>
|
||||||
::bitstream_reader::bit_size_of_sized::<#field_type>(#size)
|
::bitstream_reader::bit_size_of_sized::< # field_type> ( # size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span =>
|
||||||
::bitstream_reader::bit_size_of::<#field_type>()
|
::bitstream_reader::bit_size_of::< # field_type> ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
quote! {
|
quote! {
|
||||||
0 #(+ #recurse)*
|
0 # ( + # recurse) *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::Struct(DataStruct {
|
Data::Struct(DataStruct {
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,18 @@ fn test_read_rest_enum() {
|
||||||
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitSize, PartialEq, Debug)]
|
||||||
|
struct EmptyStruct;
|
||||||
|
|
||||||
|
fn test_empty_struct() {
|
||||||
|
let bytes = vec![0, 0, 0, 0];
|
||||||
|
let buffer = BitBuffer::new(bytes, BigEndian);
|
||||||
|
let mut stream = BitStream::from(buffer);
|
||||||
|
assert_eq!(EmptyStruct, stream.read().unwrap());
|
||||||
|
assert_eq!(0, stream.pos());
|
||||||
|
assert_eq!(0, bit_size_of::<EmptyStruct>());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BitSize)]
|
#[derive(BitSize)]
|
||||||
struct SizeStruct {
|
struct SizeStruct {
|
||||||
foo: u8,
|
foo: u8,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue