7 个版本 (4 个重大更新)
0.11.0 | 2024年4月4日 |
---|---|
0.10.1 | 2023年6月3日 |
0.10.0 | 2021年7月24日 |
0.9.0 | 2021年7月15日 |
0.7.1 | 2020年2月12日 |
#100 在 #byte-slice
每月下载量 392
在 6 个crate中使用(通过 bitbuffer)
52KB
1.5K SLoC
自动为struct和enum生成BitRead
和BitReadSized
实现
Structs
只要struct中的每个字段都实现了BitRead
或BitReadSized
,就可以为struct推导出实现。
struct是按定义的顺序逐字段读取的,如果设置了字段的尺寸,将使用stream.read_sized()
,否则将使用stream_read()
。
可以使用3种不同的方法设置字段的尺寸
- 使用
size
属性将尺寸设置为整数 - 使用
size
属性将先前定义的字段作为尺寸 - 使用
read_bits
属性读取指定数量的位作为整数,使用生成的值作为尺寸
当推导出BitReadSized
时,可以在尺寸属性中将输入尺寸用作input_size
字段。
示例
use bitbuffer::BitRead;
#[derive(BitRead)]
struct TestStruct {
foo: u8,
str: String,
#[size = 2] // when `size` is set, the attributed will be read using `read_sized`
truncated: String,
bar: u16,
float: f32,
#[size = 3]
asd: u8,
#[size_bits = 2] // first read 2 bits as unsigned integer, then use the resulting value as size for the read
dynamic_length: u8,
#[size = "asd"] // use a previously defined field as size
previous_field: u8,
}
use bitbuffer::BitReadSized;
#[derive(BitReadSized, PartialEq, Debug)]
struct TestStructSized {
foo: u8,
#[size = "input_size"]
string: String,
#[size = "input_size"]
int: u8,
}
Enums
只要enum的每个变体都没有字段,或者有一个未命名的字段,该字段实现了BitRead
或BitReadSized
,就可以为enum推导出实现。
首先读取一定数量的位作为enum的区分符,然后读取读取的区分符对应的变体。
有关为实现 BitReadSized
的字段设置输入大小的详细信息,请参阅上方 Structs
部分中关于大小的部分。
变体的判别符默认为每个字段递增一,从 0
开始。您可以覆盖字段的判别符,这将同时更改后续每个字段的判别符。
示例
#
#[derive(BitRead)]
#[discriminant_bits = 2]
enum TestBareEnum {
Foo,
Bar,
Asd = 3, // manually set the discriminant value for a field
}
#
#[derive(BitRead)]
#[discriminant_bits = 2]
enum TestUnnamedFieldEnum {
#[size = 5]
Foo(i8),
Bar(bool),
#[discriminant = 3] // since rust only allows setting the discriminant on field-less enums, you can use an attribute instead
Asd(u8),
}
#
#[derive(BitReadSized, PartialEq, Debug)]
#[discriminant_bits = 2]
enum TestUnnamedFieldEnumSized {
#[size = 5]
Foo(i8),
Bar(bool),
#[discriminant = 3]
#[size = "input_size"]
Asd(u8),
}
对齐
您可以使用 #[align] 属性请求结构体、枚举或字段的对齐。
#
#[derive(BitRead)]
#[align] // align the reader before starting to read the struct
struct TestAlignStruct {
#[size = 1]
foo: u8,
#[align] // align the reader before reading the field
bar: u8,
}
它还可以应用于非单元枚举变体
#
#[derive(BitRead)]
#[align] // align the reader before starting to read the enum
#[discriminant_bits = 2]
enum TestAlignEnum {
Foo(u8),
#[align] // align the reader before reading the variant (but after reading the discriminant)
Bar(u8),
}
端序
如果 BitRead
或 BitReadSized
推导的 struct 需要一个 Endianness 类型参数,您需要告诉 derive 宏所使用的类型参数名称
#
#[derive(BitRead)]
#[endianness = "E"]
struct EndiannessStruct<'a, E: Endianness> {
size: u8,
#[size = "size"]
stream: BitReadStream<'a, E>,
}
如果您指定了结构体的端序,这也需要这样做
#
#[derive(BitRead)]
#[endianness = "BigEndian"]
struct EndiannessStruct<'a> {
size: u8,
#[size = "size"]
stream: BitReadStream<'a, BigEndian>,
}
依赖项
~330–780KB
~18K SLoC