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 次
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