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

use the smallest possible size int for descriminant reading/writing

This commit is contained in:
Robin Appelman 2021-07-24 17:34:29 +02:00
commit eb4bafc310
4 changed files with 40 additions and 18 deletions

View file

@ -144,7 +144,7 @@ use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{
parse_macro_input, parse_quote, parse_str, Attribute, Data, DataStruct, DeriveInput, Expr,
Fields, GenericParam, Ident, Lit, LitStr, Path,
Fields, GenericParam, Ident, Lit, LitInt, LitStr, Path,
};
use syn_util::get_attribute_value;
@ -414,14 +414,16 @@ fn parse(data: Data, struct_name: &Ident, attrs: &[Attribute], unchecked: bool)
let discriminant_token: TokenStream = match Discriminant::from(variant) {
Discriminant::Int(discriminant) => {
let lit = LitInt::new(&format!("{}", discriminant), span);
last_discriminant = discriminant as isize;
quote_spanned! { span => #discriminant }
quote_spanned! { span => #lit }
}
Discriminant::Wildcard => quote_spanned! { span => _ },
Discriminant::Default => {
let new_discriminant = (last_discriminant + 1) as usize;
let lit = LitInt::new(&format!("{}", new_discriminant), span);
last_discriminant += 1;
quote_spanned! { span => #new_discriminant }
quote_spanned! { span => #lit }
}
};
quote_spanned! {span=>
@ -431,13 +433,15 @@ fn parse(data: Data, struct_name: &Ident, attrs: &[Attribute], unchecked: bool)
let span = data.enum_token.span();
let repr = repr_for_bits(discriminant_bits);
let enum_name = Lit::Str(LitStr::new(&struct_name.to_string(), struct_name.span()));
quote_spanned! {span=>
let discriminant:usize = stream.read_int(#discriminant_bits as usize)?;
let discriminant:#repr = stream.read_int(#discriminant_bits as usize)?;
Ok(match discriminant {
#(#match_arms)*
_ => {
return Err(::bitbuffer::BitError::UnmatchedDiscriminant{discriminant, enum_name: #enum_name.to_string()})
return Err(::bitbuffer::BitError::UnmatchedDiscriminant{discriminant: discriminant as usize, enum_name: #enum_name.to_string()})
}
})
}
@ -555,3 +559,15 @@ fn get_field_size(attrs: &[Attribute], span: Span) -> Option<TokenStream> {
})
})
}
fn repr_for_bits(discriminant_bits: u64) -> TokenStream {
if discriminant_bits <= 8 {
quote!(u8)
} else if discriminant_bits <= 16 {
quote!(u16)
} else if discriminant_bits <= 32 {
quote!(u32)
} else {
quote!(usize)
}
}

View file

@ -1,11 +1,11 @@
use crate::discriminant::Discriminant;
use crate::size;
use crate::{repr_for_bits, size};
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{
parse_macro_input, parse_quote, parse_str, Attribute, Data, DataStruct, DeriveInput, Expr,
Fields, GenericParam, Ident, Index, Lit, Member, Path, Type,
Fields, GenericParam, Ident, Index, Lit, LitInt, Member, Path, Type,
};
use syn_util::get_attribute_value;
@ -182,17 +182,20 @@ fn write(data: Data, struct_name: &Ident, attrs: &[Attribute]) -> TokenStream {
let discriminant_token: TokenStream = match Discriminant::from(variant) {
Discriminant::Int(discriminant) => {
let lit = LitInt::new(&format!("{}", discriminant), span);
last_discriminant = discriminant as isize;
quote_spanned! { span => #discriminant }
quote_spanned! { span => #lit }
}
Discriminant::Wildcard => {
let free_discriminant = max_discriminant + 1;
quote_spanned! { span => #free_discriminant }
let lit = LitInt::new(&format!("{}", free_discriminant), span);
quote_spanned! { span => #lit }
}
Discriminant::Default => {
let new_discriminant = (last_discriminant + 1) as usize;
let lit = LitInt::new(&format!("{}", new_discriminant), span);
last_discriminant += 1;
quote_spanned! { span => #new_discriminant }
quote_spanned! { span => #lit }
}
};
@ -240,12 +243,13 @@ fn write(data: Data, struct_name: &Ident, attrs: &[Attribute]) -> TokenStream {
});
let span = data.enum_token.span();
let repr = repr_for_bits(discriminant_bits);
quote_spanned! {span=>
let discriminant = match &self {
let discriminant:#repr = match &self {
#(#discriminant_value),*
};
__target__stream.write_int(discriminant as usize, #discriminant_bits as usize)?;
__target__stream.write_int(discriminant, #discriminant_bits as usize)?;
match &self {
#(#write_inner)*
}

View file

@ -3,11 +3,13 @@
#![allow(unused_imports)]
use bitbuffer::{BitReadStream, Endianness};
use bitbuffer_derive::{BitWrite, BitWriteSized};
use bitbuffer_derive::{BitRead, BitWrite, BitWriteSized};
#[derive(BitWrite)]
struct TestSizeExpression {
size: u8,
#[size = "size + 2"]
str: String,
#[discriminant_bits = 4]
enum TestEnumRest {
Foo,
Bar,
#[discriminant = "_"]
Asd,
}