sharksforarms / deku

Declarative binary reading and writing: bit-level, symmetric, serialization/deserialization
Apache License 2.0
1.05k stars 54 forks source link

Cant "count" from Some(field) directly - need as_ref().unwrap() #407

Open sempervictus opened 5 months ago

sempervictus commented 5 months ago

When writing

...
    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_dsc: Option<SvcDesc>,
    #[deku(count = "svc_dsc.length")]
    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_name: Vec<u8>,
...

the compiler can't figure out how to reference the length struct member from svc_dsc because it's wrapped in an Option.

error[E0609]: no field `length` on type `&Option<SvcDesc>`
   --> src/ano.rs:106:20
    |
106 |     #[deku(count = "svc_dsc.length")]
    |                    ^^^^^^^^^^^^^^^^

Since the macro notation doesn't allow use of

    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_dsc: Option<SvcDesc>,
    #[deku(count = "Some(svc_dsc).length")]
    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_name: Vec<u8>,

either due to

error[E0609]: no field `length` on type `Option<&Option<SvcDesc>>`
   --> src/ano.rs:106:20
    |
106 |     #[deku(count = "Some(svc_dsc).length")]
    |                    ^^^^^^^^^^^^^^^^^^^^^^

It doesn't like getting dereferenced or unwrapped due to the borrow checker either :smile:.

I finally did figure out that you can unwrap the reference to the Option by writing this as

    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_dsc: Option<SvcDesc>,
    #[deku(count = "svc_dsc.as_ref().unwrap().length")]
    #[deku(skip, cond = "*status != vec![0xFA,0xFF] || hdr.sub_packets < 3")]
    svc_name: Vec<u8>,

but it was somewhat confounding there for a bit. Think it's worth looking at some sugar to handle options directly or at least documenting the access pattern for newcomers.

wcampbell0x2a commented 2 months ago

Oh interesting, if this isn't in a deku derive macro you get a better error:

error[E0609]: no field `len` on type `Option<Len>`
  --> examples/example.rs:16:7
   |
16 |     a.len;
   |       ^^^ unknown field
   |
help: one of the expressions' fields has a field of the same name
   |
16 |     a.unwrap().len;
   |       +++++++++