mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
allow wildcard in enum parsing
This commit is contained in:
parent
8c378089ca
commit
c571326ed7
3 changed files with 49 additions and 8 deletions
|
|
@ -12,7 +12,7 @@ name = "bitstream_reader_derive"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = "0.15"
|
syn = { version = "0.15", features = ["full"] }
|
||||||
quote = "0.6"
|
quote = "0.6"
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "0.4"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,10 @@ extern crate proc_macro;
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::token::Token;
|
||||||
use syn::{
|
use syn::{
|
||||||
parse_macro_input, parse_quote, parse_str, Attribute, Data, DeriveInput, Expr, Fields, Ident,
|
parse_macro_input, parse_quote, parse_str, Attribute, Data, DeriveInput, Expr, Fields, Ident,
|
||||||
Lit, LitStr, Meta, Path,
|
Lit, LitStr, Meta, Pat, Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
/// See the [crate documentation](index.html) for details
|
||||||
|
|
@ -273,7 +274,7 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
|
||||||
let mut last_discriminant = -1;
|
let mut last_discriminant = -1;
|
||||||
let mut discriminants = Vec::with_capacity(data.variants.len());
|
let mut discriminants = Vec::with_capacity(data.variants.len());
|
||||||
for variant in &data.variants {
|
for variant in &data.variants {
|
||||||
let discriminant = variant
|
let discriminant: Option<usize> = variant
|
||||||
.discriminant
|
.discriminant
|
||||||
.clone()
|
.clone()
|
||||||
.map(|(_, expr)| match expr {
|
.map(|(_, expr)| match expr {
|
||||||
|
|
@ -282,12 +283,19 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
|
||||||
})
|
})
|
||||||
.or_else(|| get_attr(&variant.attrs, "discriminant"))
|
.or_else(|| get_attr(&variant.attrs, "discriminant"))
|
||||||
.map(|lit| match lit {
|
.map(|lit| match lit {
|
||||||
Lit::Int(lit) => lit.value(),
|
Lit::Int(lit) => Some(lit.value() as usize),
|
||||||
_ => panic!("discriminant is required to be an integer literal"),
|
Lit::Str(lit) => match lit.value().as_str() {
|
||||||
|
"_" => None,
|
||||||
|
_ => {
|
||||||
|
panic!("discriminant is required to be an integer literal or \"_\"")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!("discriminant is required to be an integer literal or \"_\""),
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| (last_discriminant + 1) as u64)
|
.unwrap_or_else(|| Some((last_discriminant + 1) as usize));
|
||||||
as usize;
|
if let Some(disc) = discriminant {
|
||||||
last_discriminant = discriminant as isize;
|
last_discriminant = disc as isize;
|
||||||
|
}
|
||||||
discriminants.push(discriminant)
|
discriminants.push(discriminant)
|
||||||
}
|
}
|
||||||
let match_arms =
|
let match_arms =
|
||||||
|
|
@ -297,6 +305,10 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
|
||||||
.map(|(variant, discriminant)| {
|
.map(|(variant, discriminant)| {
|
||||||
let span = variant.span();
|
let span = variant.span();
|
||||||
let variant_name = &variant.ident;
|
let variant_name = &variant.ident;
|
||||||
|
let discriminant_string = discriminant
|
||||||
|
.map(|value| value.to_string())
|
||||||
|
.unwrap_or("_".to_string());
|
||||||
|
let discriminant = parse_str::<Pat>(discriminant_string.as_str()).unwrap();
|
||||||
let read_fields = match &variant.fields {
|
let read_fields = match &variant.fields {
|
||||||
Fields::Unit => quote_spanned! {span=>
|
Fields::Unit => quote_spanned! {span=>
|
||||||
#struct_name::#variant_name
|
#struct_name::#variant_name
|
||||||
|
|
|
||||||
|
|
@ -230,3 +230,32 @@ fn test_read_struct3() {
|
||||||
assert_eq!(5, result.size);
|
assert_eq!(5, result.size);
|
||||||
assert_eq!(5, result.stream.bit_len());
|
assert_eq!(5, result.stream.bit_len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
#[discriminant_bits = 2]
|
||||||
|
enum TestEnumRest {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
#[discriminant = "_"]
|
||||||
|
Asd,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_rest_enum() {
|
||||||
|
let bytes = vec![
|
||||||
|
0b1100_0110,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
0b1000_0100,
|
||||||
|
];
|
||||||
|
let buffer = BitBuffer::new(bytes, BigEndian);
|
||||||
|
let mut stream = BitStream::from(buffer);
|
||||||
|
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
||||||
|
assert_eq!(TestEnumRest::Foo, stream.read().unwrap());
|
||||||
|
assert_eq!(TestEnumRest::Bar, stream.read().unwrap());
|
||||||
|
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue