sharksforarms / deku

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

Working with elements of Vec<StructUsingDeku> to get sum of their byte-sizes #413

Open sempervictus opened 5 months ago

sempervictus commented 5 months ago

When using complex structures such as:

pub(super) struct Message {
    pub(super) hdr: MsgHeader,
    #[deku(count = "hdr.service_count")]
    pub(super) svcs: Vec<Svc>,
}

getting update to work becomes non-trivial since there's no good way to count up the sizes of those Svc structs given that they are

pub(super) struct Svc {
    pub(super) hdr: SvcHeader,
    #[deku(ctx = "*hdr")]
    pub(super) svc: SvcBody,
}
pub enum AnoSvcBody {
    #[deku(id = "0x0001")]
    FIRST {
        version: UbString,
...

themselves nested structures including typed enums based on a value in the Svc hdr struct. Attempting to

    pub fn update(&mut self) -> Result<(), DekuError> {
        let v: Vec<Vec<u8>> = self.svcs.iter()
            .map(|s| s.try_into()?)
            .collect();
        self.hdr.length = v.iter().map(|s| s.len()).sum();
        Ok(())
    }

causes

the trait `From<&Svc>` is not implemented for `Vec<u8>`

as do attempts to deref() in the map. Similarly to_bytes() is not found on &Svc :facepalm:

Ideally references would accept trait methods the same way as the owned structs, otherwise are there any macros or other sugar available to access these deeply nested members and pull the byte-sizes for summation?

sempervictus commented 5 months ago

Come to think of it... deku::size_of(struct) would be nice for the nested complexity of enums structured this way.

wcampbell0x2a commented 5 months ago

to_bytes() is only generated by types not using ctx: https://docs.rs/deku/latest/deku/trait.DekuContainerRead.html

You could use https://docs.rs/deku/latest/deku/attributes/index.html#ctx_default, if the ctx wouldn't affect your .len.

Const size generation was also asked for here: #307

sempervictus commented 5 months ago

Thanks for the pointers. Unfortunately ctx is how the type is passed from headed to typed-enum-body, but I'll see if I can make the default one work. Happen to have any dirty tricks in your code bag to get sizes for those lower-level child structs/enums or getting them to marshal into bytes somehow? Try into should work but being behind a reference breaks that as well.

sharksforarms commented 2 months ago

@sempervictus I know it's been a while, but providing a full code example (even if it's failing) will make it easier for us to try and find a solution, it's hard/wasteful for us to make assumptions on your intention and binary format