Skip to content

Commit

Permalink
Add bit_order attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a committed Aug 23, 2024
1 parent ccc76da commit 813a123
Show file tree
Hide file tree
Showing 14 changed files with 1,554 additions and 190 deletions.
21 changes: 19 additions & 2 deletions deku-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ struct DekuData {

/// enum only: byte size of the enum `id`
bytes: Option<Num>,

/// Bit Order for all fields
bit_order: Option<syn::LitStr>,
}

impl DekuData {
Expand Down Expand Up @@ -188,6 +191,7 @@ impl DekuData {
id_type: receiver.id_type?,
bits: receiver.bits,
bytes: receiver.bytes,
bit_order: receiver.bit_order,
};

DekuData::validate(&data)?;
Expand Down Expand Up @@ -322,6 +326,7 @@ impl<'a> TryFrom<&'a DekuData> for DekuDataEnum<'a> {
deku_data.endian.as_ref(),
deku_data.bits.as_ref(),
deku_data.bytes.as_ref(),
deku_data.bit_order.as_ref(),
)?;

Ok(Self {
Expand Down Expand Up @@ -439,11 +444,14 @@ struct FieldData {
/// condition to parse field
cond: Option<TokenStream>,

// assertion on field
/// assertion on field
assert: Option<TokenStream>,

// assert value of field
/// assert value of field
assert_eq: Option<TokenStream>,

/// Bit Order of field
bit_order: Option<syn::LitStr>,
}

impl FieldData {
Expand Down Expand Up @@ -481,6 +489,7 @@ impl FieldData {
cond: receiver.cond?,
assert: receiver.assert?,
assert_eq: receiver.assert_eq?,
bit_order: receiver.bit_order,
};

FieldData::validate(&data)?;
Expand Down Expand Up @@ -668,6 +677,10 @@ struct DekuReceiver {
/// enum only: byte size of the enum `id`
#[darling(default)]
bytes: Option<Num>,

/// Bit Order of field
#[darling(default)]
bit_order: Option<syn::LitStr>,
}

type ReplacementError = TokenStream;
Expand Down Expand Up @@ -848,6 +861,10 @@ struct DekuFieldReceiver {
// assert value of field
#[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
assert_eq: Result<Option<TokenStream>, ReplacementError>,

/// Bit Order of field
#[darling(default)]
bit_order: Option<syn::LitStr>,
}

/// Receiver for the variant-level attributes inside a enum
Expand Down
84 changes: 61 additions & 23 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use darling::ast::{Data, Fields};
use darling::ToTokens;
use proc_macro2::TokenStream;
use quote::quote;
use syn::LitStr;

use crate::macros::{
gen_ctx_types_and_arg, gen_field_args, gen_internal_field_ident, gen_internal_field_idents,
gen_type_from_ctx_id, pad_bits, token_contains_string, wrap_default_ctx,
gen_bit_order_from_str, gen_ctx_types_and_arg, gen_field_args, gen_internal_field_ident,
gen_internal_field_idents, gen_type_from_ctx_id, pad_bits, token_contains_string,
wrap_default_ctx,
};
use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id};

Expand Down Expand Up @@ -512,28 +514,60 @@ fn emit_bit_byte_offsets(
(bit_offset, byte_offset)
}

fn emit_padding(bit_size: &TokenStream) -> TokenStream {
fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStream {
let crate_ = super::get_crate_name();
quote! {
{
use core::convert::TryFrom;
// TODO: I hope this consts in most cases?
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;


if (__deku_pad % 8) == 0 {
let bytes_read = __deku_pad / 8;
let mut buf = vec![0; bytes_read];
let _ = __deku_reader.read_bytes(bytes_read, &mut buf)?;
} else {
let _ = __deku_reader.read_bits(__deku_pad)?;
if let Some(bit_order) = bit_order {
let order = gen_bit_order_from_str(bit_order).unwrap();
quote! {
{
println!("{:?}", #order);
use core::convert::TryFrom;
// TODO: I hope this consts in most cases?
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;


if (__deku_pad % 8) == 0 {
let bytes_read = __deku_pad / 8;
let mut buf = vec![0; bytes_read];
// TODO: use skip_bytes, or Seek in the future?
let _ = __deku_reader.read_bytes(bytes_read, &mut buf, #order)?;
} else {
// TODO: use skip_bits, or Seek in the future?
let _ = __deku_reader.read_bits(__deku_pad, #order)?;
}
}
}
} else {
quote! {
{
use core::convert::TryFrom;
// TODO: I hope this consts in most cases?
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;


if (__deku_pad % 8) == 0 {
let bytes_read = __deku_pad / 8;
let mut buf = vec![0; bytes_read];
// TODO: use skip_bytes, or Seek in the future?
let _ = __deku_reader.read_bytes(bytes_read, &mut buf, ::#crate_::ctx::Order::Msb0)?;
} else {
// TODO: use skip_bits, or Seek in the future?
let _ = __deku_reader.read_bits(__deku_pad, ::#crate_::ctx::Order::Msb0)?;
}
}
}
}
Expand All @@ -550,6 +584,7 @@ fn emit_field_read(
let field_type = &f.ty;

let field_endian = f.endian.as_ref().or(input.endian.as_ref());
let field_bit_order = f.bit_order.as_ref().or(input.bit_order.as_ref());

let field_reader = &f.reader;

Expand Down Expand Up @@ -619,6 +654,7 @@ fn emit_field_read(
f.bits.as_ref(),
f.bytes.as_ref(),
f.ctx.as_ref(),
field_bit_order,
)?;

// The __deku_reader limiting options are special, we need to generate `(limit, (other, ..))` for them.
Expand Down Expand Up @@ -710,11 +746,13 @@ fn emit_field_read(
let pad_bits_before = pad_bits(
f.pad_bits_before.as_ref(),
f.pad_bytes_before.as_ref(),
field_bit_order,
emit_padding,
);
let pad_bits_after = pad_bits(
f.pad_bits_after.as_ref(),
f.pad_bytes_after.as_ref(),
field_bit_order,
emit_padding,
);

Expand Down
53 changes: 38 additions & 15 deletions deku-derive/src/macros/deku_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::convert::TryFrom;
use darling::ast::{Data, Fields};
use proc_macro2::TokenStream;
use quote::quote;
use syn::LitStr;

use crate::macros::{
assertion_failed, gen_ctx_types_and_arg, gen_field_args, gen_struct_destruction, pad_bits,
token_contains_string, wrap_default_ctx,
assertion_failed, gen_bit_order_from_str, gen_ctx_types_and_arg, gen_field_args,
gen_struct_destruction, pad_bits, token_contains_string, wrap_default_ctx,
};
use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id};

Expand Down Expand Up @@ -410,20 +411,38 @@ fn emit_bit_byte_offsets(
(bit_offset, byte_offset)
}

fn emit_padding(bit_size: &TokenStream) -> TokenStream {
fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStream {
let crate_ = super::get_crate_name();
quote! {
{
use core::convert::TryFrom;
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;
__deku_writer.write_bits(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice())?;
if let Some(bit_order) = bit_order {
let order = gen_bit_order_from_str(bit_order).unwrap();
quote! {
{
use core::convert::TryFrom;
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;
__deku_writer.write_bits_order(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice(), #order)?;
}
}
} else {
quote! {
{
use core::convert::TryFrom;
extern crate alloc;
use alloc::borrow::Cow;
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(Cow::from(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
)))
)?;
__deku_writer.write_bits(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice())?;
}
}
}
}
Expand All @@ -437,6 +456,7 @@ fn emit_field_write(
) -> Result<TokenStream, syn::Error> {
let crate_ = super::get_crate_name();
let field_endian = f.endian.as_ref().or(input.endian.as_ref());
let field_bit_order = f.bit_order.as_ref().or(input.bit_order.as_ref());

// fields to check usage of bit/byte offset
let field_check_vars = [
Expand Down Expand Up @@ -492,6 +512,7 @@ fn emit_field_write(
f.bits.as_ref(),
f.bytes.as_ref(),
f.ctx.as_ref(),
field_bit_order,
)?;

if f.temp {
Expand All @@ -512,11 +533,13 @@ fn emit_field_write(
let pad_bits_before = pad_bits(
f.pad_bits_before.as_ref(),
f.pad_bytes_before.as_ref(),
field_bit_order,
emit_padding,
);
let pad_bits_after = pad_bits(
f.pad_bits_after.as_ref(),
f.pad_bytes_after.as_ref(),
field_bit_order,
emit_padding,
);

Expand Down
Loading

0 comments on commit 813a123

Please sign in to comment.