Robbepop / modular-bitfield

Macro to generate bitfields for structs that allow for modular use of enums.
Apache License 2.0
155 stars 40 forks source link

Add `bits = N` parameter to the #[bitfield] macro #41

Closed Robbepop closed 3 years ago

Robbepop commented 3 years ago

With the proposed bits = N parameter for the #[bitfield] macro it will be possible to control how many bits the bitfield is going to use. For filled = true this is simply ensuring that exactly the amount of bits in the struct is going to be in use which must be divisible by 8. For filled = false this is, similar to #[derive(BitfieldSpecifier)] an indicator to the macro of how many bits there should be. This can be stretched to any value. For example, your bitfield actually just requires 7 bits in total but you want it to spread to 32-bits? No problem! Using filled = false, bits = 32 does the job for you.

Robbepop commented 3 years ago

To simplify the overall design of this crate we should actually replace the current #[bitfield(filled: bool)] parameter with the proposed #[bitfield(bits = N)] parameter.

They way bits = N could replace filled: bool is wherever filled = false has to be used right now we would enforce usage of bits = N with N being the bits that the user wants the bitfield to have. With #[skip] __: BN users can easily define whole areas of a bitfield to leave as undefined which should be used instead of using filled = false and is more powerful than that.

This also unifies design of the #[derive(BitfieldSpecifier)] derive macro for enums.

Robbepop commented 3 years ago

I have made some more thoughts about this and came to the conclusion that with the introduction of a bits: int parameter we no longer really want or need the bytes: int parameter with which we (so far) controlled the amount of bytes that a bitfield is going to need. So introducing the bits: int should deprecate or remove the bytes: int parameter which makes the overall design a bit simpler because you no longer need to handle cases like bits = 32, bytes = 3 that are conflicting with each other.

What I wrote above about filled: bool parameter might not be true entirely. There are two stand points:

  1. Keeping filled: bool and allowing interactions using both configs.

    • bits = N, filled = true: The bitfield must not have undefined bits and must have a bit width of exactly N.
    • bits = N, filled = false: The bitfield may have undefined bits and defaults to bit width equal to N. It is asserted at compile time that the required bits do not exceed or equal N - aka it is asserted that there are undefined bits.
  2. Removing of the filled: bool parameter:

    • How exactly can be differentiate between the 2 above cases with filled = false and filled = true? Do we actually really need filled = false? We just introduced #[skip] __: BN for pretty much the same purpose. The only advantage of filled = false is that it is a tad less to write and does not require yet another "fill" field. This comes more in handy if the bitfield is generally very small, e.g. contains just 1 or 2 bit fields.