この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Introduction
bitflagsはビットフラグを簡単に定義することができるマクロを
提供してくれるcrateです。
複数のフラグ管理をシンプルにしてくれます。
Environment
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 11.3.1
- rust : 1.60.0
Try
cargo new でプロジェクトをつくったら
Cargo.tomlに依存ライブラリを記述します。
[dependencies]
bitflags = "1.3.2"
マクロ(bitflags!)をつかって複数のフラグを管理する構造体として定義します。
↓ではu32型の変数1つでA,B,Cの3つのフラグを管理します。
use bitflags::bitflags;
bitflags! {
pub struct Flags: u32 {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
}
}
普通に変数に代入して比較したり、
containsで対象のフラグが含まれているかチェックできます。
let flag = Flags::A;
assert_eq!(flag, Flags::A);
assert_eq!(flag.contains(Flags::A), true);
複数のフラグもセットできます。
それぞれの変数で&をとったり引き算したりできます。
//複数フラグセット
let flag_1 = Flags::A | Flags::C;
let flag_2 = Flags::B | Flags::C;
assert_eq!((flag_1 & flag_2), Flags::C);
assert_eq!((flag_1 -flag_2), Flags::A);
assert_eq!(!flag_2, Flags::A);
実際の値を表示するにはbitsを使いましょう。
println!("{:#010b}", Flags::A.bits);// 0b00000001
println!("{:#010b}", Flags::B.bits);// 0b00000010
println!("{:#010b}", Flags::C.bits);// 0b00000100
println!("{:#010b}", flag.bits);//0b00000001
println!("{:#010b}", flag_1.bits);//0b00000101
println!("{:#010b}", flag_2.bits);//0b00000110
removeとinsertでフラグの変更。
let mut flag:Flags = Flags::A;
assert_eq!(flag, Flags::A);
flag = Flags::A | Flags::C;
assert_eq!(flag, Flags::A | Flags::C);
assert_eq!(flag & Flags::A, Flags::A);
assert_eq!(flag & Flags::C, Flags::C);
//remove
flag.remove(Flags::C);
assert_eq!(flag.contains(Flags::A), true);
assert_eq!(flag.contains(Flags::B), false);
assert_eq!(flag.contains(Flags::C), false);
//insert
flag.insert(Flags::C);
assert_eq!(flag.contains(Flags::A), true);
assert_eq!(flag.contains(Flags::B), false);
assert_eq!(flag.contains(Flags::C), true);
all関数ですべてのフラグをたてることができる。
let all_flag = Flags::all();
println!("{:#010b}", all_flag.bits);//0b00000111
簡単な説明は以上です。
これ以外にも機能があるので、ドキュメントをご確認ください。
Summary
bitflagsマクロを使うと、普通にやるよりシンプルにフラグ管理ができます。
boolで8つのフラグを構造体で定義したら8bit必要ですが、
bitflagsでu32のフラグを使えば4bitで管理できます。
無駄なリソースも使わず、安全に計算できたりもするので楽ですね。