#bit-fields #bit #proc-macro #bitfields #getter-setter

bitf

该软件包提供了一种过程宏,可以轻松地将结构体转换为位域

9 个版本 (5 个稳定版)

1.3.0 2022年1月19日
1.2.0 2022年1月15日
0.11.1 2022年1月15日
0.10.1 2022年1月6日
0.9.0 2022年1月1日

#1532数据结构

每月下载量 29 次

MIT/Apache

27KB
393 代码行

bitf

Rust 过程宏,可快速从结构体生成位域。

功能

  • 8 到 128 位的任意大小
  • 自动实现 获取器设置器 以及默认值。
  • 支持在结构体上使用其他属性
  • 字段声明可以是最低有效位或最高有效位
  • 支持自定义返回类型(基本类型和自定义类型)
  • 支持为每个字段自定义可见性
  • 跳过标记为保留的字段的实现
  • 实现一个美观打印关联函数:pprint()

默认情况下

  • 从最低有效位开始声明字段;
  • 将所有字段声明为公共的;
  • 不实现美观打印函数;

用法和语法

可以使用以下方式使用宏

#[bitf(size, opt_arg1, opt_arg2, opt_arg3)]

Where size can be:
    u8
    u16
    u32
    u64
    u128

There are 3 optional parameters:
Order:  can be 'lsb' or 'msb'
Visibility: 'no_pub'
Pretty Print: 'pp'

大小

size 参数将限制位域的总大小。

顺序

order 参数是可选的,并将改变声明的字段顺序。默认情况下,该参数设置为 lsb。当将顺序参数设置为 msb 时,结构体中声明的第一个字段将放在最高有效位上,反之亦然。

可见性

visibility 参数是可选的,并将改变声明的字段的可见性。它只能设置为 no_pub。默认情况下,所有字段都声明为公共的,使用 no_pub 标志将取消此行为并依赖于用户声明的可见性。

因此,字段的声明和位置基于字段声明

use bitf::bitf;

#[bitf(u8, lsb, pp)]
struct Example
{
    any_case_name_2: (),        // () is used to specify to use the raw type defined in the attribute (here is u8)
    _reserved_4:     (),        // This field will not be implemented as the name is _reserved
    name_B_2:        u16,	// Return type override. The `get` method implemented will return a u16
    				// Custom types can be used, be will need to implement the From trait
				// Please see the test file in "test/attribute_macro.rs" for an example
}

// The internal, full value of the field can be accessed as :

let e = Example::default();
println!("{}", e.raw);

// and the representation of the bitfield can be accessed via
e.pprint();

当与其他属性结合使用时,请确保在 #[derive(..)] 属性之前实现,否则扩展顺序可能会(会)失败。

use bitf::bitf;

#[repr(C)]
#[allow(dead_code)]
#[bitf(u8)]
#[derive(Debug)]
struct MyStruct
{
    fieldA_4:	(),
    fieldB_4:	(),
}

美观打印

Pretty Print参数通过pp开关设置。此开关将在结构体上实现一系列关联函数,通过pprint()访问。此函数将生成以下输出(对于128位位域)


64     60  59   57  56                 40      35         27     23   21    18  17           7   6     3   2    0
┌──────┬───┬────┬───┬──────────────────┬───────┬──────────┬──────┬────┬─────┬───┬────────────┬───┬─────┬───┬────┐
│ 1111 │ 1 │ 01 │ 0 │ rrrrrrrrrrrrrrrr │ 01101 │ 11110101 │ 0110 │ 00 │ 010 │ 0 │ 1000110101 │ 0 │ 110 │ 0 │ 10 │
└──────┴───┴────┴───┴──────────────────┴───────┴──────────┴──────┴────┴─────┴───┴────────────┴───┴─────┴───┴────┘

标记为"rrrrrrrr..."的字段表示保留字段。这些字段在使用名称_reserved_usize声明时定义

请注意,没有分页机制或任何适应shell大小的智能系统。因此,如果您尝试打印128个1字节宽的位域,除非您有异常宽的屏幕,否则可能会失败

保留字段:跳过字段的实现

在声明字段时,可以使用以下语法来跳过其实现。_reserved_intSize

在之前的示例中,字段_reserved_4的4位将不会实现。不会为此字段生成访问器。

示例

考虑以下位域

7             0
0 0 0 0 0 0 0 0
| | | | | | | |_ field_a    - Size 1
| | | | | | |___ fieldB     - Size 1
| | | | | |_____ fieldC     - Size 1
| |  \|/________ reserved   - Size 3
\ /_____________ field_D    - Size 2

可以通过以下声明和宏使用来实现

use bitf::bitf;

#[bitf(u8)]
struct MyStruct
{
    field_a_1:  (),
    fieldB_1:   (),
    FieldC_1:   (),
    _reserved_3: (),
    Field_D_2:  (),
}

这将生成以下结构和相关方法

struct MyStruct
{
  pub raw:  u8,
}

impl MyStruct
{
    pub fn field_a(self: &Self) -> u8 { /* bitwise logic */ 0 }
    pub fn set_field_a(self: &Self, val: u8) { /* bitwise logic */ }
    pub fn fieldB(self: &Self) -> u8 { /* bitwise logic */ 0 }
    pub fn set_fieldB(self: &Self, val: u8) { /* bitwise logic */ }
    /*
     * And so on...
     */
    
}

impl Default for MyStruct 
{ 
    fn default() -> Self
    {
        MyStruct { raw: 0x0 }
    } 
}

//So you can easily set and read values of each defined bitfield:

let mut bf = MyStruct::default();

bf.set_field_a(1);
bf.set_fieldB(1);
println!("{:#010b}", bf.field_a());

待办事项

  • 一个短视的决定使得目前宏假定声明的字段格式为CamelCaseName_Size。最好是实现Any_Case_Size形式
  • 生成适当的Rust文档
  • 实现美观打印,便于读取位域
  • 跳过实现定义为保留的字段(或不是?)。已完成:您可以使用命名约定_reserved_intSize将字段标记为保留
  • 实现检查,如果位域太小无法容纳所有声明的字段,则失败
  • 添加lsb/msb作为可选参数,默认为lsb
  • 添加可见性修饰符参数。所有声明的字段都实现为pub(默认)或由用户指定
  • 为每个声明的字段添加自定义返回类型
  • 支持向结构体添加属性
  • ???

依赖项

~270–720KB
~17K SLoC