Skip to content

Commit

Permalink
Merge 0138356 into e92700a
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a committed May 4, 2024
2 parents e92700a + 0138356 commit e6c5a67
Show file tree
Hide file tree
Showing 29 changed files with 258 additions and 148 deletions.
4 changes: 2 additions & 2 deletions benches/deku.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::io::{Cursor, Read};
use std::io::{Cursor, Read, Seek};

use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use deku::prelude::*;
Expand Down Expand Up @@ -38,7 +38,7 @@ fn deku_write<T: DekuContainerWrite>(input: &T) {
let _v = input.to_bytes().unwrap();
}

fn deku_read<T: for<'a> DekuContainerRead<'a>>(mut reader: impl Read) {
fn deku_read<T: for<'a> DekuContainerRead<'a>>(mut reader: impl Read + Seek) {
let mut reader = Reader::new(&mut reader);
let _v = T::from_reader_with_ctx(&mut reader, ()).unwrap();
}
Expand Down
28 changes: 26 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>,

/// struct only: seek from current position
seek_from_current: Option<Num>,
}

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

DekuData::validate(&data)?;
Expand Down Expand Up @@ -269,12 +273,14 @@ impl DekuData {

/// Emit a reader. On error, a compiler error is emitted
fn emit_reader(&self) -> TokenStream {
self.emit_reader_checked().unwrap_or_else(|e| e.to_compile_error())
self.emit_reader_checked()
.unwrap_or_else(|e| e.to_compile_error())
}

/// Emit a writer. On error, a compiler error is emitted
fn emit_writer(&self) -> TokenStream {
self.emit_writer_checked().unwrap_or_else(|e| e.to_compile_error())
self.emit_writer_checked()
.unwrap_or_else(|e| e.to_compile_error())
}

/// Same as `emit_reader`, but won't auto convert error to compile error
Expand Down Expand Up @@ -442,6 +448,12 @@ struct FieldData {

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

//seek_rewind: Option<Num>,
seek_from_current: Option<TokenStream>,
//seek_from_end: Option<Num>,
//seek_from_start: Option<Num>,
//seek_position: Option<Num>,
}

impl FieldData {
Expand Down Expand Up @@ -479,6 +491,11 @@ impl FieldData {
cond: receiver.cond?,
assert: receiver.assert?,
assert_eq: receiver.assert_eq?,
//seek_rewind: receiver.seek_rewind?,
seek_from_current: receiver.seek_from_current?,
//seek_from_end: receiver.seek_from_end?,
//seek_from_start: receiver.seek_from_start?,
//seek_position: receiver.seek_position?,
};

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

#[darling(default)]
seek_from_current: Option<Num>,
}

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

/// seek from current position
#[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
seek_from_current: Result<Option<TokenStream>, ReplacementError>,
}

