#encode-decode #binary-encoding #decode #encode #binary #deserialize #serialization

no-std bincode

一种将结构体转换为字节并进行相反转换的二进制序列化/反序列化策略!

61个版本 (11个稳定版)

2.0.0-rc.32023年3月30日
2.0.0-rc.22022年10月4日
2.0.0-rc.12022年3月4日
2.0.0-alpha.22021年12月14日
0.0.2 2014年11月24日

#2 in 编码

Download history 687706/week @ 2024-04-10 707052/week @ 2024-04-17 707778/week @ 2024-04-24 671482/week @ 2024-05-01 672508/week @ 2024-05-08 727654/week @ 2024-05-15 719242/week @ 2024-05-22 794656/week @ 2024-05-29 806017/week @ 2024-06-05 815672/week @ 2024-06-12 780025/week @ 2024-06-19 814202/week @ 2024-06-26 745677/week @ 2024-07-03 811380/week @ 2024-07-10 812868/week @ 2024-07-17 700527/week @ 2024-07-24

3,221,227 每月下载量
7,181 个crate中使用 (2,858 直接使用)

MIT 许可证

260KB
6K SLoC

Bincode

CI

Matrix

一个紧凑的编码/解码器对,使用二进制零填充编码方案。编码对象的尺寸将与在运行中的Rust程序中该对象占用的内存大小相同或更小。

除了暴露两个简单的函数(一个编码到 Vec<u8>,另一个从 &[u8] 解码)之外,二进制编码还提供了一个Reader/Writer API,使其能够与Rust文件、网络流和 flate2-rs 压缩库等基于流的API完美配合。

API文档

野外的Bincode

  • google/tarpc: Bincode用于序列化和反序列化网络RPC消息。
  • servo/webrender: Bincode用于记录WebRender API调用,以便进行记录/回放式的图形调试。
  • servo/ipc-channel: IPC-Channel使用Bincode通过类似通道的API在进程之间发送结构体。
  • ajeetdsouza/zoxide: zoxide使用Bincode将目录数据库及其访问频率存储在磁盘上。

示例

use bincode::{config, Decode, Encode};

#[derive(Encode, Decode, PartialEq, Debug)]
struct Entity {
    x: f32,
    y: f32,
}

#[derive(Encode, Decode, PartialEq, Debug)]
struct World(Vec<Entity>);

fn main() {
    let config = config::standard();

    let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);

    let encoded: Vec<u8> = bincode::encode_to_vec(&world, config).unwrap();

    // The length of the vector is encoded as a varint u64, which in this case gets collapsed to a single byte
    // See the documentation on varint for more info for that.
    // The 4 floats are encoded in 4 bytes each.
    assert_eq!(encoded.len(), 1 + 4 * 4);

    let (decoded, len): (World, usize) = bincode::decode_from_slice(&encoded[..], config).unwrap();

    assert_eq!(world, decoded);
    assert_eq!(len, encoded.len()); // read all bytes
}

规范

Bincode的格式在 docs/spec.md 中指定。

常见问题解答

Bincode是否适合存储?

编码格式是稳定的,只要使用相同的配置。这应该可以保证,如果未发生重大版本变更,则后续版本仍能读取由先前版本库产生的数据。

如果使用相同的配置,Bincode 1 和 2 完全兼容。

Bincode 对字节序是无关的,这使得在不同架构之间进行交换成为可能。它也非常节省空间,因为它在输出格式中不存储元数据(如结构体字段名称),并且写入长二进制数据流时不需要任何可能增加大小的编码。

因此,Bincode 适用于存储数据。请注意,它不实现任何数据版本控制方案或文件头,因为这些功能超出了本crate的范畴。

Bincode 是否适合不信任的输入?

Bincode 尝试保护免受恶意数据的影响。有一个最大大小配置可用(Configuration::with_limit),但在默认配置中未启用。启用它将导致预分配大小限制在内存耗尽攻击的防护范围内。

假设结构体的反序列化代码本身是安全的,反序列化任何传入的数据不会导致未定义的行为或内存问题。

在配置更改以启用最大大小限制的情况下,Bincode 可以用于不信任的输入,这样它就不会在您的应用程序中创建安全问题。恶意输入在反序列化时会失败。

Bincode 的 MSRV(最低支持的 Rust 版本)是什么?

Bincode 2.0 仍在开发中,目前还没有一个目标 MSRV。一旦 2.0 完全发布,MSRV 将被锁定。在此之后,任何对 MSRV 的更改都视为 semver 目的下的破坏性更改。

为什么 bincode 不遵守 #[repr(u8)]

Bincode 将枚举变体编码为 u32。如果您担心存储大小,我们可以建议启用 Configuration::with_variable_int_encoding()。此选项默认与 standard 配置一起启用。在这种情况下,枚举变体几乎总是编码为 u8

目前我们没有发现尊重 #[repr(...)] 的令人信服的理由。您最可能是在尝试与类似但不完全相同的 bincode 格式进行互操作。我们只支持我们自己的协议(规范)。

如果您确实想使用 bincode 来编码/解码不同的协议,请考虑自己实现 EncodeDecodebincode-derive 将生成的实现输出到 target/generated/bincode/<name>_Encode.rstarget/generated/bincode/<name>_Decode.rs,这应该能帮助您入门。

依赖项

~200KB