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:
parent
2a1718b5f6
commit
eb4bafc310
4 changed files with 40 additions and 18 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)*
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
} else {
|
||||
self.push_non_fit_bits(value.into_bytes(), count)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue