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用于解码。它们分别抽象了WriteRead

这些特质已经为一些基本类型以及与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_structsPoint2DNode

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);

提供一种求和类型

用户定义的结构体通常在枚举中求和,该枚举表示协议应能够编码和解码的所有可能结构。可以通过为枚举派生PackUnpack来实现。不同变体上的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