Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a committed Aug 3, 2023
1 parent a897076 commit ba06d8b
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 81 deletions.
7 changes: 4 additions & 3 deletions deku-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,10 +667,11 @@ fn apply_replacements(input: &syn::LitStr) -> Result<Cow<'_, syn::LitStr>, Repla
}

let input_str = input_value
.replace("deku::input", "__deku_input") // part of the public API `from_bytes`
.replace("deku::input_bits", "__deku_input_bits") // part of the public API `read`
// TODO: remove these?
//.replace("deku::input", "__deku_input") // part of the public API `from_bytes`
//.replace("deku::input_bits", "__deku_input_bits") // part of the public API `read`
.replace("deku::output", "__deku_output") // part of the public API `write`
.replace("deku::rest", "&__deku_rest[__deku_total_read..]")
.replace("deku::reader", "container")
.replace("deku::bit_offset", "__deku_bit_offset")
.replace("deku::byte_offset", "__deku_byte_offset");

Expand Down
29 changes: 14 additions & 15 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
quote! {
use core::convert::TryFrom;
let container = &mut deku::container::Container::new(__deku_input.0);
let _ = container.read_bits(__deku_input.1);
let _ = container.read_bits(__deku_input.1)?;

#magic_read

Expand Down Expand Up @@ -104,7 +104,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {

tokens.extend(quote! {
impl #imp ::#crate_::DekuRead<#lifetime, #ctx_types> for #ident #wher {
fn from_reader<R: std::io::Read>(container: &#lifetime mut ::#crate_::container::Container<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader<R: std::io::Read>(container: &mut ::#crate_::container::Container<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand All @@ -115,7 +115,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {

tokens.extend(quote! {
impl #imp ::#crate_::DekuRead<#lifetime> for #ident #wher {
fn from_reader<R: std::io::Read>(container: &#lifetime mut ::#crate_::container::Container<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader<R: std::io::Read>(container: &mut ::#crate_::container::Container<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand Down Expand Up @@ -274,7 +274,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {

let variant_id_read = if id.is_some() {
quote! {
let (__deku_amt_read, __deku_variant_id) = (0, (#id));
let __deku_variant_id = (#id);
}
} else if id_type.is_some() {
quote! {
Expand All @@ -301,7 +301,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
quote! {
use core::convert::TryFrom;
let container = &mut deku::container::Container::new(__deku_input.0);
let _ = container.read_bits(__deku_input.1);
let _ = container.read_bits(__deku_input.1)?;

#magic_read

Expand Down Expand Up @@ -340,7 +340,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
tokens.extend(quote! {
#[allow(non_snake_case)]
impl #imp ::#crate_::DekuRead<#lifetime, #ctx_types> for #ident #wher {
fn from_reader<R: std::io::Read>(container: &#lifetime mut ::#crate_::container::Container<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader<R: std::io::Read>(container: &mut ::#crate_::container::Container<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand All @@ -352,7 +352,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
tokens.extend(quote! {
#[allow(non_snake_case)]
impl #imp ::#crate_::DekuRead<#lifetime> for #ident #wher {
fn from_reader<R: std::io::Read>(container: &#lifetime mut ::#crate_::container::Container<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader<R: std::io::Read>(container: &mut ::#crate_::container::Container<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand Down Expand Up @@ -439,7 +439,7 @@ fn emit_bit_byte_offsets(
.any(|v| token_contains_string(v, "__deku_byte_offset"))
{
Some(quote! {
let __deku_byte_offset = __deku_bit_offset / 8;
let __deku_byte_offset = container.bits_read / 8;
})
} else {
None
Expand All @@ -451,7 +451,7 @@ fn emit_bit_byte_offsets(
|| byte_offset.is_some()
{
Some(quote! {
let __deku_bit_offset = usize::try_from(unsafe { __deku_rest.as_bitptr().offset_from(__deku_input_bits.as_bitptr()) } )?;
let __deku_bit_offset = container.bits_read;
})
} else {
None
Expand All @@ -465,18 +465,17 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream {
quote! {
{
use core::convert::TryFrom;
// TODO: I hope this consts in most cases?
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
::#crate_::DekuError::InvalidParam(format!(
"Invalid padding param \"({})\": cannot convert to usize",
stringify!(#bit_size)
))
)?;

if __deku_rest[__deku_total_read..].len() >= __deku_pad {
__deku_total_read += __deku_pad;
} else {
return Err(::#crate_::DekuError::Incomplete(::#crate_::error::NeedSize::new(__deku_pad)));
}

// TODO: This could be bytes
container.read_bits(__deku_pad)?;
}
}
}
Expand Down Expand Up @@ -657,7 +656,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
13 changes: 5 additions & 8 deletions examples/custom_reader_and_writer.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
use std::convert::TryInto;

use deku::bitvec::{BitSlice, BitVec, Msb0};
use deku::bitvec::{BitVec, Msb0};
use deku::ctx::BitSize;
use deku::prelude::*;

fn bit_flipper_read(
fn bit_flipper_read<R: std::io::Read>(
field_a: u8,
rest: &BitSlice<u8, Msb0>,
container: &mut Container<R>,
bit_size: BitSize,
) -> Result<u8, DekuError> {
// Access to previously read fields
println!("field_a = 0x{:X}", field_a);

// The current rest
println!("rest = {:?}", rest);

// Size of the current field
println!("bit_size: {:?}", bit_size);

// read field_b, calling original func
let (amt_read, value) = u8::read(rest, bit_size)?;
let value = u8::from_reader(container, bit_size)?;

// flip the bits on value if field_a is 0x01
let value = if field_a == 0x01 { !value } else { value };
Expand Down Expand Up @@ -53,7 +50,7 @@ struct DekuTest {
field_a: u8,

#[deku(
reader = "bit_flipper_read(*field_a, deku::rest, BitSize(8))",
reader = "bit_flipper_read(*field_a, deku::reader, BitSize(8))",
writer = "bit_flipper_write(*field_a, *field_b, deku::output, BitSize(8))"
)]
field_b: u8,
Expand Down
1 change: 1 addition & 0 deletions examples/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use deku::{
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct FieldF {
#[deku(bits = "6")]
#[deku(assert_eq = "6")]
data: u8,
}

Expand Down
51 changes: 25 additions & 26 deletions src/container.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use bitvec::prelude::*;
use std::io::Read;
use std::io::{self, Read};

use crate::{prelude::NeedSize, DekuError};

pub enum ContainerRet {

Check warning on line 6 in src/container.rs

View workflow job for this annotation

GitHub Actions / Build

missing documentation for an enum

Check warning on line 6 in src/container.rs

View workflow job for this annotation

GitHub Actions / Test Suite

missing documentation for an enum

Check warning on line 6 in src/container.rs

View workflow job for this annotation

GitHub Actions / Build

missing documentation for an enum

Check warning on line 6 in src/container.rs

View workflow job for this annotation

GitHub Actions / Test Suite

missing documentation for an enum
Bytes,
Expand All @@ -23,7 +25,11 @@ impl<R: Read> Container<R> {
}
}

pub fn read_bits(&mut self, amt: usize) -> std::io::Result<BitVec<u8, Msb0>> {
#[inline]
pub fn read_bits(&mut self, amt: usize) -> Result<BitVec<u8, Msb0>, DekuError> {
if amt == 0 {
return Ok(BitVec::new());
}
let mut ret = BitVec::with_capacity(amt);

if amt < self.leftover.len() {
Expand All @@ -34,12 +40,16 @@ impl<R: Read> Container<R> {
ret.extend(self.leftover.clone());

let bits_left = amt - self.leftover.len();
let mut bytes_len = (bits_left / 8);
let mut bytes_len = bits_left / 8;
if (bits_left % 8) != 0 {
bytes_len += 1;
}
let mut buf = vec![0; bytes_len];
self.inner.read_exact(&mut buf);
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == io::ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(amt)));
}
}

let mut rest: BitVec<u8, Msb0> = BitVec::try_from_slice(&buf).unwrap();
let add = rest.split_off(bits_left);
Expand All @@ -56,30 +66,19 @@ impl<R: Read> Container<R> {
//
// 1. We must have no leftover bits, so that we are "aligned"
#[inline]
pub fn read_bytes(&mut self, amt: usize, buf: &mut [u8]) -> ContainerRet {
pub fn read_bytes(&mut self, amt: usize, buf: &mut [u8]) -> Result<ContainerRet, DekuError> {
if self.leftover.is_empty() {
self.inner.read_exact(buf);
ContainerRet::Bytes
if let Err(e) = self.inner.read_exact(&mut buf[..amt]) {
if e.kind() == io::ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(amt * 8)));
}

// TODO: other errors?
}
self.bits_read += amt * 8;
Ok(ContainerRet::Bytes)
} else {
ContainerRet::Bits(self.read_bits(amt * 8).unwrap())
Ok(ContainerRet::Bits(self.read_bits(amt * 8)?))
}
}
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_container() {
use std::io::Cursor;
let buf = [0x12, 0x34];
let buf = std::io::Cursor::new(buf);

let mut container = Container::new(buf);

let bits = container.read_bits(4).unwrap();
let bits = container.read_bits(4).unwrap();
let bits = container.read_bits(4).unwrap();
let bits = container.read_bits(4).unwrap();
}
}
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use alloc::format;
use alloc::string::String;

/// Number of bits needed to retry parsing
///
/// TODO: add bytes
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NeedSize {
bits: usize,
Expand Down
20 changes: 12 additions & 8 deletions src/impls/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ impl DekuRead<'_, (Endian, ByteSize)> for u8 {
(endian, size): (Endian, ByteSize),
) -> Result<u8, DekuError> {
let mut buf = [0; core::mem::size_of::<u8>()];
let ret = container.read_bytes(size.0, &mut buf);
let ret = container.read_bytes(size.0, &mut buf)?;
let a = match ret {
ContainerRet::Bits(mut bits) => {
ContainerRet::Bits(bits) => {
let a = <u8>::read(&bits, (endian, size))?;
a.1
}
Expand Down Expand Up @@ -139,7 +139,7 @@ macro_rules! ImplDekuReadBits {
container: &mut crate::container::Container<R>,
(endian, size): (Endian, BitSize),
) -> Result<$typ, DekuError> {
let mut bits = container.read_bits(size.0).unwrap();
let bits = container.read_bits(size.0)?;
let a = <$typ>::read(&bits, (endian, size))?;
Ok(a.1)
}
Expand Down Expand Up @@ -222,14 +222,18 @@ macro_rules! ImplDekuReadBytes {
(endian, size): (Endian, ByteSize),
) -> Result<$typ, DekuError> {
let mut buf = [0; core::mem::size_of::<$typ>()];
let ret = container.read_bytes(size.0, &mut buf);
let ret = container.read_bytes(size.0, &mut buf)?;
let a = match ret {
ContainerRet::Bits(mut bits) => {
ContainerRet::Bits(bits) => {
let a = <$typ>::read(&bits, (endian, size))?;
a.1
}
ContainerRet::Bytes => {
<$typ>::from_be_bytes(buf.try_into().unwrap())
if endian.is_le() {
<$typ>::from_le_bytes(buf.try_into().unwrap())
} else {
<$typ>::from_be_bytes(buf.try_into().unwrap())
}
}
};
Ok(a)
Expand Down Expand Up @@ -262,7 +266,7 @@ macro_rules! ImplDekuReadSignExtend {
(endian, size): (Endian, ByteSize),
) -> Result<$typ, DekuError> {
// TODO: specialize for reading byte aligned
let mut bits = container.read_bits(size.0 * 8).unwrap();
let bits = container.read_bits(size.0 * 8)?;
let a = <$typ>::read(&bits, (endian, size))?;
Ok(a.1)
}
Expand All @@ -289,7 +293,7 @@ macro_rules! ImplDekuReadSignExtend {
container: &mut crate::container::Container<R>,
(endian, size): (Endian, BitSize),
) -> Result<$typ, DekuError> {
let mut bits = container.read_bits(size.0 * 8).unwrap();
let bits = container.read_bits(size.0 * 8)?;
let a = <$typ>::read(&bits, (endian, size))?;
Ok(a.1)
}
Expand Down
2 changes: 1 addition & 1 deletion src/impls/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ where
{
let mut res = capacity.map_or_else(Vec::new, Vec::with_capacity);

let mut start_read = container.bits_read;
let start_read = container.bits_read;

loop {
let val = <T>::from_reader(container, ctx)?;
Expand Down
4 changes: 2 additions & 2 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/
pub use crate::error::{DekuError, NeedSize};
pub use crate::{
deku_derive, DekuContainerRead, DekuContainerWrite, DekuEnumExt, DekuRead, DekuUpdate,
DekuWrite,
container::Container, deku_derive, DekuContainerRead, DekuContainerWrite, DekuEnumExt,
DekuRead, DekuUpdate, DekuWrite,
};
Loading

0 comments on commit ba06d8b

Please sign in to comment.