sharksforarms / deku

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

How to use the size in an inner struct #368

Open yanshay opened 1 year ago

yanshay commented 1 year ago

In the following example, the buffer is of an unknown size and I want to get the inner_b to contain all bytes that are not included in fields prior and after it in the hierarchical structures.

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
struct Outer {
  outer_a: u8,
  outer_b: Inner,
  outer_c: u8
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(ctx = "size: u32")]
struct Inner {
   inner_a: u8,
  #[deku(count = "size as usize - deku::byte_offset - 2")]
   inner_b: Vec<u8>,
   inner_c: u8,
}

I get the following error:

    | #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
    |                            ^^^^^^^^
    |                            |
    |                            expected `u32`, found `()`
    |                            arguments to this function are incorrect

I assume that I need to somehow pass the size of the buffer from the outer struct to the inner context, but couldn't find how to do that. Is there a way? Or any other way to achieve what I'm trying to do?

yanshay commented 1 year ago

I found an alternative solution by using the deku::rest instead: #[deku(count = "deku::rest.len()/8-2")]

It would still be interesting to know how to use size.

wcampbell0x2a commented 1 year ago

Since you added ctx to the Inner, you need a way of adding that same context to the outer_b: Inner.

use deku::prelude::*;

#[derive(Debug, PartialEq, DekuRead)]
struct Outer {
    outer_a: u8,
    #[deku(ctx = "deku::rest.len()/8-2")]
    outer_b: Inner,
    outer_c: u8,
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(ctx = "size: usize")]
struct Inner {
    inner_a: u8,
    #[deku(count = "size - deku::byte_offset - 2")]
    inner_b: Vec<u8>,
    inner_c: u8,
}

Unfortunately, this variable deku::rest ctx is added to DekuWrite incorrectly (?), so you can't use that portion. Anyway, https://github.com/dtolnay/cargo-expand usually does a good job of showing you the codegen.

yanshay commented 1 year ago

Since you added ctx to the Inner, you need a way of adding that same context to the outer_b: Inner.

I don't understand how the code changes you suggested are related to what you wrote. You used different solutions I tried in Outer and Inner context, while you referred to 'same context' in your text?

Unfortunately, this variable deku::rest ctx is added to DekuWrite incorrectly (?), so you can't use that portion

I want to make sure I understand what you mean - I can't use deku:rest.len() in the writing? I don't see how it could work in writing as there isn't 'rest' when writing if I get it right. Or maybe I'm totally off? But same would go for size.