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::spanned::Spanned;
use syn::{ use syn::{
parse_macro_input, parse_quote, parse_str, Attribute, Data, DataStruct, DeriveInput, Expr, 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; 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) { let discriminant_token: TokenStream = match Discriminant::from(variant) {
Discriminant::Int(discriminant) => { Discriminant::Int(discriminant) => {
let lit = LitInt::new(&format!("{}", discriminant), span);
last_discriminant = discriminant as isize; last_discriminant = discriminant as isize;
quote_spanned! { span => #discriminant } quote_spanned! { span => #lit }
} }
Discriminant::Wildcard => quote_spanned! { span => _ }, Discriminant::Wildcard => quote_spanned! { span => _ },
Discriminant::Default => { Discriminant::Default => {
let new_discriminant = (last_discriminant + 1) as usize; let new_discriminant = (last_discriminant + 1) as usize;
let lit = LitInt::new(&format!("{}", new_discriminant), span);
last_discriminant += 1; last_discriminant += 1;
quote_spanned! { span => #new_discriminant } quote_spanned! { span => #lit }
} }
}; };
quote_spanned! {span=> 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 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())); let enum_name = Lit::Str(LitStr::new(&struct_name.to_string(), struct_name.span()));
quote_spanned! {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 { Ok(match discriminant {
#(#match_arms)* #(#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::discriminant::Discriminant;
use crate::size; use crate::{repr_for_bits, size};
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::{ use syn::{
parse_macro_input, parse_quote, parse_str, Attribute, Data, DataStruct, DeriveInput, Expr, 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; 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) { let discriminant_token: TokenStream = match Discriminant::from(variant) {
Discriminant::Int(discriminant) => { Discriminant::Int(discriminant) => {
let lit = LitInt::new(&format!("{}", discriminant), span);
last_discriminant = discriminant as isize; last_discriminant = discriminant as isize;
quote_spanned! { span => #discriminant } quote_spanned! { span => #lit }
} }
Discriminant::Wildcard => { Discriminant::Wildcard => {
let free_discriminant = max_discriminant + 1; 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 => { Discriminant::Default => {
let new_discriminant = (last_discriminant + 1) as usize; let new_discriminant = (last_discriminant + 1) as usize;
let lit = LitInt::new(&format!("{}", new_discriminant), span);
last_discriminant += 1; 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 span = data.enum_token.span();
let repr = repr_for_bits(discriminant_bits);
quote_spanned! {span=> quote_spanned! {span=>
let discriminant = match &self { let discriminant:#repr = match &self {
#(#discriminant_value),* #(#discriminant_value),*
}; };
__target__stream.write_int(discriminant as usize, #discriminant_bits as usize)?; __target__stream.write_int(discriminant, #discriminant_bits as usize)?;
match &self { match &self {
#(#write_inner)* #(#write_inner)*
} }

View file

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

View file

@ -142,7 +142,7 @@ where
}); });
} }
if type_bit_size < USIZE_BITS { if type_bit_size < USIZE_BITS || count < USIZE_BITS {
self.push_bits(value.into_usize_unchecked(), count); self.push_bits(value.into_usize_unchecked(), count);
} else { } else {
self.push_non_fit_bits(value.into_bytes(), count) self.push_non_fit_bits(value.into_bytes(), count)