3个稳定版本
1.0.2 | 2020年8月16日 |
---|---|
1.0.1 | 2020年8月10日 |
1.0.0 | 2020年8月9日 |
在解析实现中排名1883
175KB
6K SLoC
fastxdr
将XDR规范转换为Rust代码。
- 生成具有快速、零拷贝反序列化的Rust类型
- 为生成的类型自定义derives
- 不会引发panic - 对于格式不正确的数据返回生成的
Error
变体 - 作为
build.rs
的一部分使用,或者使用独立的二进制文件生成 - 将XDR联合映射到Rust枚举1-to-1以方便使用
- XDR typedefs生成不同的Rust类型(不是类型别名)
- 符合
rfc1014
/rfc1832
/rfc4506
包含opaque
字节的类型是针对AsRef<[u8]>
实现泛型的,并且所有类型都实现了TryFrom<Bytes>
,以实现惯用的、零拷贝反序列化(见Bytes
)。
速度
反序列化线协议非常快,通常在1微秒以下。
下面的示例是从生产网络捕获的NFS消息,具有协议的典型大小和复杂性
setclientid time: [719.93 ns 724.15 ns 728.76 ns]
mount time: [661.15 ns 663.54 ns 665.85 ns]
lookup time: [819.69 ns 823.80 ns 828.04 ns]
通过避免完全复制不透明字节的需求,即使是包含大量数据的XDR消息,在现代CPU上通常在1us或更少的时间内以O(n)时间和空间反序列化。
库功能
此crate可以用作库来实现自定义代码生成,或构建XDR linters等。
该库使用Pest crate对XDR规范进行分词,构建抽象语法树,索引和解析类型别名和常量,并生成代码来计算XDR序列化类型的链路大小——此信息通过index
和ast
模块暴露给用户。
用法
生成的代码有依赖项,必须添加到您的Cargo.toml
[dependencies]
thiserror = "1.0"
bytes = "0.5"
然后,要么在构建脚本中生成代码(首选),要么手动使用CLI。
要查看生成的类型,您可以在应用程序中导出生成的类型并使用cargo doc
,或者使用CLI直接生成可读的生成代码。
构建脚本
要将它作为build.rs
构建脚本的一部分使用,首先将fastxdr
添加到构建依赖项中
[build-dependencies]
fastxdr = "1.0"
然后在crate根目录下创建一个build.rs
文件(不在src
目录中)
fn main() {
// Tell Cargo to regenerate the types if the XDR spec changes
println!("cargo:rerun-if-changed=src/xdr_spec.x");
// Read from xdr_spec.x, writing the generated code to out.rs
std::fs::write(
std::path::Path::new(std::env::var("OUT_DIR").unwrap().as_str()).join("out.rs"),
fastxdr::Generator::default()
.generate(include_str!("src/xdr_spec.x"))
.unwrap(),
)
.unwrap();
}
并在您的应用程序中包含生成的内容
// Where out.rs is the filename from above
include!(concat!(env!("OUT_DIR"), "/out.rs"));
use xdr::*;
生成的内容位于名为xdr
的模块中,如果需要,您可以将其重新导出。
CLI
您也可以使用CLI生成代码
cargo install fastxdr
fastxdr ./path/to/spec.x > generated.rs
如果规范被修改但代码未重新生成,或者规范未提交到源代码控制,这可能会造成混淆,通常使用build.rs
脚本是最好的选择。
孤儿规则
由于孤儿规则,无法为定义在生成代码之外的类型实现TryFrom
,例如u32
等。这通常是正常的,除了相对不常见的包含原始类型的可变长度数组类型定义。
因此,任何对原始类型数组的类型定义都必须稍作修改——这不是一个破坏性更改,也不会影响序列化的网络格式
typedef uint32_t bitmap4<>;
由于孤儿规则阻止向u32
类型定义添加TryFrom
实现,因此请将其包裹在类型定义中以生成新类型
typedef uint32_t bitmap_inner;
typedef bitmap_inner bitmap4<>;
现在数组包含了一个可以为其实现TryFrom
的bitmap_inner
类型。
依赖项
~3MB
~62K SLoC