Skip to content

Commit

Permalink
Merge 157add8 into 91f03e1
Browse files Browse the repository at this point in the history
  • Loading branch information
wcampbell0x2a authored Dec 28, 2023
2 parents 91f03e1 + 157add8 commit 47f4940
Show file tree
Hide file tree
Showing 52 changed files with 1,062 additions and 653 deletions.
114 changes: 101 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@
## [Unreleased]

## Changes
[#390](https://github.com/sharksforarms/deku/pull/390) added MSRV for `1.67.1`.
[#389](https://github.com/sharksforarms/deku/pull/389) changed edition to 2021
[#352](https://github.com/sharksforarms/deku/pull/352) added a new function `from_reader` that uses `io::Read`.
`io::Read` is also now used internally, bringing massive performance and usability improvements.
- Added MSRV for `1.67.1` ([#390](https://github.com/sharksforarms/deku/pull/390))
- Changed edition to 2021 ([#389](https://github.com/sharksforarms/deku/pull/389))
- Refactored `logging` feature with massive usability increases ([#352](https://github.com/sharksforarms/deku/pull/352)), ([#355](https://github.com/sharksforarms/deku/pull/355))
- Bumped the `syn` library to 2.0, which required replacing `type` for Enums with `id_type` ([#386](https://github.com/sharksforarms/deku/pull/386))
```diff,rust
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
-#[deku(type = "u8")]
+#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC((u8, u8)),
}
```

### Updated Reader API
- Changed API of reading to use `io::Read`, bringing massive performance and usability improvements ([#352](https://github.com/sharksforarms/deku/pull/352))
- Changed the trait `DekuRead` to `DekuReader`

### New `from_reader`
For example:
```rust
use std::io::{Seek, SeekFrom, Read};
use std::fs::File;
Expand All @@ -31,7 +44,7 @@ With the switch to internal streaming, the variables `deku::input`, `deku::input
`deku::reader` is a replacement for some of the functionality.
See [examples/deku_input.rs](examples/deku_input.rs) for a new example of caching all reads.

old:
Old:
```rust
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
Expand All @@ -56,7 +69,7 @@ fn custom_read(
}
```

new:
New:
```rust
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
Expand All @@ -83,7 +96,7 @@ fn custom_read<R: std::io::Read>(

- With the addition of using `Read`, containing a byte slice with a reference is not supported:

old
Old
```rust
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
struct TestStruct<'a> {
Expand All @@ -94,7 +107,7 @@ struct TestStruct<'a> {
}
```

new
New
```rust
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
struct TestStruct {
Expand All @@ -108,20 +121,20 @@ struct TestStruct {
- `id_pat` is now required to be the same type as stored id.
This also disallows using tuples for storing the id:

old:
Old:
```rust
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
#[deku(type = "u8")]
#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC((u8, u8)),
}
```

new:
New:
```rust
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
#[deku(type = "u8")]
#[deku(id_type = "u8")]
enum DekuTest {
#[deku(id_pat = "_")]
VariantC {
Expand All @@ -133,6 +146,81 @@ enum DekuTest {

- The feature `const_generics` was removed and is enabled by default.

### Updated Writer API
- Changed API of writing to use `io::Write`, bringing massive performance and usability improvements ([#355](https://github.com/sharksforarms/deku/pull/355))
- Changed the trait `DekuWrite` to `DekuWriter`
- The more internal (with context) `write(..)` was replaced with `to_writer(..)`.
With the switch to internal streaming, the variables `deku::output` are now not possible and were removed. `deku::writer` is a replacement for some of the functionality.

Old:
```rust
fn bit_flipper_write(
field_a: u8,
field_b: u8,
output: &mut BitVec<u8, Msb0>,
bit_size: BitSize,
) -> Result<(), DekuError> {
// Access to previously written fields
println!("field_a = 0x{:X}", field_a);

// value of field_b
println!("field_b = 0x{:X}", field_b);

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

// flip the bits on value if field_a is 0x01
let value = if field_a == 0x01 { !field_b } else { field_b };

value.write(output, bit_size)
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,

#[deku(
writer = "bit_flipper_write(*field_a, *field_b, deku::output, BitSize(8))"
)]
field_b: u8,
}
````

New:
```rust
fn bit_flipper_write<W: Write>(
field_a: u8,
field_b: u8,
writer: &mut Writer<W>,
bit_size: BitSize,
) -> Result<(), DekuError> {
// Access to previously written fields
println!("field_a = 0x{:X}", field_a);

// value of field_b
println!("field_b = 0x{:X}", field_b);

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

// flip the bits on value if field_a is 0x01
let value = if field_a == 0x01 { !field_b } else { field_b };

value.to_writer(writer, bit_size)
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct DekuTest {
field_a: u8,

#[deku(
writer = "bit_flipper_write(*field_a, *field_b, deku::writer, BitSize(8))"
)]
field_b: u8,
}
```
- Added `DekuError::Write` to denote `io::Write` errors

## [0.16.0] - 2023-02-28

### Changes
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ log = { version = "0.4.17", optional = true }
no_std_io = { version = "0.5.0", default-features = false, features = ["alloc"] }

[dev-dependencies]
rstest = "0.16.0"
rstest = "0.18.0"
hexlit = "0.5.5"
criterion = "0.4.0"
alloc_counter = "0.0.4"
trybuild = "1.0.77"
rustc-hash = "1.1.0"
env_logger = "0.10.0"
assert_hex = "0.2.2"

[[bench]]
name = "deku"
Expand Down
2 changes: 1 addition & 1 deletion benches/deku.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct DekuBytes {
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(type = "u8")]
#[deku(id_type = "u8")]
enum DekuEnum {
#[deku(id = "0x01")]
VariantA(u8),
Expand Down
6 changes: 3 additions & 3 deletions deku-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ logging = []

[dependencies]
quote = "1.0"
syn = "1.0"
syn = "2.0"
# extra-traits gives us Debug
# syn = {version = "1.0", features = ["extra-traits"]}
proc-macro2 = "1.0"
darling = "0.14"
darling = "0.20"
proc-macro-crate = { version = "1.3.0", optional = true }

[dev-dependencies]
rstest = "0.16"
rstest = "0.18"
32 changes: 15 additions & 17 deletions deku-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use proc_macro2::TokenStream;
use quote::quote;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::AttributeArgs;

use crate::macros::deku_read::emit_deku_read;
use crate::macros::deku_write::emit_deku_write;
Expand Down Expand Up @@ -205,7 +204,10 @@ impl DekuData {
ast::Data::Struct(_) => {
// Validate id_* attributes are being used on an enum
if data.id_type.is_some() {
Err(cerror(data.id_type.span(), "`type` only supported on enum"))
Err(cerror(
data.id_type.span(),
"`id_type` only supported on enum",
))
} else if data.id.is_some() {
Err(cerror(data.id.span(), "`id` only supported on enum"))
} else if data.bytes.is_some() {
Expand All @@ -217,19 +219,19 @@ impl DekuData {
}
}
ast::Data::Enum(_) => {
// Validate `type` or `id` is specified
// Validate `id_type` or `id` is specified
if data.id_type.is_none() && data.id.is_none() {
return Err(cerror(
data.ident.span(),
"`type` or `id` must be specified on enum",
"`id_type` or `id` must be specified on enum",
));
}

// Validate either `type` or `id` is specified
// Validate either `id_type` or `id` is specified
if data.id_type.is_some() && data.id.is_some() {
return Err(cerror(
data.ident.span(),
"conflicting: both `type` and `id` specified on enum",
"conflicting: both `id_type` and `id` specified on enum",
));
}

Expand Down Expand Up @@ -635,11 +637,7 @@ struct DekuReceiver {
id: Option<Id>,

/// enum only: type of the enum `id`
#[darling(
rename = "type",
default = "default_res_opt",
map = "map_litstr_as_tokenstream"
)]
#[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")]
id_type: Result<Option<TokenStream>, ReplacementError>,

/// enum only: bit size of the enum `id`
Expand Down Expand Up @@ -668,7 +666,7 @@ fn apply_replacements(input: &syn::LitStr) -> Result<Cow<'_, syn::LitStr>, Repla

let input_str = input_value
.replace("deku::reader", "__deku_reader")
.replace("deku::output", "__deku_output") // part of the public API `write`
.replace("deku::writer", "__deku_writer")
.replace("deku::bit_offset", "__deku_bit_offset")
.replace("deku::byte_offset", "__deku_byte_offset");

Expand Down Expand Up @@ -875,7 +873,7 @@ pub fn proc_deku_write(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
}

fn is_not_deku(attr: &syn::Attribute) -> bool {
attr.path
attr.path()
.get_ident()
.map(|ident| ident != "deku" && ident != "deku_derive")
.unwrap_or(true)
Expand Down Expand Up @@ -939,8 +937,8 @@ pub fn deku_derive(
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse `deku_derive` attribute
let attr_args = syn::parse_macro_input!(attr as AttributeArgs);
let args = match DekuDerive::from_list(&attr_args) {
let nested_meta = darling::ast::NestedMeta::parse_meta_list(attr.into()).unwrap();
let args = match DekuDerive::from_list(&nested_meta) {
Ok(v) => v,
Err(e) => {
return proc_macro::TokenStream::from(e.write_errors());
Expand Down Expand Up @@ -1039,9 +1037,9 @@ mod tests {
}"#),
// Valid Enum
case::enum_empty(r#"#[deku(type = "u8")] enum Test {}"#),
case::enum_empty(r#"#[deku(id_type = "u8")] enum Test {}"#),
case::enum_all(r#"
#[deku(type = "u8")]
#[deku(id_type = "u8")]
enum Test {
#[deku(id = "1")]
A,
Expand Down
2 changes: 1 addition & 1 deletion deku-derive/src/macros/deku_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ fn emit_field_read(

let trace_field_log = if cfg!(feature = "logging") {
quote! {
log::trace!("Reading: {}::{}", #ident, #field_ident_str);
log::trace!("Reading: {}.{}", #ident, #field_ident_str);
}
} else {
quote! {}
Expand Down
Loading

0 comments on commit 47f4940

Please sign in to comment.