How to implement bitwise operations on a bitflags enum?

不羁的心 提交于 2021-01-26 03:59:17

问题


I have an enum that looks like this:

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

I want to do a bitwise operation on several of the enum values. However, the Rust compiler complains:

an implementation of `std::ops::BitAnd` might be missing for `PublicFlags`.

回答1:


An enum in Rust is not intended to be used as bit flags. PublicFlags can only take the values given in the enum (and not a combination). So for instance, the following match statement is exhaustive:

let flags: PublicFlags;
...
match flags {
    PublicFlagVersion => {...}
    PublicFlagReset => {...}
    NoncePresent => {...}
    IdPresent => {...}
    PktNumLen4 => {...}
    PktNumLen2 => {...}
    PktNumLen1 => {...}
    Multipath => {...}
}

There is no way to have a PublicFlags variable with a combination of the flags.

The solution is to actually store the value as a u8, then use constants to store the value of each flag. This can be cumbersome, but thankfully the bitflags crate wraps all the boilerplate up in a macro for you. Here is an example how you would create your struct using 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));
} 


来源:https://stackoverflow.com/questions/43509560/how-to-implement-bitwise-operations-on-a-bitflags-enum

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!