Generate an enum #449

Open
opened 2025-07-15 08:17:27 -05:00 by axelkar · 1 comment
axelkar commented 2025-07-15 08:17:27 -05:00 (Migrated from github.com)

Statically having an enum for unique flags would be super useful. As the main benefit, you could match on them like normal.

Contiguous power-of-two flags could also be represented by their binary logarithms. Here's some choices for the integer primitive:

  • u8 can represent the indices of all bits in u128 (2⁸ > log₂ 2¹²⁸)
  • u32 from trailing_zeros return type

As an example of how this would make lookup tables easy, compare the following code blocks:

bitflags::bitflags! {
  struct Flags: u32 {
    const A = 1 << 0;
    const B = 1 << 1;
    const C = 1 << 2;
    const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
  }
}

let map = [OtherValue::default(); Flags::all().bits().count_ones() as usize];

let flags: Flags = from_io();
flags.iter_names(|flag| {
  assert!(flag.bits().is_power_of_two()); // even this can't be guaranteed because ABC exists

  let index = flag.bits().trailing_zeros() as usize;
  map[index]
}).collect::<Vec<OtherValue>>();
bitflags::bitflags! {
  struct Flags: u32 {
    const A = 1 << 0;
    const B = 1 << 1;
    const C = 1 << 2;
    const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
  }
}

/// automatically generated
#[repr(u32)]
enum Flag {
  A = 0,
  B = 1,
  C = 2,
}

let map = [OtherValue::default(); Flag::count()];

let flags: Flags = from_io();
flags.iter_enum(|flag| {
  map[flag as u32 as usize]
}).collect::<Vec<OtherValue>>();

Edit: I just found the enumflags2 crate, but I want to see how this is responded to

Statically having an enum for unique flags would be super useful. As the main benefit, you could match on them like normal. Contiguous power-of-two flags could also be represented by their binary logarithms. Here's some choices for the integer primitive: - **u8** can represent the indices of all bits in u128 (2⁸ > log₂ 2¹²⁸) - **u32** from [`trailing_zeros`](https://doc.rust-lang.org/std/primitive.u64.html#method.trailing_zeros) return type As an example of how this would make lookup tables easy, compare the following code blocks: ```rust bitflags::bitflags! { struct Flags: u32 { const A = 1 << 0; const B = 1 << 1; const C = 1 << 2; const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); } } let map = [OtherValue::default(); Flags::all().bits().count_ones() as usize]; let flags: Flags = from_io(); flags.iter_names(|flag| { assert!(flag.bits().is_power_of_two()); // even this can't be guaranteed because ABC exists let index = flag.bits().trailing_zeros() as usize; map[index] }).collect::<Vec<OtherValue>>(); ``` ```rust bitflags::bitflags! { struct Flags: u32 { const A = 1 << 0; const B = 1 << 1; const C = 1 << 2; const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); } } /// automatically generated #[repr(u32)] enum Flag { A = 0, B = 1, C = 2, } let map = [OtherValue::default(); Flag::count()]; let flags: Flags = from_io(); flags.iter_enum(|flag| { map[flag as u32 as usize] }).collect::<Vec<OtherValue>>(); ``` Edit: I just found the `enumflags2` crate, but I want to see how this is responded to
KodrAus commented 2025-07-18 18:49:52 -05:00 (Migrated from github.com)

Hi @axelkar 👋 Thanks for the suggestion! This is something that would be out-of-scope for bitflags to support natively, since it doesn't just deal with flags where a single bit uniquely corresponds to a single flag that could be made into an enum variant.

Hi @axelkar :wave: Thanks for the suggestion! This is something that would be out-of-scope for `bitflags` to support natively, since it doesn't just deal with flags where a single bit uniquely corresponds to a single flag that could be made into an `enum` variant.
Sign in to join this conversation.
No labels
bug
good first issue
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-bitflags/bitflags#449
No description provided.