2个不稳定版本
0.2.0 | 2020年11月21日 |
---|---|
0.1.0 | 2020年10月12日 |
#1253 in 编码
用于 raio
85KB
2K SLoC
packs
这是packs
项目的库。
packs
是用Rust编写的PackStream实现。有关更多信息,请参阅项目的github 页面。
lib.rs
:
用Rust编写的PackStream实现。
API
特质Pack
用于编码,特质Unpack
用于解码。它们分别抽象了Write
和Read
。
这些特质已经为一些基本类型以及与PackStream规范一起提供的标准集合结构实现,请参阅std_structs
模块。
use packs::{Pack, Unpack};
use packs::std_structs::Node;
let mut node = Node::new(42);
node.properties.add_property("title", "A Book's Title");
node.properties.add_property("pages", 302);
// encode `node` into a `Vec<u8>`:
let mut buffer = Vec::new();
node.encode(&mut buffer).unwrap();
// and recover it from these bytes:
let recovered = Node::decode(&mut buffer.as_slice()).unwrap();
assert_eq!(node, recovered);
用户自定义结构体
结构体可以用几种方式编码和解码,遵循PackStream规范。指定一个#[tag = u8]
属性将结构体解释为带有提供标签字节的Structure及其字段作为结构的字段。即它将被处理为来自std_structs
的Point2D
或Node
。
use packs::*;
#[derive(Debug, PartialEq, Pack, Unpack)]
#[tag = 0x0B]
struct Book {
pub title: String,
pub pages: i64,
}
// this is not packed as a `Node`. It is a genuinely user defined struct,
// it will differ in its byte structure to the `Node` above.
let book = Book { title: String::from("A Book's title"), pages: 302 };
let mut buffer = Vec::new();
book.encode(&mut buffer).unwrap();
let recovered = Book::decode(&mut buffer.as_slice()).unwrap();
assert_eq!(book, recovered);
提供一种求和类型
用户定义的结构体通常在枚举中求和,该枚举表示协议应能够编码和解码的所有可能结构。可以通过为枚举派生Pack
和Unpack
来实现。不同变体上的tag
属性不是可选的,但可以与提供给结构的tag
属性不同。
use packs::*;
#[derive(Debug, PartialEq, Pack, Unpack)]
#[tag = 0x0B]
struct Book {
pub title: String,
pub pages: i64,
}
#[derive(Debug, PartialEq, Pack, Unpack)]
#[tag = 0x0C]
struct Person {
pub name: String,
}
#[derive(Debug, PartialEq, Pack, Unpack)]
enum MyStruct {
#[tag = 0x0B]
Book(Book),
#[tag = 0x0C]
Person(Person),
}
let person = Person { name: String::from("Check Mate") };
let mut buffer = Vec::new();
person.encode(&mut buffer).unwrap();
// recover via `MyStruct`:
let my_struct = MyStruct::decode(&mut buffer.as_slice()).unwrap();
assert_eq!(MyStruct::Person(person), my_struct);
标签一致性
在枚举变体及其对应的结构体中可能存在不同的标签,有时这很有用,可以在不同的设置中使用相同的结构体。但如果编码和解码不遵循相同的路径,可能会导致不一致。例如,使用其Pack
实现编码结构体,然后使用具有不同标签的Unpack
实现解码,将不会正常工作。
运行时类型值
除了直接使用类型外,值还可以通过求和类型 Value
进行编码和解码,这使得可以在不知道其类型的情况下解码任何值。
use packs::{Value, Unpack, Pack, NoStruct};
use packs::std_structs::StdStruct;
let mut buffer = Vec::new();
42i64.encode(&mut buffer).unwrap();
let value = <Value<NoStruct>>::decode(&mut buffer.as_slice()).unwrap();
assert_eq!(Value::Integer(42), value);
类型 Value
抽象了可能的结构。可以使用 NoStruct
来拒绝任何结构,或者使用 Value<StdStruct>
(c.f. StdStruct
) 来允许任何标准结构作为 Value
的部分。
在上面的例子中,也可以使用 Value<MyStruct>
let mut buffer = Vec::new();
let person = Person { name: String::from("Check Mate") };
person
.encode(&mut buffer)
.unwrap();
let runtime_typed = <Value<MyStruct>>::decode(&mut buffer.as_slice()).unwrap();
assert_eq!(Value::Structure(MyStruct::Person(person)), runtime_typed);
依赖关系
~305–770KB
~18K SLoC