bitflags
bitflags copied to clipboard
Idea: represent the flag constants as an enum
I had the idea the flags instead of being associated constants could be an enum that is repr of the same underlying integer type. Then the full struct can be thought of as a set like container for the enum values. Having the enum has some advantages in type safety and would allow you to easily implement an iterator over the set flags. One significant change is that some operations would be duplicated. For example in the set (flags struct) you can insert, remove, toggle with another set (which is what the crate does at the moment) but you can also do the same operations on individual flag enum values.
Sketch of generated code:
struct Flags(u32) {
#[repr(u32)]
enum Flag {
A = 1,
B = 2,
C = 4,
}
pub fn insert(&mut self, other: Flags);
pub fn insert_single(&mut self, other: Flag);
}
Overall this probably doesn't fit in nicely enough with the current functionality but I wanted to bring it up since I didn't see it discussed before through the Github search.
I actually also just came here to post this same idea! Main motivation is the auto-complete will actually work in IDEs.
So if I understand correctly, the Flag
enum would only be used for stuff like iterating and inserting single flags? Because the result of operations like |
couldn't be stored as a Flag
, as that would lead to undefined behaviour.
Having the enum has some advantages in type safety and would allow you to easily implement an iterator over the set flags.
Could you elaborate? I don't see how this helps in implementing an iterator, nor do I think it would be a big help in type safety, as a huge part of bitflags
is dealing with sets of flags (if you're only using individual flags, you might as well use a normal enum).
Main motivation is the auto-complete will actually work in IDEs.
I think that's a problem with macros, not with associated constants vs enum variants.
As you noticed having this enum allows you to distinguish a single flag from a set of flags. I understand that the usual use case for bitflags is the set but sometimes you might want to work with a single flag which the set cannot represent. For example this is the case when iterating over all the set flags in a set. The enum has more type safety in this case than a plain integer.
I think there are legitimate scenarios where it does make sense to be able to loop over both the "enabled" flags set and the "unenabled" flags set without much fuss.
In the last few years IDE support has come a long way for Rust. CLion for instance can see through macros and autocomplete on the associated constants you specify in your flags types.
This is an interesting suggestion, but I don't think it's something we'd consider for bitflags
. That doesn't mean it's not worth spinning up some kind of new enumflags
library for it!