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

borrow data

This commit is contained in:
Robin Appelman 2020-12-05 22:48:40 +01:00
commit 0c8d2ebe18
9 changed files with 195 additions and 167 deletions

View file

@ -112,10 +112,10 @@
//! #
//! #[derive(BitRead)]
//! #[endianness = "E"]
//! struct EndiannessStruct<E: Endianness> {
//! struct EndiannessStruct<'a, E: Endianness> {
//! size: u8,
//! #[size = "size"]
//! stream: BitReadStream<E>,
//! stream: BitReadStream<'a, E>,
//! }
//! ```
//!
@ -125,10 +125,10 @@
//! #
//! #[derive(BitRead)]
//! #[endianness = "BigEndian"]
//! struct EndiannessStruct {
//! struct EndiannessStruct<'a> {
//! size: u8,
//! #[size = "size"]
//! stream: BitReadStream<BigEndian>,
//! stream: BitReadStream<'a, BigEndian>,
//! }
//! ```
extern crate proc_macro;
@ -138,7 +138,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, Ident, Lit, LitStr, Path, Variant,
Fields, GenericParam, Ident, Lit, LitStr, Path, Variant,
};
use syn_util::get_attribute_value;
@ -175,6 +175,18 @@ fn derive_bitread_trait(
let mut trait_generics = input.generics.clone();
// we need these separate generics to only add out Endianness param to the 'impl'
let (_, ty_generics, where_clause) = input.generics.split_for_impl();
let lifetime: Option<&GenericParam> = trait_generics
.params
.iter()
.filter(|param| matches!(param, GenericParam::Lifetime(_)))
.next();
let lifetime = match lifetime {
Some(GenericParam::Lifetime(lifetime)) => lifetime.lifetime.clone(),
_ => {
trait_generics.params.push(parse_quote!('a));
parse_quote!('a)
}
};
if endianness.is_none() {
trait_generics
.params
@ -193,7 +205,10 @@ fn derive_bitread_trait(
let parsed_unchecked = parse(input.data.clone(), &name, &input.attrs, true);
let endianness_placeholder = endianness.unwrap_or_else(|| "_E".to_owned());
let trait_def_str = format!("::bitbuffer::{}<{}>", trait_name, &endianness_placeholder);
let trait_def_str = format!(
"::bitbuffer::{}<{}, {}>",
trait_name, lifetime, &endianness_placeholder
);
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
let endianness_ident = Ident::new(&endianness_placeholder, span);
@ -218,10 +233,10 @@ fn derive_bitread_trait(
},
Span::call_site(),
);
//
let expanded = quote! {
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
fn read(stream: &mut ::bitbuffer::BitReadStream<#endianness_ident>#extra_param) -> ::bitbuffer::Result<Self> {
fn read(stream: &mut ::bitbuffer::BitReadStream<#lifetime, #endianness_ident>#extra_param) -> ::bitbuffer::Result<Self> {
// if the read has a predicable size, we can do the bounds check in one go
match <Self as #trait_def>::#size_method_name(#extra_param_call) {
Some(size) => {
@ -236,7 +251,7 @@ fn derive_bitread_trait(
}
}
unsafe fn read_unchecked(stream: &mut ::bitbuffer::BitReadStream<#endianness_ident>#extra_param, end: bool) -> ::bitbuffer::Result<Self> {
unsafe fn read_unchecked(stream: &mut ::bitbuffer::BitReadStream<#lifetime, #endianness_ident>#extra_param, end: bool) -> ::bitbuffer::Result<Self> {
#parsed_unchecked
}
@ -410,12 +425,12 @@ fn size(data: Data, struct_name: &Ident, attrs: &[Attribute], has_input_size: bo
match size {
Some(size) => {
quote_spanned! { span =>
<#field_type as ::bitbuffer::BitReadSized<::bitbuffer::LittleEndian>>::bit_size_sized(#size)
<#field_type as ::bitbuffer::BitReadSized<'_, ::bitbuffer::LittleEndian>>::bit_size_sized(#size)
}
}
None => {
quote_spanned! { span =>
<#field_type as ::bitbuffer::BitRead<::bitbuffer::LittleEndian>>::bit_size()
<#field_type as ::bitbuffer::BitRead<'_, ::bitbuffer::LittleEndian>>::bit_size()
}
}
}

View file

@ -0,0 +1,10 @@
#![allow(dead_code)]
#![allow(unreachable_patterns)]
use bitbuffer_derive::BitRead;
#[derive(BitRead)]
struct TestStruct {
foo: u8,
str: String,
}

View file

@ -45,7 +45,7 @@ fn test_read_struct() {
0b0101_0101,
0b1010_1010,
];
let buffer = BitReadBuffer::new(bytes, LittleEndian);
let buffer = BitReadBuffer::new(&bytes, LittleEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
TestStruct {
@ -83,7 +83,7 @@ fn test_read_bare_enum() {
0b1000_0100,
0b1000_0100,
];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(TestBareEnum::Asd, stream.read().unwrap());
assert_eq!(TestBareEnum::Foo, stream.read().unwrap());
@ -114,7 +114,7 @@ fn test_read_unnamed_field_enum() {
0b1000_0100,
0b1000_0100,
];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
TestUnnamedFieldEnum::Asd(0b_00_0110_10),
@ -144,7 +144,7 @@ fn test_read_struct_sized() {
let bytes = vec![
12, 'h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, 0, 0, 0, 0, 0, 0,
];
let buffer = BitReadBuffer::new(bytes, LittleEndian);
let buffer = BitReadBuffer::new(&bytes, LittleEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
TestStructSized {
@ -180,7 +180,7 @@ fn test_read_unnamed_field_enum_sized() {
0b1000_0100,
0b1000_0100,
];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
TestUnnamedFieldEnumSized::Asd(0b_00_0110),
@ -213,7 +213,7 @@ fn test_read_struct2() {
'l' as u8,
'e' as u8,
];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
TestStruct2 {
@ -227,16 +227,16 @@ fn test_read_struct2() {
#[derive(BitRead)]
#[endianness = "E"]
struct TestStruct3<E: Endianness> {
struct TestStruct3<'a, E: Endianness> {
size: u8,
#[size = "size"]
stream: BitReadStream<E>,
stream: BitReadStream<'a, E>,
}
#[test]
fn test_read_struct3() {
let bytes = vec![0b0000_0101, 0, 0, 0, 0, 0, 0, 0];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
let result: TestStruct3<BigEndian> = stream.read().unwrap();
assert_eq!(5, result.size);
@ -265,7 +265,7 @@ fn test_read_rest_enum() {
0b1000_0100,
0b1000_0100,
];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
assert_eq!(TestEnumRest::Foo, stream.read().unwrap());
@ -281,7 +281,7 @@ fn test_unnamed_struct() {
let bytes = vec![
12, 'h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8, 0, 0, 0, 0, 0, 0,
];
let buffer = BitReadBuffer::new(bytes, LittleEndian);
let buffer = BitReadBuffer::new(&bytes, LittleEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(
@ -295,7 +295,7 @@ struct EmptyStruct;
fn test_empty_struct() {
let bytes = vec![0, 0, 0, 0];
let buffer = BitReadBuffer::new(bytes, BigEndian);
let buffer = BitReadBuffer::new(&bytes, BigEndian);
let mut stream = BitReadStream::from(buffer);
assert_eq!(EmptyStruct, stream.read().unwrap());
assert_eq!(0, stream.pos());