11 个版本 (4 个重大更新)
0.5.0 | 2024 年 7 月 25 日 |
---|---|
0.4.1 | 2024 年 6 月 13 日 |
0.3.0 | 2024 年 3 月 28 日 |
#995 in 编码
每月 274 次下载
67KB
1.5K SLoC
bin-proto
简单的 Rust 结构化位级编/解码器。
是 protocol 的改进和现代化分支。相对于 deku,它更高效(但稍微功能较少)。
此包增加了一个可以应用于类型的特质(以及一个用于易用性的自定义 derive),允许结构化数据从任何二进制流发送和接收。如果您需要位流,建议使用 bitstream_io,因为它们的 BitRead
和 BitWrite
特质正在内部使用。
示例
将以下内容添加到您的 Cargo.toml
[dependencies]
bin-proto = "0.5"
然后定义一个具有 #[derive(bin_proto::ProtocolRead, bin_proto::ProtocolWrite)]
属性的类型。
use bin_proto::{ProtocolRead, ProtocolWrite, ProtocolNoCtx};
#[derive(Debug, ProtocolRead, ProtocolWrite, PartialEq)]
#[protocol(discriminant_type = "u8")]
#[protocol(bits = 4)]
enum E {
V1 = 1,
#[protocol(discriminant = "4")]
V4,
}
#[derive(Debug, ProtocolRead, ProtocolWrite, PartialEq)]
struct S {
#[protocol(bits = 1)]
bitflag: bool,
#[protocol(bits = 3)]
bitfield: u8,
enum_: E,
#[protocol(write_value = "self.arr.len() as u8")]
arr_len: u8,
#[protocol(tag = "arr_len as usize")]
arr: Vec<u8>,
#[protocol(tag(type = "u16", write_value = "self.prefixed_arr.len() as u16"))]
prefixed_arr: Vec<u8>,
#[protocol(flexible_array_member)]
read_to_end: Vec<u8>,
}
assert_eq!(
S::from_bytes(&[
0b1000_0000 // bitflag: true (1)
| 0b101_0000 // bitfield: 5 (101)
| 0b0001, // enum_: V1 (0001)
0x02, // arr_len: 2
0x21, 0x37, // arr: [0x21, 0x37]
0x00, 0x01, 0x33, // prefixed_arr: [0x33]
0x01, 0x02, 0x03, // read_to_end: [0x01, 0x02, 0x03]
], bin_proto::ByteOrder::BigEndian).unwrap(),
S {
bitflag: true,
bitfield: 5,
enum_: E::V1,
arr_len: 2,
arr: vec![0x21, 0x37],
prefixed_arr: vec![0x33],
read_to_end: vec![0x01, 0x02, 0x03],
}
);
您可以在自己的类型上实现 Protocol
,并使用上下文进行解析
use bin_proto::{ProtocolRead, ProtocolWrite};
pub struct Ctx;
pub struct NeedsCtx;
impl ProtocolRead<Ctx> for NeedsCtx {
fn read(
_read: &mut dyn bin_proto::BitRead,
_byte_order: bin_proto::ByteOrder,
_ctx: &mut Ctx,
) -> bin_proto::Result<Self> {
// Use ctx here
Ok(Self)
}
}
impl ProtocolWrite<Ctx> for NeedsCtx {
fn write(
&self,
_write: &mut dyn bin_proto::BitWrite,
_byte_order: bin_proto::ByteOrder,
_ctx: &mut Ctx,
) -> bin_proto::Result<()> {
// Use ctx here
Ok(())
}
}
#[derive(ProtocolRead, ProtocolWrite)]
#[protocol(ctx = "Ctx")]
pub struct WithCtx(NeedsCtx);
WithCtx(NeedsCtx)
.bytes_ctx(bin_proto::ByteOrder::LittleEndian, &mut Ctx)
.unwrap();
性能 / 替代方案
此包的主要替代方案是 deku,以及用于字节级协议的 binrw。
bin-proto
几乎在所有测试场景中都比 deku
快得多。以下表格的单元是 ns
,来自 github CI。您可以在 bench
目录中找到基准测试。
读取 enum |
写入 enum |
读取 Vec |
写入 Vec |
读取 IPv4 头 | 写入 IPv4 头 | |
---|---|---|---|---|---|---|
bin-proto |
29 | 62 | 1,327 | 557 | 173 | 138 |
deku |
1 | 92 | 582 | 937 | 3,234 | 633 |
路线图
以下功能计划实现
- 位/字节对齐
no_std
支持(仅在bitstream_io
支持后)
依赖项
~0.4–0.9MB
~20K SLoC