Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a position_of! macro to reference earlier fields position #161

Open
MrNbaYoh opened this issue Sep 28, 2022 · 0 comments
Open

Add a position_of! macro to reference earlier fields position #161

MrNbaYoh opened this issue Sep 28, 2022 · 0 comments
Labels
enhancement New feature or request

Comments

@MrNbaYoh
Copy link
Contributor

This issue is a feature proposal for adding a position_of! macro in the generated code for reading/writing.

#[binrw]
struct Test {
 a: u32,
 b: u32,
 #[br(calc = position_of!(b) + 1000]
 c: u64,
}

Main features

  • it is defined in the BinRead::read/BinWrite::write function, so it is not visible from outside
  • position_of!(x) gives the stream position at which the field x has been read

Additional ideas

  • to make look less like it's popping out of nowhere, add a struct-level position_of attribute such as:
    • if it is absent, the macro is not added in the generated code
    • #[br(position_of)] means we add it with it's default name
    • #[br(position_of = my_name)] means we add it and name it my_name

Concerns

  • what to return when the field is not actually read/written:
    • when it's conditionally read/written (with and if attribute for example), should it be:
      • an Option<u64> which is None when the field is not read and Some when it is (preferred)
      • a regular u64 that gives the position of the stream where the field could've been read (introduce concerns with conditionally applied seek/align directives)
    • when it's calculated with calc, should it be:
      • not defined at all (preferred)
      • a regular u64 that gives the position of the stream at the time the field is calculated
  • any other edge case?

Implementation proposals

The main difficulty is that we need to define a macro that allows us to reference earlier fields only:

  • we can redefine the macro each time a new field position is known, so for the given example you'd have:
    macro_rules! position_of {
        (a) => {
             __binrw_generated_position_of_a
        };
    }
    once the position of a is known, and as soon as the position of b is known, redefine it this way:
    macro_rules! position_of {
        (a) => {
             __binrw_generated_position_of_a
        };
        (b) => {
             __binrw_generated_position_of_b
        };
    }
  • or we can define it once and make it craft new idents with something like paste
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants