deku
deku copied to clipboard
deku_derive fails when combined with cfg_attr
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 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>
}