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

Tagged Union/Associated Data in enum support #80

Open
stevefan1999-personal opened this issue Sep 15, 2023 · 3 comments
Open

Tagged Union/Associated Data in enum support #80

stevefan1999-personal opened this issue Sep 15, 2023 · 3 comments

Comments

@stevefan1999-personal
Copy link

stevefan1999-personal commented Sep 15, 2023

This is like a normal Rust enum except we have a known limited choice, and this means we have to add a discriminator field and the subsequent bits. This is very useful to represent bit fields inside a C union.

Final size of the enum is (discriminator bits + max(content of each enum)). Examples coming soon.

#[tagged(discriminator_bits = 2)]
enum Entity {
  Human { foo: u1 } = 0b00,
  Dog { foo: u2 } = 0b10,
  Cat { bar: u4 } = 0b01,
  Squirrel { foo_bar: u6 } = 0b11,
}

This means we have a u8 field because we have a u2 header/discriminator + max(all enum trailing content) = u6 so u8. This is indicated by the dominant size of Squirrel. All others will have their unused bits zero-extended.

@pickx
Copy link
Collaborator

pickx commented Sep 18, 2023

thanks for the proposal. let's clarify this a little.
I've summarized what I understand from your proposal (please feel free to correct me) and added additional questions in parenthesis.

  • the enum has only "named fields" variants (do you want to additionally support tuple variants?), but not unit variants
  • all of the variants' fields are arbitrary_ints (or would you like to support any Bitsized type?)
  • variants have only one field (or would you like to allow Hamster { foo: u1, bar: u4, baz: u1 }?)
  • the enum is not annotated with #[bitsize(n)]. instead it is annotated with #[tagged(discriminator_bits = n)]
  • the enum is filled (I assume fallback would not be allowed?)
  • the discriminator is the MSB of the bitfield (or is it in the LSB position?)
  • let k = n + max_bitsize_of_any_variant. the generated bitfield for a variant would be a concat of: the discriminator, the field(s) of the variant, then zero-padding to length k

@stevefan1999-personal
Copy link
Author

thanks for the proposal. let's clarify this a little. I've summarized what I understand from your proposal (please feel free to correct me) and added additional questions in parenthesis.

  • the enum has only "named fields" variants (do you want to additionally support tuple variants?), but not unit variants
  • all of the variants' fields are arbitrary_ints (or would you like to support any Bitsized type?)
  • variants have only one field (or would you like to allow Hamster { foo: u1, bar: u4, baz: u1 }?)
  • the enum is not annotated with #[bitsize(n)]. instead it is annotated with #[tagged(discriminator_bits = n)]
  • the enum is filled (I assume fallback would not be allowed?)
  • the discriminator is the MSB of the bitfield (or is it in the LSB position?)
  • let k = n + max_bitsize_of_any_variant. the generated bitfield for a variant would be a concat of: the discriminator, the field(s) of the variant, then zero-padding to length k

I just think of it like this:

| discriminator bits | largest variant bits |

So using the example above:

| 2 bits | largest variant = Squirrel = 6 bits |

This is nice because the current Rust enum implementation won't be able to optimize the discriminator size (it almost always takes one byte at the least), so we can pack the whole thing into one byte rather than having align_up(8 + 6) = 16 bits = 2 bytes. One byte savings could be significant!

@stevefan1999-personal
Copy link
Author

https://alic.dev/blog/dense-enums

Just saw this on HN today. Could be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants