3 个不稳定版本

使用旧的 Rust 2015

0.2.0 2016年6月6日
0.1.1 2016年5月31日
0.1.0 2016年5月29日

#2287解析器实现

Download history 182/week @ 2024-01-10 454/week @ 2024-01-17 156/week @ 2024-01-24 126/week @ 2024-01-31 186/week @ 2024-02-07 149/week @ 2024-02-14 126/week @ 2024-02-21 239/week @ 2024-02-28 189/week @ 2024-03-06 163/week @ 2024-03-13 200/week @ 2024-03-20 330/week @ 2024-03-27 312/week @ 2024-04-03 140/week @ 2024-04-10 162/week @ 2024-04-17 154/week @ 2024-04-24

813 每月下载量
9 仓库中(5 个直接使用)

Apache-2.0/MIT

52KB
790

bytevec: 使用字节向量的 Rust 序列化库

Build Status MIT licensed Apache 2.0 licensed

bytevec 利用 Rust 简洁且稳定的类型系统将数据对象序列化为字节向量 (Vec<u8>) 并返回。

请在此处阅读文档 http://fero23.github.io/doc/bytevec/.

它做什么?

Rust 有一个非常强大的类型系统,对于大多数类型(从原始类型开始)具有可预测的大小,因此将任何类型转换为字节序列并将其转换回相当容易。这个库旨在为用户提供将给定类型实例转换为字节向量的手段,并将其存储或通过网络发送到另一台设备,同时使用库特质随时从字节向量获取值。

当然,Rust 并非魔法般地能够自动实现序列化函数的特质,因为每种类型都有自己的特性。这个库使用两个特质来给类型提供执行该操作所需的功能:ByteEncodableByteDecodable

###ByteEncodable 特质 实现此特质类型的类型可以使用 encode 方法生成一个 Vec<u8> 字节序列。这似乎很容易出错,对吧?当然,它内部使用 unsafe 块来提取给定类型的字节,因此可能非常不安全。这就是为什么它总是检查任何可能的错误,并返回包装在 BVEncodeResult 实例中的向量。如果一切顺利,我们将能够获取表示原始数据结构的字节向量值。

bytevec 实际上并不将原始类型实例的字节进行 1:1 转换,因为并非所有 Rust 类型都存储在栈上。对于任何包含堆存储值的类型,它将给出底层值的表示。

bytevec 为以下类型实现了 ByteEncodable

  • 整数类型:u8u16u32u64i8i16i32i64
  • 浮点类型:f32f64
  • charstrString
  • Vec
  • &[T]
  • HashMap
  • HashSet
  • 最多包含12个元素的元组
  • 自定义struct

对于集合和其他结构,自动实现bytevec需要其所有底层元素实现ByteEncodable特质。

### bytevec序列化格式bytevec不遵循任何特定的序列化格式。在将某些类型值转换为字节时,它遵循简单的规则

  • 对于具有固定大小的原始类型,如整数类型、浮点数或char,它将直接抓取字节并将它们放在长度与类型大小相同的u8缓冲区中,通过std::mem::transmute实现。这些类型在序列化和反序列化时分别转换为和从小端。
  • String和str不存储它们的字节计数,字符串的容器(如果有)负责存储字符串的字节缓冲区大小。
  • 复杂的数据结构,如struct、元组和集合,需要存储其底层数据字段的大小。这些大小存储为泛型整数类型参数Size的值,应在每个调用ByteEncodableByteDecodable特质的方法的调用中提供。此类型参数传递给包含数据字段的序列化和反序列化操作。类型参数SizeBVSize特质的约束。目前实现此特质的类型有u8u16u32u64。用户应根据预期的字节缓冲区大小选择Size类型参数。如果预期大小超过了u32的232字节长度限制,则使用u64
  • 对于具有明确定义字段的架构,如自定义struct或元组,它将在结构切片段的开始处存储每个字段的大小为一个Size值序列,然后是字段的实际值字节。
  • 对于任何具有可变长度的集合,它将首先将长度(元素数量,而非字节计数)存储为一个Size值,然后是每个元素的字节计数(是的,是Size),然后是元素的实际值。所有这些都按顺序进行,顺序很重要,序列化的顺序就是反序列化的顺序。
  • 所有可序列化的值都可以嵌套,因此任何实现了 ByteEncodable 并包含 VecString 或其他也实现了 ByteEncodable 的结构的结构都将对其所有字段进行序列化。

