Rust严格编码库strict_encoding的使用,高效实现二进制数据的严格序列化与反序列化
Rust严格编码库strict_encoding的使用,高效实现二进制数据的严格序列化与反序列化
严格编码库(Strict encoding library)
用于客户端验证的确定性二进制序列化。
这个库实现了由LNPBP-7定义的严格编码标准。严格编码是一种二进制保守编码,广泛用于客户端验证,用于具有已知内部数据结构的确定性便携(平台无关)数据序列化。严格编码是一种无模式的编码。
作为严格编码的一部分,该库还包括网络地址统一编码标准(LNPBP-42)的实现,它允许将任何类型的网络地址表示为固定大小的字节字符串,占用37字节。该标准用于网络地址的严格编码。
使用
要使用该库,只需在项目Cargo.toml的[dependencies]部分引用最新版本。
strict_encoding = "2.5"
库定义了两个主要特性,StrictEncode
和StrictDecode
,它们应该在每个需要为客户端验证表示的类型上实现。
库导出了派生宏#[derive(StrictEncode, StrictDecode)]
,它们是strict_encoding_derive
子库的一部分,并由默认特性derive
控制。
示例代码
下面是一个完整的示例,展示如何使用strict_encoding进行二进制数据的严格序列化和反序列化:
use strict_encoding::{StrictEncode, StrictDecode};
// 定义一个需要序列化的结构体
#[derive(StrictEncode, StrictDecode, Debug, PartialEq)]
struct MyStruct {
id: u32,
name: String,
active: bool,
}
fn main() {
// 创建一个实例
let original = MyStruct {
id: 42,
name: "Test".to_string(),
active: true,
};
// 序列化为二进制数据
let encoded = original.strict_encode().expect("Encoding failed");
// 反序列化回结构体
let decoded = MyStruct::strict_decode(&encoded).expect("Decoding failed");
// 验证数据一致
assert_eq!(original, decoded);
println!("Successfully encoded and decoded: {:?}", decoded);
}
完整示例demo
下面是一个更完整的示例,展示如何使用strict_encoding处理复杂数据结构:
use strict_encoding::{StrictEncode, StrictDecode};
use std::collections::HashMap;
// 定义包含多种数据类型的结构体
#[derive(StrictEncode, StrictDecode, Debug, PartialEq)]
struct ComplexData {
id: u64,
tags: Vec<String>,
metadata: HashMap<String, String>,
is_verified: bool,
version: (u8, u8),
}
fn main() {
// 创建复杂数据结构实例
let mut metadata = HashMap::new();
metadata.insert("author".to_string(), "Alice".to_string());
metadata.insert("license".to_string(), "MIT".to_string());
let original = ComplexData {
id: 123456789,
tags: vec!["rust".to_string(), "serialization".to_string()],
metadata,
is_verified: true,
version: (1, 0),
};
// 序列化为二进制数据
let encoded = original.strict_encode().expect("Encoding failed");
println!("Encoded data length: {} bytes", encoded.len());
// 反序列化回结构体
let decoded = ComplexData::strict_decode(&encoded).expect("Decoding failed");
// 验证数据一致
assert_eq!(original, decoded);
println!("Successfully decoded: {:?}", decoded);
// 输出反序列化的数据
println!("ID: {}", decoded.id);
println!("Tags: {:?}", decoded.tags);
println!("Metadata:");
for (key, value) in &decoded.metadata {
println!(" {}: {}", key, value);
}
println!("Verified: {}", decoded.is_verified);
println!("Version: {}.{}", decoded.version.0, decoded.version.1);
}
特性控制
库实现了严格编码特性,用于rust标准库和常用crate定义的主要数据类型;后者会增加依赖项数量,因此可以用特性标志控制:
chrono
(默认使用):来自chrono
crate的日期和时间类型miniscript
:比特币Miniscript中定义的类型crypto
:非比特币加密原语,包括Ed25519曲线、来自ed25519-dalek
库的X25519签名以及来自grin_secp256k1zkp
库的pedersen承诺+bulletproofs
这个crate需要bitcoin
作为上游依赖,因为许多严格编码的格式被标准化为使用比特币共识编码。
贡献
贡献指南可以在CONTRIBUTING文件中找到。
许可
该库在Apache 2.0开源许可下分发。有关许可详细信息,请参阅LICENCE文件。
Rust严格编码库strict_encoding的使用指南
简介
strict_encoding
是一个Rust库,专注于二进制数据的严格序列化与反序列化。它提供了一种类型安全、高效的方式来处理二进制数据,特别适合需要精确控制数据布局的场景,如网络协议、文件格式和区块链应用。
主要特性
- 严格的二进制编码规则
- 零拷贝反序列化支持
- 类型安全的序列化接口
- 可组合的编码策略
- 支持derive宏简化实现
安装
在Cargo.toml中添加依赖:
[dependencies]
strict_encoding = "1.0"
基本使用方法
1. 为结构体实现严格编码
use strict_encoding::{StrictEncode, StrictDecode};
#[derive(StrictEncode, StrictDecode)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 10, y: 20 };
// 序列化为字节向量
let bytes = point.strict_serialize().unwrap();
// 反序列化
let decoded = Point::strict_deserialize(&bytes).unwrap();
assert_eq!(point.x, decoded.x);
assert_eq!(point.y, decoded.y);
}
2. 处理枚举类型
use strict_encoding::{StrictEncode, StrictDecode};
#[derive(StrictEncode, StrictDecode)]
enum Shape {
Circle { radius: f32 },
Rectangle { width: f32, height: f32 },
}
fn main() {
let circle = Shape::Circle { radius: 5.0 };
let bytes = circle.strict_serialize().unwrap();
let decoded = Shape::strict_deserialize(&bytes).unwrap();
if let Shape::Circle { radius } = decoded {
assert_eq!(radius, 5.0);
}
}
3. 自定义编码行为
use strict_encoding::{
StrictEncode, StrictDecode, StrictType, StrictDumb
};
#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
#[strict_type(lib = "my_lib")]
struct CustomData {
#[strict_type(rename = "identifier")]
id: u64,
#[strict_type(skip)]
metadata: String, // 这个字段不会被编码
}
高级用法
1. 流式处理
use strict_encoding::{StrictWriter, StrictReader};
let mut writer = StrictWriter::new(vec![]);
writer.write_u8(0x42).unwrap();
writer.write_u16(0x1234).unwrap();
let data = writer.finalize();
let mut reader = StrictReader::new(&data[..]);
assert_eq!(reader.read_u8().unwrap(), 0x42);
assert_eq!(reader.read_u16().unwrap(), 0x1234);
2. 网络协议实现示例
use strict_encoding::{StrictEncode, StrictDecode};
#[derive(StrictEncode, StrictDecode)]
enum NetworkMessage {
Ping,
Pong,
Data(Vec<u8>),
Error { code: u16, message: String },
}
fn handle_message(data: &[u8]) {
match NetworkMessage::strict_deserialize(data) {
Ok(NetworkMessage::Ping) => {
let response = NetworkMessage::Pong.strict_serialize().unwrap();
// 发送响应...
}
// 处理其他消息类型...
_ => {}
}
}
性能提示
- 对于大型数据结构,考虑使用
&[u8]
而不是Vec<u8>
来避免不必要的内存分配 - 在热路径上重用缓冲区而不是创建新的向量
- 使用
strict_serialize_into
和strict_deserialize_from
进行流式处理
错误处理
use strict_encoding::{StrictDecode, Error};
fn safe_decode(data: &[u8]) -> Result<Point, Error> {
Point::strict_deserialize(data)
}
match safe_decode(invalid_data) {
Ok(point) => println!("Decoded point: {:?}", point),
Err(e) => eprintln!("Decoding failed: {}", e),
}
完整示例
以下是一个完整的网络协议实现示例,展示了如何使用strict_encoding
进行消息的序列化和反序列化:
use strict_encoding::{StrictEncode, StrictDecode, Error};
// 定义网络协议消息类型
#[derive(StrictEncode, StrictDecode, Debug, PartialEq)]
enum ProtocolMessage {
Handshake {
version: u32,
features: Vec<String>,
},
DataChunk {
seq: u64,
payload: Vec<u8>,
},
Termination {
reason: String,
code: u8,
},
}
fn main() -> Result<(), Error> {
// 创建并序列化消息
let handshake = ProtocolMessage::Handshake {
version: 1,
features: vec!["encryption".to_string(), "compression".to_string()],
};
let serialized = handshake.strict_serialize()?;
println!("Serialized data: {:?}", serialized);
// 反序列化消息
let deserialized = ProtocolMessage::strict_deserialize(&serialized)?;
println!("Deserialized: {:?}", deserialized);
assert_eq!(handshake, deserialized);
Ok(())
}
总结
strict_encoding
为Rust提供了高效、类型安全的二进制序列化方案,特别适合需要精确控制数据布局的场景。通过derive宏,可以轻松为自定义类型实现编码逻辑,同时库提供了丰富的API来处理各种复杂情况。