1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +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,6 +249,23 @@ 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();
if unchecked {
match size {
Some(size) => {
quote_spanned! { span =>
{
let _size: usize = #size;
stream.read_sized_unchecked::<#field_type>(_size)?
}
}
}
None => {
quote_spanned! { span =>
stream.read_unchecked::<#field_type>()?
}
}
}
} else {
match size { match size {
Some(size) => { Some(size) => {
quote_spanned! { span => quote_spanned! { span =>
@ -259,6 +281,7 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
} }
} }
} }
}
}); });
match &fields { match &fields {

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)