#byte #serialization #quick #concise #serde-json #language #dbor

serde_dbor

为 Rust 设计的快速简洁的序列化语言

3 个稳定版本

使用旧的 Rust 2015

1.0.2 2018 年 6 月 8 日
1.0.1 2018 年 6 月 7 日
1.0.0 2018 年 3 月 6 日

#17 in #concise

MIT 许可证

90KB
2K SLoC

DBOR - Dq 的二进制对象表示

DBOR 是一种基于 CBOR 的序列化格式,专为 Rust 设计,并针对速度和文件大小进行了优化。它与 io 流交互时使用缓冲读取和写入系统,以实现最大效率。

示例用法

(来自 serde_json 的教程)

Cargo.toml

[dependencies]
serde = "*"
serde_derive = "*"
serde_dbor = "*"

main.rs

extern crate serde;
extern crate serde_dbor;

#[macro_use]
extern crate serde_derive;

use serde_dbor::Error;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>
}

fn example<'a>(data: &'a [u8]) => Result<(), Error> {
    // Parse the data into a Person object.
    let p: Person = serde_dbor::from_slice(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

规范

DBOR 与 CBOR 类似,由指令字节和附加内容字节组成。然而,在 DBOR 中,每个项目的内容之前都需要进行描述,这意味着不允许不定长数组、字符串或映射,因为它们需要在项目末尾有终止字节。指令字节分为两个部分,分别为 3 位和 5 位。前 3 位定义了项目的类型,最后 5 位是该项的参数,在某些情况下可以是该项的值。例如,值为 21 的无符号整数存储为 0x15,或 0b000 10101,因为类型 0 (0b000) 是 uint,该字节有足够的空间来编码数字 21 (0b10101)。

当指令字节指示参数为一定大小时 n,则下一个 n 个字节将被用于该参数,之后将是指令字节描述的项目的内容。例如,一个 u16 参数占用指令字节后的两个字节。然而,在序列化一个 u16 时,它可能被缩短为一个 u8 或指令字节本身。还应注意,DBOR 以小端格式存储多字节整数和浮点数,因为它使大多数机器上的序列化/反序列化速度更快(x86 使用小端)。

指令字节

类型 ID 编码类型 参数描述
0b000 (0) uint
  • 0-23 - 值 0-23
  • 24 - u8
  • 25 - u16
  • 26 - u32
  • 27 - u64
  • 28-31 - 保留
0b001 (1) 整型
  • 0-15 - 值 0-15
  • 16-23 - 值 -8--1
  • 24 - i8
  • 25 - i16
  • 26 - i32
  • 27 - i64
  • 28-31 - 保留
0b010 (2) 其他
  • 0 - false
  • 1 - true
  • 2 - ()
  • 3 - None
  • 4 - f32
  • 5 - f64
  • 6-31 - 保留
0b011 (3) 变体(枚举)
  • 0-23 - 变体 ID 0-23
  • 24 - 变体 ID 作为 u8
  • 25 - 变体 ID 作为 u16
  • 26 - 变体 ID 作为 u32
  • 27 - 命名变体(见下文)
  • 28-31 - 保留
0b100 (4) 序列(数组/元组/结构体)
  • 0-23 - 长度为 0-23
  • 24 - 长度作为 u8
  • 25 - 长度作为 u16
  • 26 - 长度作为 u32
  • 27 - 长度作为 u64(仅在64位机器上)
  • 28-31 - 保留
0b101 (5) 字节(字符串/字节数组)
  • 0-23 - 长度为 0-23
  • 24 - 长度作为 u8
  • 25 - 长度作为 u16
  • 26 - 长度作为 u32
  • 27 - 长度作为 u64(仅在64位机器上)
  • 28-31 - 保留
0b110 (6) 映射
  • 0-23 - 长度为 0-23
  • 24 - 长度作为 u8
  • 25 - 长度作为 u16
  • 26 - 长度作为 u32
  • 27 - 长度作为 u64(仅在64位机器上)
  • 28-31 - 保留
0b111 (7) 保留
  • 0-31 - 保留

命名变体字节

  • 0-247 - 0-247 的名称长度
  • 248 - 名称长度作为 u8
  • 249 - 名称长度作为 u16
  • 250 - 名称长度作为 u32
  • 251 - 名称长度作为 u64(仅在64位机器上)
  • 252-255 - 保留

注意:目前尚未实现使用命名变体的序列化,但已实现反序列化。

示例数据

Rust 代码

struct Data {
    some_text: String,
    a_small_number: u64,
    a_byte: u8,
    some_important_numbers: Vec<u16>,
}

let data = Data {
    some_text: "Hello world!",
    a_small_number: 0x04,
    a_byte: 0x27,
    some_important_numbers: vec![
        0x1234,
        0x6789,
        0xabcd,
    ]
}

DBOR的注释十六进制转储

84                    # Seq(4)
  ac                    # Bytes(12)
    48 65 6c 6c 6f 20...
    77 6f 72 6c 64 21     # "Hello world!"
  04                    # uint(4)
  18                    # u8
    27                    # 0x27
  83                    # Seq(3)
    19                    # u16
      34 12                 # 0x1234
    19                    # u16
      89 67                 # 0x6789
    19                    # u16
      cd ab                 # 0xabcd

依赖关系

~115–360KB