#bit-flags #ffi #derive #debugging #flag-mast

flag-mast-derive

人体工程学Rust位标志

5个版本

0.2.1 2020年12月29日
0.2.0 2020年12月29日
0.1.2 2020年12月29日
0.1.1 2020年12月29日
0.1.0 2020年12月29日

#22 in #bit-flags


用于 2 个crate(通过 flag-mast

MIT/Apache

10KB
295 代码行

flag-mast

人体工程学Rust位标志

Crates.io Docs.rs GitHub top language

使用方法

“flag-mast”crate提供了一个衍生宏,用于帮助创建与C兼容的人体工程学位标志。

示例

use flag_mast::*;

#[derive(Flags, Default)]
#[flag(name = "BARKS", method_name = "can_bark", value = 0x1)]
#[flag(name = "SITS", method_name = "can_sit", value = 0x2)]
#[flag(name = "BROWN", method_name = "is_brown", value = 0x4)]
struct Dog(#[flag_backing_field] u32);

fn foo() {
  let mut dog = Dog::default();
  dog.set_can_bark(true)
     .set_can_sit(false)
     .set_is_brown(true);
	 
  if dog.is_brown() {
    println!("Cute doggo!");
  } else {
    println!("Doggo is not brown, but is cute anyway");
  }
}

衍生宏不会改变结构体的底层布局,甚至可以repr(C)!。

name”参数是标志的规范名称,它不必是有效的Rust标识符或遵循Rust的命名约定。

如果“name”参数是合适的Rust标识符(可以自定义前缀),则可以省略“method_name”参数。

value”参数可以是整数字面量或包含表示标志值的表达式的字符串。

value”不需要与支持字段具有相同的精确类型,只需能够转换为此类型即可。

flag_backing_field”属性指定用于存储位标志的结构体字段。

这意味着我们还可以有

use flag_mast::*;

const BLUE: u8 = 0x1;
const RED: u8 = 0x2;

mod secondary_colours {
  pub const YELLOW: u16 = 0x4;
}


#[derive(Flags, Default)]
#[flag(name = "blue", value = "BLUE")]
#[flag(name = "red", value = "RED")]
#[flag(name = "yellow", value = "secondary_colours::YELLOW")]
#[flag(name = "purple", value = "BLUE & RED")]
#[flag(name = "black", value = 0x8)]
#[repr(C)]
struct Colour{
  is_useful: bool,
  #[flag_backing_field] 
  flags: u32
}

fn bar() {
  let mut colour = Colour::default();
  colour.set_blue(true);
  colour.set_red(true);
  
  if colour.purple() {
    println("That's red AND blue!");
  }
}

自动调试实现

该衍生宏还可以自动为你生成一个适用于你的标志的Debug实现。此行为由一个额外的属性控制。

use flag_mast::*;

#[derive(Flags, Default)]
#[flag_debug]
#[flag(name = "one", value = 4)]
#[flag(name = "second", method_name = "two", value = 8)]
#[flag(name = "three", value = 16)]
struct Buttons(#[flag_backing_field] u16)

fn baz() {
  let mut buttons = Buttons::default();
  buttons.set_one(true);
  
  println!("{:?}", buttons);
  println!("---");
  println!("{:#?}", buttons);
}

这将打印(注意使用的是方法名

Buttons { one: true, two: false, three: true }
---
Buttons {
    one: true,
    two: false,
    three: false
}

你也可以通过指定compact参数到flag_debug属性来选择(可能)更紧凑的调试格式。此格式只显示已设置的标志。

use flag_mast::*;

#[derive(Flags, Default)]
#[flag_debug(compact)]
#[flag(name = "one", value = 4)]
#[flag(name = "second", method_name = "two", value = 8)]
#[flag(name = "three", value = 16)]
struct Buttons(#[flag_backing_field] u16)

fn baz() {
  let mut buttons = Buttons::default();
  buttons.set_one(true);
  buttons.set_two(true);
  
  println!("{:?}", buttons);
  println!("---");
  println!("{:#?}", buttons);
}

这将打印(注意使用的是名称

Buttons { "one", "second" }
---
Buttons {
    "one",
    "second",
}

许可证

flag-mast采用MIT许可和Apache 2.0许可证。您可以选择您喜欢的任意一个。

依赖关系

~1.5MB
~36K SLoC