-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Proposal for bit data #205
Conversation
It has been suggested to implement this a syntax extension. This will not | ||
work, because | ||
|
||
* We need significant error-checking, including bit-size calulations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you expand on why you don't think that a procedural macro would be able to provide this error checking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the language had support for bitdata signed and unsigned values (like e.g. u4
and i12
), I believe it would be possible to support it through procedural macros. Having said that, I'm not an expert on procedural macros, and honestly - if anyone can write it using this feature - I would love to see it.
We were discussing this for Zinc. I ended up suggesting a way to do it with a Rust plugin, but we ended up going a custom DSL for ease of use. hackndev/zinc#129 (comment) |
A few points,
|
Sightly different to strict 'endianness' is the bit numbering. Whether 0 is But this is doable in a syntax extension, albeit as a struct with functions |
Thanks all for some very useful comments. I will address it in an upcoming diff. As @bharrisau mentioned, this proposal ignores endianess since it is irrelevant (the underlying byte, half-word, word, dword defines the byte order), but bit-numbering (LSB first or MSB first) should probably be added. |
|
||
## Compared to `enum` | ||
|
||
The `bitdata` type is similar to the existing `enum` type with the following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to make it more similar to a struct of various bit lengths?
Since enums are usually one long value of a certain width which would make it prone to more endian issues (The whole order would be off)
As well as a numerical value (enum) would require more packing and unpacking to read\write as well as masking, where as a struct is at the least one byte aligned (So the compiler would only have to pack\unpack anything under a byte and anything that's not byte aligned (that is, not a u8\16\32\64\etc.,) )
Also, anything saved as a bitdata as an enum would have to be the biggest number value (so if you have 20 bits of data, you'd be writing a 32 bit number instead of a struct where 20 bits would round up to 24 bits (or an array of 3 bytes)) This helps with storage in extremely tight areas, but more importantly in serial\Microcontroller communication (unless you accommodate on the non-pc end) as sending more bytes than necessary will throw off the program... (Best solution i can think of for this is MIDI, MIDI Commands are sent 3 Bytes at a time (24 Bits), so a 4bit value would mess it up.
As this will likely end up being "please try implementing this as a syntax extension", I'll copy in what the syntax extension may look like from my other post.
I don't think you can get virtual struct fields through any method yet (a metatable trait would be needed, or a significant upgrade to Index). So you are unable to de-structure the struct, or treat the fields as real fields. |
This RFC does not explain what happens if you use a |
This is a well-written and reasonably thorough RFC, which I greatly appreciate. However, while it would be convenient for certain use cases, I don't really see us adding a feature like this in the short term. This is basically because we are focused on building up the language in other areas (e.g., rounding out smart pointer design and type machinery). It is also somewhat unclear how widely applicable this feature would be. There are some pieces of the design that seem surprising to me and for which I would like to see more justification:
I guess that the last two points can be put another way: the presence of discriminants makes this feature "feel" typesafe, but the usage is very low-level and doesn't actually enforce any sort of invariant (i.e., that you access fields only when the discriminant has a suitable value). Maybe those sorts of invariants and type-level machinery are overkill when you're dealing in bits rather than larger values, but that is not immediately clear to me. |
@kballard My thought was that if there are two arms with the same discriminant bits, then the compiler should warn (or error) on the second one, since it is a match arm that can't be reached. @nikomatsakis As I mentioned above - no, I don't expect this in Rust any time soon. Having said that, I do believe quite a bit of code could be written in a much safer manner using this machinery, especially code that deals with hardware (like e.g. micro-controllers, graphics chips, device drivers), but also code that rely on communicating data at the bit-level. I think even I will work more on the proposal, but in terms of your points. The two-level namespace is not strictly needed since you can always introduce new variables and The reason that both use-cases (C unions and Rust-ish enums) are in the proposal is flexibility. Recall that we are just talking about describing the bits of (for instance) a |
Trying to get feedback on bit-data. I realize that it may not be a 1.0 priority, but discussion on this is still helpful.