3 个不稳定版本
使用旧的 Rust 2015
0.2.0 | 2016年6月6日 |
---|---|
0.1.1 | 2016年5月31日 |
0.1.0 | 2016年5月29日 |
#2287 在 解析器实现 中
813 每月下载量
在 9 个 仓库中(5 个直接使用)
52KB
790 行
bytevec: 使用字节向量的 Rust 序列化库
bytevec 利用 Rust 简洁且稳定的类型系统将数据对象序列化为字节向量 (Vec<u8>
) 并返回。
请在此处阅读文档 http://fero23.github.io/doc/bytevec/.
它做什么?
Rust 有一个非常强大的类型系统,对于大多数类型(从原始类型开始)具有可预测的大小,因此将任何类型转换为字节序列并将其转换回相当容易。这个库旨在为用户提供将给定类型实例转换为字节向量的手段,并将其存储或通过网络发送到另一台设备,同时使用库特质随时从字节向量获取值。
当然,Rust 并非魔法般地能够自动实现序列化函数的特质,因为每种类型都有自己的特性。这个库使用两个特质来给类型提供执行该操作所需的功能:ByteEncodable
和 ByteDecodable
。
###ByteEncodable
特质 实现此特质类型的类型可以使用 encode
方法生成一个 Vec<u8>
字节序列。这似乎很容易出错,对吧?当然,它内部使用 unsafe
块来提取给定类型的字节,因此可能非常不安全。这就是为什么它总是检查任何可能的错误,并返回包装在 BVEncodeResult
实例中的向量。如果一切顺利,我们将能够获取表示原始数据结构的字节向量值。
bytevec 实际上并不将原始类型实例的字节进行 1:1 转换,因为并非所有 Rust 类型都存储在栈上。对于任何包含堆存储值的类型,它将给出底层值的表示。
bytevec 为以下类型实现了 ByteEncodable
- 整数类型:
u8
、u16
、u32
、u64
、i8
、i16
、i32
、i64
- 浮点类型:
f32
和f64
char
、str
和String
Vec
&[T]
HashMap
HashSet
- 最多包含12个元素的元组
- 自定义
struct
对于集合和其他结构,自动实现bytevec需要其所有底层元素实现ByteEncodable
特质。
### bytevec序列化格式bytevec不遵循任何特定的序列化格式。在将某些类型值转换为字节时,它遵循简单的规则
- 对于具有固定大小的原始类型,如整数类型、浮点数或char,它将直接抓取字节并将它们放在长度与类型大小相同的
u8
缓冲区中,通过std::mem::transmute
实现。这些类型在序列化和反序列化时分别转换为和从小端。 - String和str不存储它们的字节计数,字符串的容器(如果有)负责存储字符串的字节缓冲区大小。
- 复杂的数据结构,如
struct
、元组和集合,需要存储其底层数据字段的大小。这些大小存储为泛型整数类型参数Size
的值,应在每个调用ByteEncodable
和ByteDecodable
特质的方法的调用中提供。此类型参数传递给包含数据字段的序列化和反序列化操作。类型参数Size
受BVSize
特质的约束。目前实现此特质的类型有u8
、u16
、u32
和u64
。用户应根据预期的字节缓冲区大小选择Size
类型参数。如果预期大小超过了u32
的232字节长度限制,则使用u64
。 - 对于具有明确定义字段的架构,如自定义
struct
或元组,它将在结构切片段的开始处存储每个字段的大小为一个Size
值序列,然后是字段的实际值字节。 - 对于任何具有可变长度的集合,它将首先将长度(元素数量,而非字节计数)存储为一个
Size
值,然后是每个元素的字节计数(是的,是Size
),然后是元素的实际值。所有这些都按顺序进行,顺序很重要,序列化的顺序就是反序列化的顺序。 - 所有可序列化的值都可以嵌套,因此任何实现了
ByteEncodable
并包含Vec
、String
或其他也实现了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
宏 此宏允许用户声明任意数量的结构,只要所有字段也实现了这两个特性,这些结构将自动实现 ByteEncodable
和 ByteDecodable
特性。
#[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
定义实现了 ByteEncodable
和 ByteDecodable
特性。此宏不声明 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_serialize或serde,它也没有试图成为这样的库。这是为那些由于任何原因无法处理基于文本的序列化,只需要快速获取一些字节,并使用没有依赖的小型crate以低开销重新创建对象的人准备的。
## 许可证 本库同时受MIT许可证和Apache许可证(版本2.0)的约束。您可以根据自己的需要选择使用其中任何一个。