13 个版本 (6 个重大变更)
7.1.0 | 2022 年 10 月 2 日 |
---|---|
6.0.0 | 2022 年 7 月 29 日 |
5.1.0 | 2022 年 4 月 15 日 |
4.0.1 |
|
0.2.0 | 2022 年 3 月 9 日 |
#1386 在 编码
每月 28 次下载
35KB
781 行
非常快!而且灵活,该库用于二进制格式中数据的序列化和反序列化。
字节序
默认情况下,库使用小端字节序。如果您想使用大端字节序,可以设置 BE
特性标志。对于本地字节序,使用 NE
。例如
[dependencies]
bin-layout = { version = "7", features = ["BE"] }
示例
use bin_layout::*;
#[derive(Encoder, Decoder)]
struct Car<'a> {
year: u16,
is_new: bool,
name: &'a str,
}
#[derive(Encoder, Decoder)]
struct Company<'a> { name: String, cars: Vec<Car<'a>> }
let old = Company {
name: "Tesla".into(),
cars: vec![
Car { name: "Model S", year: 2018, is_new: true },
Car { name: "Model X", year: 2019, is_new: false },
],
};
let bytes = old.encode();
let new = Company::decode(&bytes);
- 零拷贝反序列化:意味着没有数据被复制。动态长度数据(
Vec
,String
,&[T]
,&str
等)首先编码它们的长度值,然后编码每个条目。
use bin_layout::*;
#[derive(Encoder, Decoder)]
struct Msg<'a> {
id: u8,
data: &'a str,
}
let bytes = [42, 13, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33];
// ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Id Len Data
let msg = Msg::decode(&bytes).unwrap();
assert_eq!(msg.id, 42);
assert_eq!(msg.data, "Hello, World!"); // Here, data is referenced.
- 在这个示例中,以下结构体不包含任何动态长度数据。因此,我们可以在编译时有一个固定大小的缓冲区。
use bin_layout::*;
#[derive(Encoder, Decoder)]
struct Date {
year: u16,
month: u8,
day: u8,
}
#[derive(Encoder, Decoder)]
struct Record {
id: u32,
date: Date,
value: [u8; 512],
}
let record = Record { id: 42, date: Date { year: 2018, month: 3, day: 7 }, value: [1; 512] };
let mut writer = [0; 520];
record.encoder(&mut writer.as_mut_slice());
- 实现
Encoder
或Decoder
特征非常简单。例如
use std::io;
use bin_layout::*;
type DynErr = Box<dyn std::error::Error + Send + Sync>;
#[derive(Encoder, Decoder)]
struct Bar(u16);
struct Foo { x: u8, y: Bar }
impl Encoder for Foo {
fn encoder(&self, c: &mut impl io::Write) -> io::Result<()> {
self.x.encoder(c)?;
self.y.encoder(c)
}
}
impl Decoder<'_> for Foo {
fn decoder(c: &mut &[u8]) -> Result<Self, DynErr> {
Ok(Self {
x: u8::decoder(c)?,
y: Bar::decoder(c)?,
})
}
}
可变长度整数编码
此编码确保较小的整数值需要较少的字节进行编码。支持类型为 L2
和 L3
,两者都使用小端字节序进行编码。
默认情况下,使用 L3
(u22)来编码记录的长度(整数)。但您可以通过在特性标志中设置 L2
(u15)来覆盖它。
编码算法非常简单,保留第一个字节的一个或两个最高有效位来编码剩余的长度。
L2
MSB | 长度 | 可用位 | 范围 |
---|---|---|---|
0 | 1 | 7 | 0..128 |
1 | 2 | 15 | 0..32768 |
L3
MSB | 长度 | 可用位 | 范围 |
---|---|---|---|
0 | 1 | 7 | 0..128 |
10 | 2 | 14 | 0..16384 |
11 | 3 | 22 | 0..4194304 |
例如,0x_C0DE
的二进制表示为 0x_11_00000011_011110
L3(0x_C0DE)
编码为 3 个字节
1st byte: 11_011110 # MSB is 11, so read next 2 bytes
2nd byte: 11
3rd byte: 11
另一个示例,L3(107)
仅占用 1 个字节进行编码
1st byte: 0_1101011 # MSB is 0, So we don't have to read extra bytes.
固定长度集合
Record 可以用来编码长度大小已知的集合。
例如,Record<u8, String>
这里最大允许的有效负载长度为 255 (u8::MAX
)
依赖项
~1.5MB
~35K SLoC