7个版本

0.8.14 2024年4月17日
0.8.12 2023年7月21日
0.8.11 2022年4月19日
0.8.10 2021年2月2日
0.4.0 2015年7月17日

#23 in 编码

Download history 285372/week @ 2024-04-26 257686/week @ 2024-05-03 285672/week @ 2024-05-10 285723/week @ 2024-05-17 303970/week @ 2024-05-24 391514/week @ 2024-05-31 419755/week @ 2024-06-07 356233/week @ 2024-06-14 428082/week @ 2024-06-21 405449/week @ 2024-06-28 405806/week @ 2024-07-05 390647/week @ 2024-07-12 404760/week @ 2024-07-19 417940/week @ 2024-07-26 412913/week @ 2024-08-02 371597/week @ 2024-08-09

1,676,316 每月下载量
1,552 个crate中(113个直接使用) 使用

MIT 许可证

92KB
1.5K SLoC

Rust MessagePack库

RMP是纯Rust实现的MessagePack高效二进制序列化格式。这个crate提供了低级核心功能,包括原始值的写入器和读取器,并且直接映射到二进制MessagePack格式。

寻找Serde支持?

这个crate代表了与MessagePack格式交互所需的基本功能。在理念上,它是作为构建高级抽象的基础而开发的。

用法

要使用rmp,首先将其添加到你的Cargo.toml

[dependencies.rmp]
rmp = "0.8"

功能

  • 低级API

    RMP设计得轻量级且简单直接。它提供了低级API,让你完全控制编码/解码过程。支持no-std环境。

  • 零拷贝值解码

    RMP允许以零拷贝方式从缓冲区中解码字节,无需任何堆分配。它简单且速度极快。Rust静态检查确保数据在缓冲区生存期间有效。

  • 清晰的错误处理

    RMP的错误系统保证你永远不会收到包含不可达变体的错误枚举。

  • 稳健且经过测试

    该项目使用TDD和CI进行开发,因此任何发现的错误都会得到修复而不会破坏现有功能。

详细

目前有两个大型模块:编码和解码。更多详细信息请查看相应的章节。

形式上,每个MessagePack消息都由一些封装数据类型的标记和实际数据本身组成。有时没有单独的数据块,例如布尔值。在这些情况下,标记包含值。例如,true值编码为0xc3

let mut buf = Vec::new();
rmp::encode::write_bool(&mut buf, true).unwrap();

assert_eq!([0xc3], buf[..]);

有时单个值可以以多种方式编码。例如,值42可以表示为:[0x2a], [0xcc, 0x2a], [0xcd, 0x00, 0x2a]等等,所有这些都被认为是有效的表示。为了允许对这种值的编码进行细粒度控制,库提供了直接映射函数。

let mut bufs = vec![vec![]; 5];

rmp::encode::write_pfix(&mut bufs[0], 42).unwrap();
rmp::encode::write_u8(&mut bufs[1], 42).unwrap();
rmp::encode::write_u16(&mut bufs[2], 42).unwrap();
rmp::encode::write_u32(&mut bufs[3], 42).unwrap();
rmp::encode::write_u64(&mut bufs[4], 42).unwrap();

assert_eq!([0x2a], bufs[0][..]);
assert_eq!([0xcc, 0x2a], bufs[1][..]);
assert_eq!([0xcd, 0x00, 0x2a], bufs[2][..]);
assert_eq!([0xce, 0x00, 0x00, 0x00, 0x2a], bufs[3][..]);
assert_eq!([0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a], bufs[4][..]);

但它们并不打算被广泛使用。相反,我们经常需要将字节紧凑地编码以节省空间。在这些情况下,RMP提供了保证选择最紧凑表示的函数。

let mut buf = Vec::new();

rmp::encode::write_sint(&mut buf, 300).unwrap();

assert_eq!([0xcd, 0x1, 0x2c], buf[..]);

另一方面,对于反序列化,值编码的表示方式并不重要——RMP处理所有这些表示。

有时你已知确切的类型表示,并希望强制执行反序列化过程以使其强类型安全。

let buf = [0xcd, 0x1, 0x2c];

assert_eq!(300, rmp::decode::read_u16(&mut &buf[..]).unwrap());

然而,如果你尝试将这样的bytearray解码为其他整数类型,例如u32,将会出现类型不匹配错误。

let buf = [0xcd, 0x1, 0x2c];
rmp::decode::read_u32(&mut &buf[..]).err().unwrap();

但有时你只是想要编码一个整数,它必须适合指定的类型,无论它是如何编码的。RMP提供了such函数,以简化与其他MessagePack库的集成。

let buf = [0xcd, 0x1, 0x2c];

assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap());
assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap());
assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap());
assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap());
assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap());
assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap());

API

几乎所有的API都是以纯函数的形式表示的,它接受一个泛型WriteRead以及要编码/解码的值。例如,让我们对π数字做一个往返。

let pi = std::f64::consts::PI;
let mut buf = Vec::new();
rmp::encode::write_f64(&mut buf, pi).unwrap();

assert_eq!([0xcb, 0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], buf[..]);
assert_eq!(pi, rmp::decode::read_f64(&mut &buf[..]).unwrap());

许可:MIT

依赖项

~175–270KB