1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-04 00:54:07 +02:00

derive unchecked methods for traits

This commit is contained in:
Robin Appelman 2020-01-07 22:36:37 +01:00
commit a6e9b59ece
2 changed files with 39 additions and 13 deletions

View file

@ -191,7 +191,8 @@ fn derive_bitread_trait(
&input.attrs, &input.attrs,
extra_param.is_some(), extra_param.is_some(),
); );
let parse = parse(input.data, &name, &input.attrs); let parsed = parse(input.data.clone(), &name, &input.attrs, false);
let parsed_unchecked = parse(input.data.clone(), &name, &input.attrs, true);
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!(
@ -216,11 +217,15 @@ fn derive_bitread_trait(
}, },
Span::call_site(), Span::call_site(),
); );
//
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 read(stream: &mut ::bitstream_reader::BitStream<#endianness_ident>#extra_param) -> ::bitstream_reader::Result<Self> { fn read(stream: &mut ::bitstream_reader::BitStream<#endianness_ident>#extra_param) -> ::bitstream_reader::Result<Self> {
#parse #parsed
}
unsafe fn read_unchecked(stream: &mut ::bitstream_reader::BitStream<#endianness_ident>#extra_param) -> ::bitstream_reader::Result<Self> {
#parsed_unchecked
} }
fn #size_method_name(#size_extra_param) -> Option<usize> { fn #size_method_name(#size_extra_param) -> Option<usize> {
@ -234,7 +239,7 @@ 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>, unchecked: bool) -> TokenStream {
let span = struct_name.span(); let span = struct_name.span();
match data { match data {
@ -244,18 +249,36 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
let size = get_field_size(&f.attrs, f.span()); let size = get_field_size(&f.attrs, f.span());
let field_type = &f.ty; let field_type = &f.ty;
let span = f.span(); let span = f.span();
match size { if unchecked {
Some(size) => { match size {
quote_spanned! { span => Some(size) => {
{ quote_spanned! { span =>
let _size: usize = #size; {
stream.read_sized::<#field_type>(_size)? let _size: usize = #size;
stream.read_sized_unchecked::<#field_type>(_size)?
}
}
}
None => {
quote_spanned! { span =>
stream.read_unchecked::<#field_type>()?
} }
} }
} }
None => { } else {
quote_spanned! { span => match size {
stream.read::<#field_type>()? Some(size) => {
quote_spanned! { span =>
{
let _size: usize = #size;
stream.read_sized::<#field_type>(_size)?
}
}
}
None => {
quote_spanned! { span =>
stream.read::<#field_type>()?
}
} }
} }
} }

View file

@ -92,6 +92,9 @@ pub trait BitRead<E: Endianness>: Sized {
/// Read the type from stream /// Read the type from stream
fn read(stream: &mut BitStream<E>) -> Result<Self>; fn read(stream: &mut BitStream<E>) -> Result<Self>;
/// Note: only the bounds are unchecked
///
/// any other validations (e.g. checking for valid utf8) still needs to be done
#[doc(hidden)] #[doc(hidden)]
unsafe fn read_unchecked(stream: &mut BitStream<E>) -> Result<Self> { unsafe fn read_unchecked(stream: &mut BitStream<E>) -> Result<Self> {
Self::read(stream) Self::read(stream)