1. 位域

1.1 定义并操作位域风格的类型

  需要安装bitflags库,可通过cargo add bitflags 命令安装

[dependencies]
bitflags = "2.1.0"

  如下实例在 bitflags! 宏的帮助下创建类型安全的位域类型 MyFlags,并为其实现基本的清理操作(clear 方法)以及 Display trait。随后,展示了基本的按位操作和格式化。

use bitflags::bitflags;
use std::fmt;

// 定义 MyFlags 枚举类型,表示一个 32 位二进制标志位
bitflags! {
#[derive(Clone, Copy, PartialEq, Eq, Debug )]
struct MyFlags: u32 {
const FLAG_A = 0b00000001; // 第一位标志位表示 FLAG_A
const FLAG_B = 0b00000010; // 第二位标志位表示 FLAG_B
const FLAG_C = 0b00000100; // 第三位标志位表示 FLAG_C
const FLAG_ABC = Self::FLAG_A.bits() // FLAG_ABC 表示 FLAG_A、FLAG_B 和 FLAG_C 的集合
| Self::FLAG_B.bits()
| Self::FLAG_C.bits();
}
}

impl MyFlags {
// 实现 clear 方法,清空标志位
pub fn clear(&mut self) -> &mut MyFlags {
*self.0.bits_mut() = 0; // 将 MyFlags 对应的 u32 类型全部置为 0
self
}
}

impl std::fmt::Display for MyFlags {
// 实现 fmt::Display trait,使得 MyFlags 类型可以被格式化输出
fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result {
write!(f, "{:032b}", self.bits()) // 将 MyFlags 转换为 32 位二进制数输出
}
}

fn main() {
// 枚举类型可以像整数一样进行按位运算
let e1 = MyFlags::FLAG_A | MyFlags::FLAG_C; // e1 包含 FLAG_A 和 FLAG_C
let e2 = MyFlags::FLAG_B | MyFlags::FLAG_C; // e2 包含 FLAG_B 和 FLAG_C
assert_eq!((e1 | e2), MyFlags::FLAG_ABC); // e1 和 e2 的并集包含 FLAG_ABC
assert_eq!((e1 & e2), MyFlags::FLAG_C); // e1 和 e2 的交集包含 FLAG_C
assert_eq!((e1 - e2), MyFlags::FLAG_A); // e1 减去 e2 的差集包含 FLAG_A
assert_eq!(!e2, MyFlags::FLAG_A); // e2 的补集不包含 FLAG_A

let mut flags = MyFlags::FLAG_ABC;
assert_eq!(format!("{}", flags), "00000000000000000000000000000111"); // 输出 MyFlags 为 32 位二进制数
assert_eq!(
format!("{}", flags.clear()),
"00000000000000000000000000000000" // 清空 MyFlags,输出 0
);
assert_eq!(format!("{:?}", MyFlags::FLAG_B), "MyFlags(FLAG_B)"); // 输出 MyFlags 枚举类型
assert_eq!(
format!("{:?}", MyFlags::FLAG_A | MyFlags::FLAG_B),
"MyFlags(FLAG_A | FLAG_B)"
);
}
  • 运行cargo run校验成功