/// Receiver for the variant-level attributes inside a enum
Expand Down
22 changes: 17 additions & 5 deletions deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
tokens.extend(quote! {
impl #imp ::#crate_::DekuReader<#lifetime, #ctx_types> for #ident #wher {
#[inline]
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand All @@ -130,7 +130,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
tokens.extend(quote! {
impl #imp ::#crate_::DekuReader<#lifetime> for #ident #wher {
#[inline]
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand Down Expand Up @@ -381,7 +381,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
#[allow(non_snake_case)]
impl #imp ::#crate_::DekuReader<#lifetime, #ctx_types> for #ident #wher {
#[inline]
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, #ctx_arg) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand All @@ -394,7 +394,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
#[allow(non_snake_case)]
impl #imp ::#crate_::DekuReader<#lifetime> for #ident #wher {
#[inline]
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
fn from_reader_with_ctx<R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_reader: &mut ::#crate_::reader::Reader<R>, _: ()) -> core::result::Result<Self, ::#crate_::DekuError> {
#read_body
}
}
Expand Down Expand Up @@ -568,6 +568,17 @@ fn emit_field_read(
&f.assert_eq,
];

let seek = if let Some(num) = &f.seek_from_current {
quote! {
use ::#crate_::no_std_io::Seek;
use ::#crate_::no_std_io::SeekFrom;
// TODO: use ?
__deku_reader.seek(SeekFrom::Current(i64::try_from(#num).unwrap())).unwrap();
}
} else {
quote! {}
};

let (bit_offset, byte_offset) = emit_bit_byte_offsets(&field_check_vars);

let field_map = f
Expand Down Expand Up @@ -761,6 +772,7 @@ fn emit_field_read(
};

let field_read = quote! {
#seek
#pad_bits_before

#bit_offset
Expand Down Expand Up @@ -795,7 +807,7 @@ pub fn emit_container_read(
impl #imp ::#crate_::DekuContainerRead<#lifetime> for #ident #wher {
#[allow(non_snake_case)]
#[inline]
fn from_reader<'a, R: ::#crate_::no_std_io::Read>(__deku_input: (&'a mut R, usize)) -> core::result::Result<(usize, Self), ::#crate_::DekuError> {
fn from_reader<'a, R: ::#crate_::no_std_io::Read + ::#crate_::no_std_io::Seek>(__deku_input: (&'a mut R, usize)) -> core::result::Result<(usize, Self), ::#crate_::DekuError> {
#from_reader_body
}

Expand Down
5 changes: 3 additions & 2 deletions examples/custom_reader_and_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use deku::writer::Writer;
use deku::{prelude::*, DekuWriter};
use no_std_io::io::Write;

fn bit_flipper_read<R: std::io::Read>(
fn bit_flipper_read<R: std::io::Read + std::io::Seek>(
field_a: u8,
reader: &mut Reader<R>,
bit_size: BitSize,
Expand Down Expand Up @@ -59,8 +59,9 @@ struct DekuTest {

fn main() {
let test_data = [0x01, 0b1001_0110];
let mut cursor = std::io::Cursor::new(test_data);

let (_read_amt, ret_read) = DekuTest::from_reader((&mut test_data.as_slice(), 0)).unwrap();
let (_read_amt, ret_read) = DekuTest::from_reader((&mut cursor, 0)).unwrap();

assert_eq!(
ret_read,
Expand Down
14 changes: 10 additions & 4 deletions examples/deku_input.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//! Example of a close replacement for deku::input
use deku::prelude::*;
use std::io::{self, Cursor, Read};
use std::io::{self, Cursor, Read, Seek, SeekFrom};

/// Every read to this struct will be saved into an internal cache. This is to keep the cache
/// around for the crc without reading from the buffer twice
struct ReaderCrc<R: Read> {
struct ReaderCrc<R: Read + Seek> {
reader: R,
pub cache: Vec<u8>,
}

impl<R: Read> ReaderCrc<R> {
impl<R: Read + Seek> ReaderCrc<R> {
pub fn new(reader: R) -> Self {
Self {
reader,
Expand All @@ -18,14 +18,20 @@ impl<R: Read> ReaderCrc<R> {
}
}

impl<R: Read> Read for ReaderCrc<R> {
impl<R: Read + Seek> Read for ReaderCrc<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = self.reader.read(buf);
self.cache.extend_from_slice(buf);
n
}
}

impl<R: Read + Seek> Seek for ReaderCrc<R> {
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
self.reader.seek(pos)
}
}

#[derive(Debug, DekuRead)]
pub struct DekuStruct {
pub a: u8,
Expand Down
2 changes: 1 addition & 1 deletion src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ struct DekuTest {
impl DekuTest {
/// Read and convert to String
fn read<R: std::io::Read>(
fn read<R: std::io::Read + std::io::Seek>(
reader: &mut deku::reader::Reader<R>,
) -> Result<String, DekuError> {
let value = u8::from_reader_with_ctx(reader, ())?;
Expand Down
9 changes: 5 additions & 4 deletions src/impls/bool.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use no_std_io::io::{Read, Write};
use no_std_io::io::{Read, Seek, Write};

#[cfg(feature = "alloc")]
use alloc::borrow::Cow;
Expand All @@ -14,7 +14,7 @@ where
Ctx: Copy,
u8: DekuReader<'a, Ctx>,
{
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
inner_ctx: Ctx,
) -> Result<bool, DekuError> {
Expand Down Expand Up @@ -62,8 +62,9 @@ mod tests {
#[should_panic(expected = "Parse(\"cannot parse bool value: 2\")")]
case(&hex!("02"), false),
)]
fn test_bool(mut input: &[u8], expected: bool) {
let mut reader = Reader::new(&mut input);
fn test_bool(input: &[u8], expected: bool) {
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let res_read = bool::from_reader_with_ctx(&mut reader, ()).unwrap();
assert_eq!(expected, res_read);
}
Expand Down
6 changes: 3 additions & 3 deletions src/impls/boxed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use no_std_io::io::{Read, Write};
use no_std_io::io::{Read, Seek, Write};

use alloc::boxed::Box;
use alloc::vec::Vec;
Expand All @@ -13,7 +13,7 @@ where
T: DekuReader<'a, Ctx>,
Ctx: Copy,
{
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
inner_ctx: Ctx,
) -> Result<Self, DekuError> {
Expand All @@ -28,7 +28,7 @@ where
Ctx: Copy,
Predicate: FnMut(&T) -> bool,
{
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
(limit, inner_ctx): (Limit<T, Predicate>, Ctx),
) -> Result<Self, DekuError> {
Expand Down
4 changes: 2 additions & 2 deletions src/impls/cow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::{Borrow, Cow};

use no_std_io::io::{Read, Write};
use no_std_io::io::{Read, Seek, Write};

use crate::reader::Reader;
use crate::writer::Writer;
Expand All @@ -11,7 +11,7 @@ where
T: DekuReader<'a, Ctx> + Clone,
Ctx: Copy,
{
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
inner_ctx: Ctx,
) -> Result<Self, DekuError> {
Expand Down
4 changes: 2 additions & 2 deletions src/impls/cstring.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use alloc::borrow::Cow;
use no_std_io::io::{Read, Write};
use no_std_io::io::{Read, Seek, Write};
use std::ffi::CString;

use crate::reader::Reader;
Expand All @@ -21,7 +21,7 @@ impl<'a, Ctx: Copy> DekuReader<'a, Ctx> for CString
where
u8: DekuReader<'a, Ctx>,
{
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
inner_ctx: Ctx,
) -> Result<Self, DekuError> {
Expand Down
10 changes: 5 additions & 5 deletions src/impls/hashmap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};

use no_std_io::io::{Read, Write};
use no_std_io::io::{Read, Seek, Write};

use crate::ctx::*;
use crate::writer::Writer;
Expand All @@ -15,7 +15,7 @@ use crate::{DekuError, DekuReader, DekuWriter};
/// and a borrow of the latest value to have been read. It should return `true` if reading
/// should now stop, and `false` otherwise
#[allow(clippy::type_complexity)]
fn from_reader_with_ctx_hashmap_with_predicate<'a, K, V, S, Ctx, Predicate, R: Read>(
fn from_reader_with_ctx_hashmap_with_predicate<'a, K, V, S, Ctx, Predicate, R: Read + Seek>(
reader: &mut crate::reader::Reader<R>,
capacity: Option<usize>,
ctx: Ctx,
Expand All @@ -42,7 +42,7 @@ where
Ok(res)
}

fn from_reader_with_ctx_hashmap_to_end<'a, K, V, S, Ctx, R: Read>(
fn from_reader_with_ctx_hashmap_to_end<'a, K, V, S, Ctx, R: Read + Seek>(
reader: &mut crate::reader::Reader<R>,
capacity: Option<usize>,
ctx: Ctx,
Expand Down Expand Up @@ -92,7 +92,7 @@ where
/// expected.insert(100, 0x04030201);
/// assert_eq!(expected, map)
/// ```
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut crate::reader::Reader<R>,
(limit, inner_ctx): (Limit<(K, V), Predicate>, Ctx),
) -> Result<Self, DekuError>
Expand Down Expand Up @@ -175,7 +175,7 @@ where
Predicate: FnMut(&(K, V)) -> bool,
{
/// Read `K, V`s until the given limit from input for types which don't require context.
fn from_reader_with_ctx<R: Read>(
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut crate::reader::Reader<R>,
limit: Limit<(K, V), Predicate>,
) -> Result<Self, DekuError>
Expand Down
Loading

0 comments on commit e6c5a67

Please sign in to comment.