如何在bitflags枚举上实现按位运算?

Bre*_*son 8 rust

我有一个看起来像这样的枚举:

#[repr(u8)]
pub enum PublicFlags {
    PublicFlagVersion = 0x01,
    PublicFlagReset = 0x02,
    NoncePresent = 0x04,
    IdPresent = 0x08,
    PktNumLen4 = 0x30,
    PktNumLen2 = 0x20,
    PktNumLen1 = 0x10,
    Multipath = 0x40,
}
Run Code Online (Sandbox Code Playgroud)

我想对几个枚举值进行逐位运算.但是,Rust编译器抱怨:

an implementation of `std::ops::BitAnd` might be missing for `PublicFlags`.
Run Code Online (Sandbox Code Playgroud)

Sas*_*ser 12

这可以作为替代答案,无需新的依赖项。

pub mod PublicFlags {
    pub const PublicFlagVersion: u8 = 0x01;
    pub const PublicFlagReset: u8 = 0x02;
    pub const NoncePresent: u8 = 0x04;
    pub const IdPresent: u8 = 0x08;
    pub const PktNumLen4: u8 = 0x30;
    pub const PktNumLen2: u8 = 0x20;
    pub const PktNumLen1: u8 = 0x10;
    pub const Multipath: u8 = 0x40;
}
Run Code Online (Sandbox Code Playgroud)

您可以像使用枚举一样使用 来引用这些值PublicFlags::PublicFlagVersion,或者use PublicFlags::*;如果在不指定命名空间的情况下引用这些值更简洁,则可以添加。

  • 该解决方案有一个很大的缺点:当使用匹配语句时,如果您使用枚举,编译器可以检测到丢失的情况。这不适用于此解决方案。 (3认同)
  • @Phidelux 标志的要点在于将它们组合起来,这对于枚举来说是不可能的。仅仅匹配各个标志是一件毫无意义的事情。 (2认同)

Djz*_*zin 11

enum在锈不打算用作位标志.PublicFlags可以采取在枚举(和未组合)给出的值.因此,例如,以下匹配声明是详尽无遗的:

let flags: PublicFlags;
...
match flags {
    PublicFlagVersion => {...}
    PublicFlagReset => {...}
    NoncePresent => {...}
    IdPresent => {...}
    PktNumLen4 => {...}
    PktNumLen2 => {...}
    PktNumLen1 => {...}
    Multipath => {...}
}
Run Code Online (Sandbox Code Playgroud)

没有办法让PublicFlags变量与标志组合.

解决方案是将值实际存储为a u8,然后使用常量来存储每个标志的值.这可能很麻烦,但幸运的是,bitflags crate将所有样板包装在一个宏中.下面是一个如何使用bitflags创建结构的示例:

#[macro_use]
extern crate bitflags;

bitflags! {
    flags PublicFlags: u8 {
        const PUBLIC_FLAG_VERSION = 0x01,
        const PUBLIC_FLAG_RESET = 0x02,
        const NONCE_PRESENT = 0x04,
        const ID_PRESENT = 0x08,
        const PKT_NUM_LEN_4 = 0x30,
        const PKT_NUM_LEN_2 = 0x20,
        const PKT_NUM_LEN_1 = 0x10,
        const MULTIPATH = 0x40,
    }
}

fn main() {
    let flag = PUBLIC_FLAG_VERSION | ID_PRESENT;
    assert!((flag & MULTIPATH).is_empty()); 
    assert!(flag.contains(ID_PRESENT));
} 
Run Code Online (Sandbox Code Playgroud)

  • 出色的!这有效!我还可以将枚举强制转换为“u8”。 (2认同)