### ByteDecodable 特性 给定从内存、文件或TCP连接检索的字节向量,用户可以将该向量传递给实现了 ByteDecodable 特性的类型的 decode 方法。decode 将对字节向量进行一些检查,如果所需的尺寸匹配,它将产生一个包裹在 BVDecodeResult 中的类型实例。如果尺寸不匹配,或者出现其他转换问题,它将产生一个详细说明失败的 ByteVecError

几乎所有 ByteEncodable 的开箱即用实现也实现了 ByteDecodable,但是其中一些,尤其是切片和元组引用在反序列化时没有意义,因为它们无法指向它们所引用的原始数据。这通常是一个需要调整的问题,但 bytevec 允许从原始引用数据到新实例的拥有的数据类型的数据转换,只要尺寸要求相同。这样,切片数据可以分配给 Vec 实例,例如,只要它们具有相同的底层元素类型。

ByteDecodable 特性还提供了一个 decode_max 方法,它类似于 decode,接受要反序列化的字节缓冲区,但此外,此方法还接受一个 limit 参数。该参数与 u8 缓冲区的长度进行比较,如果缓冲区长度大于它,它将返回一个 BadSizeDecodeError,否则它将返回对字节缓冲区的 decode 的结果。

### 示例:切片的序列化和反序列化

let slice = &["Rust", "Is", "Awesome!"];
let bytes = slice.encode::<u32>().unwrap();
let vec = <Vec<String>>::decode::<u32>(&bytes).unwrap();
assert_eq!(vec, slice);

### bytevec_decl 宏 此宏允许用户声明任意数量的结构,只要所有字段也实现了这两个特性,这些结构将自动实现 ByteEncodableByteDecodable 特性。

#[macro_use]
extern crate bytevec;

use bytevec::{ByteEncodable, ByteDecodable};

bytevec_decl! {
    #[derive(PartialEq, Eq, Debug)]
    pub struct Point {
        x: u32,
        y: u32
    }
}

fn main() {
    let p1 = Point {x: 32, y: 436};
    let bytes = p1.encode::<u32>().unwrap();
    let p2 = Point::decode::<u32>(&bytes).unwrap();
    assert_eq!(p1, p2);
}

### bytevec_impls

此宏为给定的 struct 定义实现了 ByteEncodableByteDecodable 特性。此宏不声明 struct 定义,用户应单独声明它们或使用 bytevec_decl 特性。

此特性还允许用户为结构的某些字段创建部分序列化操作的实现。如果 struct 的实际定义比传递给宏的更多字段,则只有宏调用中列出的字段将被序列化和反序列化。在反序列化过程中,struct 的其余字段将使用从 Default::default() 方法返回的值进行初始化,因此 struct 必须实现 Default

#[macro_use]
extern crate bytevec;

use bytevec::{ByteEncodable, ByteDecodable};

#[derive(PartialEq, Eq, Debug, Default)]
struct Vertex3d {
    x: u32,
    y: u32,
    z: u32
}

bytevec_impls! {
    impl Vertex3d {
        x: u32,
        y: u32
    }
}

fn main() {
    let p1 = Vertex3d {x: 32, y: 436, z: 0};
    let bytes = p1.encode::<u32>().unwrap();
    let p2 = Vertex3d::decode::<u32>(&bytes).unwrap();
    assert_eq!(p1, p2);
}

#### 这听起来就像你常用的序列化库,但为什么要处理字节呢?bytevec当然不是为每个人准备的。它不是一个完整的序列化库,如rustc_serializeserde,它也没有试图成为这样的库。这是为那些由于任何原因无法处理基于文本的序列化,只需要快速获取一些字节,并使用没有依赖的小型crate以低开销重新创建对象的人准备的。

## 许可证 本库同时受MIT许可证和Apache许可证(版本2.0)的约束。您可以根据自己的需要选择使用其中任何一个。

无运行时依赖