Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a committed Aug 2, 2023
1 parent 0c40c1a commit f795279
Show file tree
Hide file tree
Showing 12 changed files with 332 additions and 132 deletions.
46 changes: 33 additions & 13 deletions benches/deku.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::io::Read;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use deku::container::Container;
use deku::prelude::*;

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
Expand All @@ -10,8 +13,13 @@ struct DekuBits {
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuByte {
data: u8,
struct DekuBytes {
// #[deku(bytes = "1")] <=== This should be emitted!
data_00: u8,
// #[deku(bytes = "2")] <=== This should be emitted!
data_01: u16,
// #[deku(bytes = "4")] <=== This should be emitted!
data_02: u32,
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
Expand All @@ -38,55 +46,67 @@ struct DekuVec {
data: Vec<u8>,
}

fn deku_read_bits(input: &[u8]) {
let (_rest, _v) = DekuBits::from_bytes((input, 0)).unwrap();
fn deku_read_bits(reader: impl Read) {
let mut container = Container::new(reader);
let _v = DekuBits::from_reader(&mut container, ()).unwrap();
}

fn deku_write_bits(input: &DekuBits) {
let _v = input.to_bytes().unwrap();
}

fn deku_read_byte(input: &[u8]) {
let (_rest, _v) = DekuByte::from_bytes((input, 0)).unwrap();
fn deku_read_byte(reader: impl Read) {
let mut container = Container::new(reader);
let _v = DekuBytes::from_reader(&mut container, ()).unwrap();
}

fn deku_write_byte(input: &DekuByte) {
fn deku_write_byte(input: &DekuBytes) {
let _v = input.to_bytes().unwrap();
}

fn deku_read_enum(input: &[u8]) {
let (_rest, _v) = DekuEnum::from_bytes((input, 0)).unwrap();
let mut container = Container::new(input);
let _v = DekuEnum::from_reader(&mut container, ()).unwrap();
}

fn deku_write_enum(input: &DekuEnum) {
let _v = input.to_bytes().unwrap();
}

fn deku_read_vec(input: &[u8]) {
let (_rest, _v) = DekuVec::from_bytes((input, 0)).unwrap();
let mut container = Container::new(input);
let _v = DekuVec::from_reader(&mut container, ()).unwrap();
}

fn deku_write_vec(input: &DekuVec) {
let _v = input.to_bytes().unwrap();
}

fn deku_read_vec_perf(input: &[u8]) {
let (_rest, _v) = DekuVecPerf::from_bytes((input, 0)).unwrap();
let mut container = Container::new(std::io::Cursor::new(input));
let _v = DekuVecPerf::from_reader(&mut container, ()).unwrap();
}

fn deku_write_vec_perf(input: &DekuVecPerf) {
let _v = input.to_bytes().unwrap();
}

fn criterion_benchmark(c: &mut Criterion) {
let mut reader = std::io::repeat(0b101);
c.bench_function("deku_read_byte", |b| {
b.iter(|| deku_read_byte(black_box([0x01].as_ref())))
b.iter(|| deku_read_byte(black_box(&mut reader)))
});
c.bench_function("deku_write_byte", |b| {
b.iter(|| deku_write_byte(black_box(&DekuByte { data: 0x01 })))
b.iter(|| {
deku_write_byte(black_box(&DekuBytes {
data_00: 0x00,
data_01: 0x02,
data_02: 0x03,
}))
})
});
c.bench_function("deku_read_bits", |b| {
b.iter(|| deku_read_bits(black_box([0xf1].as_ref())))
b.iter(|| deku_read_bits(black_box(&mut reader)))
});
c.bench_function("deku_write_bits", |b| {
b.iter(|| {
Expand Down
174 changes: 94 additions & 80 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,51 +57,51 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {

let initialize_struct = super::gen_struct_init(is_named_struct, internal_fields);

//// Implement `DekuContainerRead` for types that don't need a context
//if input.ctx.is_none() || (input.ctx.is_some() && input.ctx_default.is_some()) {
// let from_bytes_body = wrap_default_ctx(
// quote! {
// use core::convert::TryFrom;
// use ::#crate_::bitvec::BitView;
// let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>();
// let mut __deku_rest = &__deku_input_bits[__deku_input.1..];
// let mut __deku_total_read = 0;

// #magic_read

// #(#field_reads)*
// let __deku_value = #initialize_struct;

// Ok((__deku_total_read, __deku_value))
// },
// &input.ctx,
// &input.ctx_default,
// );

// tokens.extend(emit_try_from(&imp, &lifetime, &ident, wher));

// tokens.extend(emit_from_bytes(
// &imp,
// &lifetime,
// &ident,
// wher,
// from_bytes_body,
// ));
//}
// Implement `DekuContainerRead` for types that don't need a context
if input.ctx.is_none() || (input.ctx.is_some() && input.ctx_default.is_some()) {
// let from_bytes_body = wrap_default_ctx(
// quote! {
// use core::convert::TryFrom;
// use ::#crate_::bitvec::BitView;
// let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>();
// let mut __deku_rest = &__deku_input_bits[__deku_input.1..];
// let mut __deku_total_read = 0;

// #magic_read

// #(#field_reads)*
// let __deku_value = #initialize_struct;

// Ok((__deku_total_read, __deku_value))
// },
// &input.ctx,
// &input.ctx_default,
// );

//tokens.extend(emit_try_from(&imp, &lifetime, &ident, wher));

// tokens.extend(emit_from_bytes(
// &imp,
// &lifetime,
// &ident,
// wher,
// from_bytes_body,
// ));
}

let (ctx_types, ctx_arg) = gen_ctx_types_and_arg(input.ctx.as_ref())?;

let read_body = quote! {
use core::convert::TryFrom;
//let mut __deku_rest = __deku_input_bits;
let mut __deku_total_read = 0;
//let mut __deku_total_read = 0;

#magic_read

#(#field_reads)*
let __deku_value = #initialize_struct;

Ok((__deku_total_read, __deku_value))
Ok(__deku_value)
};

tokens.extend(quote! {
Expand Down Expand Up @@ -223,18 +223,8 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
deku_ids.push(deku_id);
}

// if we're consuming an id, set the rest to new_rest before reading the variant
let new_rest = if consume_id {
quote! {
//__deku_total_read += __deku_amt_read;
}
} else {
quote! {}
};

quote! {
{
#new_rest
#(#field_reads)*
Self :: #initialize_enum
}
Expand Down Expand Up @@ -290,7 +280,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
}
} else if id_type.is_some() {
quote! {
let (__deku_amt_read, __deku_variant_id) = <#id_type>::from_reader(container, (#id_args))?;
let __deku_variant_id = <#id_type>::from_reader(container, (#id_args))?;
}
} else {
// either `id` or `type` needs to be specified
Expand All @@ -309,46 +299,46 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {

// Implement `DekuContainerRead` for types that don't need a context
if input.ctx.is_none() || (input.ctx.is_some() && input.ctx_default.is_some()) {
let from_bytes_body = wrap_default_ctx(
quote! {
use core::convert::TryFrom;
use ::#crate_::bitvec::BitView;
let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>();
let mut __deku_rest = &__deku_input_bits[__deku_input.1..];
let mut __deku_total_read = 0;

#magic_read

#variant_read

Ok((__deku_total_read, __deku_value))
},
&input.ctx,
&input.ctx_default,
);

tokens.extend(emit_try_from(&imp, &lifetime, &ident, wher));

tokens.extend(emit_from_bytes(
&imp,
&lifetime,
&ident,
wher,
from_bytes_body,
));
//let from_bytes_body = wrap_default_ctx(
// quote! {
// use core::convert::TryFrom;
// use ::#crate_::bitvec::BitView;
// let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>();
// let mut __deku_rest = &__deku_input_bits[__deku_input.1..];
// let mut __deku_total_read = 0;

// #magic_read

// #variant_read

// Ok((__deku_total_read, __deku_value))
// },
// &input.ctx,
// &input.ctx_default,
//);

//tokens.extend(emit_try_from(&imp, &lifetime, &ident, wher));

//tokens.extend(emit_from_bytes(
// &imp,
// &lifetime,
// &ident,
// wher,
// from_bytes_body,
//));
}
let (ctx_types, ctx_arg) = gen_ctx_types_and_arg(input.ctx.as_ref())?;

let read_body = quote! {
use core::convert::TryFrom;
let mut __deku_rest = __deku_input_bits;
let mut __deku_total_read = 0;
//let mut __deku_rest = __deku_input_bits;
//let mut __deku_total_read = 0;

#magic_read

#variant_read

Ok((__deku_total_read, __deku_value))
Ok(__deku_value)
};

tokens.extend(quote! {
Expand Down Expand Up @@ -608,29 +598,53 @@ fn emit_field_read(
quote! {
{
use core::borrow::Borrow;
#type_as_deku_read::from_reader<R: std::io::Read>(&mut container, (::#crate_::ctx::Limit::new_count(usize::try_from(*((#field_count).borrow()))?), (#read_args)))
#type_as_deku_read::from_reader
(
container,
(::#crate_::ctx::Limit::new_count(usize::try_from(*((#field_count).borrow()))?), (#read_args))
)
}
}
} else if let Some(field_bits) = &f.bits_read {
quote! {
{
use core::borrow::Borrow;
#type_as_deku_read::from_reader<R: std::io::Read>(container, (::#crate_::ctx::Limit::new_bit_size(::#crate_::ctx::BitSize(usize::try_from(*((#field_bits).borrow()))?)), (#read_args)))
#type_as_deku_read::from_reader
(
container,
(::#crate_::ctx::Limit::new_bit_size(::#crate_::ctx::BitSize(usize::try_from(*((#field_bits).borrow()))?)), (#read_args))
)
}
}
} else if let Some(field_bytes) = &f.bytes_read {
quote! {
{
use core::borrow::Borrow;
#type_as_deku_read::from_reader<R: std::io::Read>(container, (::#crate_::ctx::Limit::new_byte_size(::#crate_::ctx::ByteSize(usize::try_from(*((#field_bytes).borrow()))?)), (#read_args)))
#type_as_deku_read::from_reader
(
container,
(::#crate_::ctx::Limit::new_byte_size(::#crate_::ctx::ByteSize(usize::try_from(*((#field_bytes).borrow()))?)), (#read_args))
)
}
}
} else if let Some(field_until) = &f.until {
// We wrap the input into another closure here to enforce that it is actually a callable
// Otherwise, an incorrectly passed-in integer could unexpectedly convert into a `Count` limit
quote! {#type_as_deku_read::from_reader<R: std::io::Read>(container, (::#crate_::ctx::Limit::new_until(#field_until), (#read_args)))}
quote! {
#type_as_deku_read::from_reader
(
container,
(::#crate_::ctx::Limit::new_until(#field_until), (#read_args))
)
}
} else {
quote! {#type_as_deku_read::from_reader<R: std::io::Read>(container, (#read_args))}
quote! {
#type_as_deku_read::from_reader
(
container,
(#read_args)
)
}
}
};

Expand All @@ -647,7 +661,7 @@ fn emit_field_read(

let field_read_normal = quote! {
let __deku_value = #field_read_func?;
let __deku_value: #field_type = #field_map(__deku_value)?;
//let __deku_value: #field_type = #field_map(__deku_value)?;
__deku_value
};

Expand Down
3 changes: 2 additions & 1 deletion examples/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum DekuTest {
fn main() {
let test_data = hex!("03020102").to_vec();

let deku_test = DekuTest::try_from(test_data.as_ref()).unwrap();
let mut container = deku::container::Container::new(std::io::Cursor::new(test_data.clone()));
let deku_test = DekuTest::from_reader(&mut container, ()).unwrap();

assert_eq!(
DekuTest::Var4 {
Expand Down
12 changes: 2 additions & 10 deletions examples/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,9 @@ fn main() {
]
.as_ref();

let mut container = Container::new(std::io::Cursor::new(test_data.clone()));
let a = u8::from_reader(&mut container, (Endian::Little, ByteSize(1)));
let b = u8::from_reader(&mut container, (Endian::Little, BitSize(7)));
let c = u8::from_reader(&mut container, (Endian::Little, BitSize(1)));
let d = u16::from_reader(&mut container, (Endian::Big, BitSize(16)));
println!("{a:02x?}");
println!("{b:02x?}");
println!("{c:02x?}");
println!("{d:02x?}");
let mut container = Container::new(std::io::Cursor::new(test_data));
let test_deku = DekuTest::from_reader(&mut container, ()).unwrap();

let test_deku = DekuTest::try_from(test_data).unwrap();
println!("{test_deku:02x?}");
assert_eq!(
DekuTest {
Expand Down
Loading

0 comments on commit f795279

Please sign in to comment.