Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deku_derive fails when combined with cfg_attr #343

Open
NTmatter opened this issue Jun 7, 2023 · 0 comments
Open

deku_derive fails when combined with cfg_attr #343

NTmatter opened this issue Jun 7, 2023 · 0 comments
Labels
bug Something isn't working

Comments

@NTmatter
Copy link

NTmatter commented Jun 7, 2023

As background, I'm trying to use Deku as an optional dependency by leveraging #[cfg_attr(feature = "deku", derive(DekuRead))] to toggle Deku's functionality.

This leads to failures when trying to use deku_derive when temp fields are present, as in #[cfg_attr(feature = "deku", deku_derive(DekuRead))]

Using the snippets below, a cargo check (Deku disabled) will complete without issues.

Running cargo check --features deku will fail on Baz, stating cannot find attribute deku in scope and error[E0277]: the trait bound Vec: deku::DekuRead<'_, Endian> is not satisfied.

Cargo.toml - deku disabled by default:

[package]
name = "deku-conditional"
version = "0.1.0"
edition = "2021"

[dependencies]
deku = { version = "0.16.0", optional = true }

[features]
deku = ["dep:deku"]

src/main.rs - optional deku support:

#[cfg(feature = "deku")]
use deku::prelude::*;

// Using deku_derive with cfg_attr fails
#[cfg_attr(feature = "deku", deku_derive(DekuRead))]
#[cfg_attr(feature = "deku", deku(endian = "big"))]
struct Baz {
    #[cfg_attr(feature = "deku", deku(temp))]
    length: u16,
    #[cfg_attr(feature = "deku", deku(count = "length"))]
    payload: Vec<u16>
}

// Conditional compilation works with regular derive.
#[cfg_attr(feature = "deku", derive(DekuRead))]
#[cfg_attr(feature = "deku", deku(endian = "big"))]
struct Bar {
    length: u16,
    #[cfg_attr(feature = "deku", deku(count = "length"))]
    payload: Vec<u16>
}

// Using deku_derive without conditional compilation works as documented.
// #[deku_derive(DekuRead)]
// #[deku(endian = "big")]
// struct Foo {
//     #[deku(temp)]
//     length: u16,
//     #[deku(count = "length")]
//     payload: Vec<u16>
// }

fn main() { }

Workaround: Manually duplicate affected structs, strip Deku attributes, and conditionally compile with #[cfg(feature = "deku")] and #[cfg(not(feature = "deku"))].

#[cfg(feature = "deku")]
use deku::prelude::*;

// Using deku_derive to remove a temp field works as documented
#[cfg(feature = "deku")]
#[deku_derive(DekuRead)]
#[deku(endian = "big")]
struct Foo {
    #[deku(temp)]
    length: u16,
    #[deku(count = "length")]
    payload: Vec<u16>
}

#[cfg(not(feature = "deku"))]
struct Foo {
    length: u16,
    payload: Vec<u16>
}
@wcampbell0x2a wcampbell0x2a added the bug Something isn't working label Jun 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants