Rust Base64标签化编解码库tagged-base64的使用,支持类型安全的高效数据转换与序列化
Rust Base64标签化编解码库tagged-base64的使用,支持类型安全的高效数据转换与序列化
安装
安装二进制工具
cargo install tagged-base64
作为库安装
在项目目录中运行以下Cargo命令:
cargo add tagged-base64
或在Cargo.toml中添加:
tagged-base64 = "0.4.0"
使用示例
下面是一个完整的示例,展示如何使用tagged-base64进行类型安全的Base64编解码:
use serde::{Serialize, Deserialize};
use tagged_base64::{TaggedB64, Tag};
// 定义自定义标签类型
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct MyTag;
// 实现Tag trait
impl Tag for MyTag {
fn tag() -> &'static str {
"mytag" // 这个标签会包含在Base64编码的输出中
}
}
// 定义使用标签的结构体
#[derive(Debug, Serialize, Deserialize)]
struct MyData {
#[serde(with = "TaggedB64::<MyTag>")]
data: Vec<u8>,
}
fn main() {
// 原始数据
let original_data = vec![1, 2, 3, 4, 5];
// 创建数据结构
let my_data = MyData {
data: original_data.clone(),
};
// 序列化为JSON
let json = serde_json::to_string(&my_data).unwrap();
println!("Serialized JSON: {}", json);
// 从JSON反序列化
let deserialized: MyData = serde_json::from_str(&json).unwrap();
// 验证数据
assert_eq!(deserialized.data, original_data);
println!("Deserialized data matches original!");
}
特性
- 类型安全:通过自定义标签确保只有正确标记的数据才能被解码
- 高效:利用Rust的性能优势提供快速的编解码操作
- 与Serde集成:无缝支持序列化和反序列化
- 可扩展:可以轻松定义自己的标签类型
完整示例代码
use serde::{Serialize, Deserialize};
use tagged_base64::{TaggedB64, Tag};
// 1. 定义两个不同的标签类型
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct UserDataTag;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct SessionDataTag;
// 2. 为每个标签实现Tag trait
impl Tag for UserDataTag {
fn tag() -> &'static str {
"user" // 用户数据标签
}
}
impl Tag for SessionDataTag {
fn tag() -> &'static str {
"session" // 会话数据标签
}
}
// 3. 定义两个使用不同标签的结构体
#[derive(Debug, Serialize, Deserialize)]
struct UserProfile {
#[serde(with = "TaggedB64::<UserDataTag>")]
avatar: Vec<u8>, // 用户头像数据
#[serde(with = "TaggedB64::<UserDataTag>")]
settings: Vec<u8>, // 用户设置数据
}
#[derive(Debug, Serialize, Deserialize)]
struct SessionInfo {
#[serde(with = "TaggedB64::<SessionDataTag>")]
token: Vec<u8>, // 会话令牌
#[serde(with = "TaggedB64::<SessionDataTag>")]
metadata: Vec<u8>, // 会话元数据
}
fn main() {
// 4. 创建示例数据
let user_profile = UserProfile {
avatar: vec![10, 20, 30, 40, 50],
settings: vec![1, 2, 3, 4, 5, 6, 7, 8],
};
let session_info = SessionInfo {
token: vec![255, 254, 253],
metadata: vec![100, 101, 102, 103],
};
// 5. 序列化为JSON
let user_json = serde_json::to_string(&user_profile).unwrap();
let session_json = serde_json::to_string(&session_info).unwrap();
println!("User Profile JSON: {}", user_json);
println!("Session Info JSON: {}", session_json);
// 6. 尝试反序列化 - 确保类型安全
// 正确的标签匹配
let user: UserProfile = serde_json::from_str(&user_json).unwrap();
let session: SessionInfo = serde_json::from_str(&session_json).unwrap();
// 错误的标签匹配会失败
let result: Result<UserProfile, _> = serde_json::from_str(&session_json);
assert!(result.is_err(), "Should fail due to tag mismatch");
println!("All operations completed successfully!");
}
文档
更多详细用法请参考官方文档。
1 回复
以下是关于tagged-base64
库的完整使用指南,包含所有示例代码:
完整示例代码
1. 预定义标签使用示例
use tagged_base64::prelude::*;
fn main() {
// 编码示例
let data = b"hello world";
let encoded = data.to_base64(Standard); // 使用标准Base64编码
println!("Encoded: {}", encoded);
// 解码示例
let decoded = Vec::<u8>::from_base64(&encoded, Standard).unwrap();
assert_eq!(decoded, data);
}
2. 自定义标签实现示例
use tagged_base64::{TaggedBase64, Tag};
// 自定义标签定义
struct MyCustomTag;
impl Tag for MyCustomTag {
const CONFIG: base64::Config = base64::Config::new(
base64::CharacterSet::Standard, // 使用标准字符集
true // 使用填充
);
}
fn main() {
let secret_data = b"sensitive information";
// 使用自定义标签编码
let encoded = secret_data.to_base64(MyCustomTag);
println!("Securely encoded: {}", encoded);
// 必须使用相同标签解码
let decoded = Vec::<u8>::from_base64(&encoded, MyCustomTag).unwrap();
assert_eq!(decoded, secret_data);
}
3. 序列化/反序列化完整示例
use serde::{Serialize, Deserialize};
use tagged_base64::{TaggedBase64, Standard};
#[derive(Serialize, Deserialize, Debug)]
struct User {
#[serde(with = "tagged_base64::serde")] // 使用tagged-base64的serde支持
avatar: Vec<u8>,
name: String,
}
fn main() {
// 创建用户对象
let user = User {
avatar: b"binary image data".to_vec(),
name: "Alice".to_string(),
};
// 序列化为JSON
let json = serde_json::to_string(&user).unwrap();
println!("Serialized JSON: {}", json);
// 从JSON反序列化
let deserialized: User = serde_json::from_str(&json).unwrap();
println!("Deserialized user: {:?}", deserialized);
assert_eq!(deserialized.avatar, b"binary image data");
}
4. 高级用法完整示例
use tagged_base64::{TaggedBase64, UrlSafe, Standard, Mime, DecodeError};
fn main() {
// 多种编码配置示例
let data = b"complex data @#$%^&";
println!("Standard编码: {}", data.to_base64(Standard));
println!("URL安全编码: {}", data.to_base64(UrlSafe));
println!("MIME编码: {}", data.to_base64(Mime));
// 错误处理示例
match Vec::<u8>::from_base64("invalid!data", Standard) {
Ok(data) => println!("解码成功: {:?}", data),
Err(DecodeError::InvalidByte(_, _)) => println!("错误: 包含无效字符"),
Err(e) => println!("其他错误: {}", e),
}
}
5. 性能优化完整示例
use std::borrow::Cow;
use tagged_base64::{TaggedBase64, Standard};
fn main() {
// 预分配缓冲区示例
let large_data = vec![0u8; 1024 * 1024]; // 1MB数据
let encoded = encode_large_data(&large_data);
println!("编码数据长度: {}", encoded.len());
// Cow使用示例
let input1 = "base64:SGVsbG8gV29ybGQ="; // Base64编码数据
let input2 = "plain text"; // 普通文本
println!("解码结果1: {:?}", maybe_decode(input1));
println!("解码结果2: {:?}", maybe_decode(input2));
}
// 预分配缓冲区的编码函数
fn encode_large_data(data: &[u8]) -> String {
let mut buf = String::with_capacity(data.len() * 4 / 3 + 4);
data.write_base64(Standard, &mut buf).unwrap();
buf
}
// 使用Cow避免不必要拷贝的函数
fn maybe_decode<'a>(input: &'a str) -> Cow<'a, [u8]> {
if input.starts_with("base64:") {
let encoded = &input[7..];
Cow::Owned(Vec::<u8>::from_base64(encoded, Standard).unwrap())
} else {
Cow::Borrowed(input.as_bytes())
}
}
使用建议
- 对于安全性要求高的场景,建议为每种数据类型创建独立的标签
- 处理大型数据时,务必使用预分配缓冲区的方式
- 在Web应用中,URL路径或参数编码使用UrlSafe标签
- 考虑使用新类型模式(New Type Pattern)包装不同标签的Base64数据
这个库通过类型系统在编译期捕获了许多潜在错误,同时保持了良好的运行时性能,是传统Base64编码的强类型替代方案。