Setting the sequence of macro expansions

Is there a way to enforce the order of proc/attribute macro expansion?
I'm using 3 and them being out of sequence is making me sad... because otherwise they're amazing crates.

#[bitfield]
#[derive(Debug, BinRead, Serialize)]
#[br(map = Self::from_bytes)]
pub struct Flags {
    r1: B3,
    v1: B1,
    v2: B1,
    v3: B1,
    v4: B1,
    r2: B1,
}

#[derive(Debug, BinRead, Serialize)]
#[br(big)]
pub struct Outside {
    y0: u16,
    y1: u16,
    f1: Flags,
}

fn main() {

    let rec = vec![0x01, 0xB0, 0x00, 0x00, 0x1e];

    let value = Outside::read(&mut Cursor::new(rec)).unwrap();

    println!("\n{}", value.json_string().unwrap());
    // println!("\n{:?}", value);
}

json_string is from simd-json-derive and the rest are seen in the code.

println!("\n{:?}", value);

Outside { y0: 432, y1: 0, f1: Flags { r1: 6, v1: 1, v2: 1, v3: 0, v4: 0, r2: 0 } }

println!("\n{}", value.json_string().unwrap());

{"y0":432,"y1":0,"f1":{"bytes":[30]}}

When I ran this through cargo-expand, it shows the Impl for BinRead first, then simd-json-derive's Serialize, then creates bitfield's functions (bitfield provides a from_bytes function).
Then, fmt::Debug is Impl'd for this struct.

In case the order of this expansion matters (it looks like it does?), it explains why value prints ok in fmt::Debug, but doesn't allow Serialze to run after BinRead's derive and bitfield's function.
bytes that we see is supposed to be what the input into bitfield function is called.

Is there a way out of this at all, each of these crates are very dear to me at the moment... they solve a lot of problems nicely.

Attribute macros are applied "inside to outside" just like regular macros, and derive is like an attribute macro. So if you want some or all of the derives to be applied to the code that is produced by #[bitfield], put them before the macro. If I understand what you're asking for correctly:

#[derive(Serialize)]
#[bitfield]
#[derive(Debug, BinRead)]
#[br(map = Self::from_bytes)]

Thank you very much for responding quickly!

It doesn't work unfortunately :frowning: .
I remember seeing that #[bitfield] wanted to be at the top.

error[E0615]: attempted to take value of method `r1` on type `&Flags`
  --> src/main.rs:46:5
   |
46 |     r1: B3,
   |     ^^ method, not a field
   |
help: use parentheses to call the method
   |
40 | #[derive(Serialize())]
   |                   ++

First, bitfield should make sense of the B3, etc exotic types, and create its functions.
Then, BinRead should do its derive, using a function from the above in br(map).
Finally, simdjson-derive should Serialize.

Any further suggestions... ?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.