add MyFlags::Abc::iter_equal_names() method #469

Closed
ssrlive wants to merge 1 commit from main into main
ssrlive commented 2025-11-08 08:15:38 -06:00 (Migrated from github.com)

Sometimes we need to retrieve the string names of the Flags values ​​we defined, so I added the method names.

Sometimes we need to retrieve the string names of the Flags values ​​we defined, so I added the method `names`.
KodrAus commented 2026-02-06 17:26:28 -06:00 (Migrated from github.com)

Hi @ssrlive 👋

Sorry I seem to have missed this in my inbox. I think this functionality is already covered by the iter_names method, which iterates over defined flags in a value, including both their name and their value.

Hi @ssrlive :wave: Sorry I seem to have missed this in my inbox. I think this functionality is already covered by [the `iter_names` method](https://docs.rs/bitflags/latest/bitflags/example_generated/struct.Flags.html#method.iter_names), which iterates over defined flags in a value, including both their name and their value.
KodrAus commented 2026-05-28 21:05:06 -05:00 (Migrated from github.com)

Thanks for the PR @ssrlive! I do believe we've already got this functionality in iter_names, so will go ahead and close this one.

Thanks for the PR @ssrlive! I do believe we've already got this functionality in `iter_names`, so will go ahead and close this one.
ssrlive commented 2026-06-02 21:23:57 -05:00 (Migrated from github.com)

Based on my testing, iter_names is completely unrelated to the content of my PR. My test code is provided below; the commented-out sections represent the parts that do not align with my original intent.

fn main() {
    bitflags::bitflags! {
        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
        struct TestFlags: u32 {
            const A = 0b00000001;
            const ZERO = 0;
            const B = 0b00000010;
            const C = 0b00000100;
            const CC = Self::C.bits();
            const D = 0b10000100;
            const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
            const AB = Self::A.bits() | Self::B.bits();
            const AC = Self::A.bits() | Self::C.bits();
            const CB = Self::B.bits() | Self::C.bits();
        }
    }


    assert_eq!(TestFlags::A.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["A"]);

    println!("ZERO: {:?}", TestFlags::ZERO.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::ZERO.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["ZERO"]);

    assert_eq!(TestFlags::B.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["B"]);

    println!("C: {:?}", TestFlags::C.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::C.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["C", "CC"]);

    assert!(TestFlags::C.iter_names().any(|n| n.0 == "CC" || n.0 == "C"));

    println!("CC: {:?}", TestFlags::CC.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::CC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["C", "CC"]);
    assert!(TestFlags::CC.iter_names().any(|n| n.0 == "CC" || n.0 == "C"));

    println!("D: {:?}", TestFlags::D.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::D.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["D"]);

    println!("ABC: {:?}", TestFlags::ABC.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::ABC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["ABC"]);

    println!("AB: {:?}", TestFlags::AB.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::AB.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["AB"]);

    println!("AC: {:?}", TestFlags::AC.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::AC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["AC"]);

    println!("CB: {:?}", TestFlags::CB.iter_names().map(|n|n.0).collect::<Vec<_>>());
    // assert_eq!(TestFlags::CB.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["CB"]);

    let xyz = TestFlags::from_bits_retain(123456);
    assert!(xyz.iter_names().map(|n| n.0).collect::<Vec<_>>().is_empty());
}

the out put

name result expected
ZERO: [] ["ZERO"]
C: ["C"] ["C", "CC"]
CC: ["C"] ["C", "CC"]
D: ["C", "D"] ["D"]
ABC: ["A", "B", "C"] ["ABC"]
AB: ["A", "B"] ["AB"]
AC: ["A", "C"] ["AC"]
CB: ["B", "C"] ["CB"]
Based on my testing, `iter_names` is completely unrelated to the content of my PR. My test code is provided below; the commented-out sections represent the parts that do not align with my original intent. ```rust fn main() { bitflags::bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] struct TestFlags: u32 { const A = 0b00000001; const ZERO = 0; const B = 0b00000010; const C = 0b00000100; const CC = Self::C.bits(); const D = 0b10000100; const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits(); const AB = Self::A.bits() | Self::B.bits(); const AC = Self::A.bits() | Self::C.bits(); const CB = Self::B.bits() | Self::C.bits(); } } assert_eq!(TestFlags::A.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["A"]); println!("ZERO: {:?}", TestFlags::ZERO.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::ZERO.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["ZERO"]); assert_eq!(TestFlags::B.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["B"]); println!("C: {:?}", TestFlags::C.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::C.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["C", "CC"]); assert!(TestFlags::C.iter_names().any(|n| n.0 == "CC" || n.0 == "C")); println!("CC: {:?}", TestFlags::CC.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::CC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["C", "CC"]); assert!(TestFlags::CC.iter_names().any(|n| n.0 == "CC" || n.0 == "C")); println!("D: {:?}", TestFlags::D.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::D.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["D"]); println!("ABC: {:?}", TestFlags::ABC.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::ABC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["ABC"]); println!("AB: {:?}", TestFlags::AB.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::AB.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["AB"]); println!("AC: {:?}", TestFlags::AC.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::AC.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["AC"]); println!("CB: {:?}", TestFlags::CB.iter_names().map(|n|n.0).collect::<Vec<_>>()); // assert_eq!(TestFlags::CB.iter_names().map(|n|n.0).collect::<Vec<_>>(), vec!["CB"]); let xyz = TestFlags::from_bits_retain(123456); assert!(xyz.iter_names().map(|n| n.0).collect::<Vec<_>>().is_empty()); } ``` the out put | name | result | expected | |------| ------ | -------- | | ZERO: | [] | ["ZERO"] | | C: | ["C"] | ["C", "CC"] | | CC: | ["C"] | ["C", "CC"] | | D: | ["C", "D"] | ["D"] | | ABC: | ["A", "B", "C"] | ["ABC"] | | AB: | ["A", "B"] | ["AB"] | | AC: | ["A", "C"] | ["AC"] | | CB: | ["B", "C"] | ["CB"] |
KodrAus commented 2026-06-02 23:32:47 -05:00 (Migrated from github.com)

@ssrlive I see, so you want to iterate over all named flags that are equivalent to a particular value? I worry this does have too much overlap with the existing iter_names method, which is maybe better named as iter_contained_names, and this one as iter_equal_names.

I'd be open to exploring it a bit more if we can figure out how to untangle those concepts a bit.

@ssrlive I see, so you want to iterate over all named flags that are equivalent to a particular value? I worry this does have too much overlap with the existing `iter_names` method, which is maybe better named as `iter_contained_names`, and this one as `iter_equal_names`. I'd be open to exploring it a bit more if we can figure out how to untangle those concepts a bit.
ssrlive commented 2026-06-02 23:45:39 -05:00 (Migrated from github.com)

So, how about I start by renaming the relevant parts of my PR to iter_equal_names?

So, how about I start by renaming the relevant parts of my PR to `iter_equal_names`?
ssrlive commented 2026-06-03 00:10:35 -05:00 (Migrated from github.com)

I have renamed all of that.

I have renamed all of that.
KodrAus commented 2026-06-03 15:18:38 -05:00 (Migrated from github.com)

@ssrlive It looks like I can't re-open the PR anymore, would you be happy to submit a fresh one and we can take a look?

@ssrlive It looks like I can't re-open the PR anymore, would you be happy to submit a fresh one and we can take a look?

Pull request closed

Sign in to join this conversation.
No reviewers
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!469
No description provided.