Rust序列化库serde-hex的使用:高效实现十六进制编码与解码的serde扩展

serde-hex

Rust crate 用于简便且多功能的十六进制值序列化/反序列化。

概述

serde-hex crate 围绕 SerHex trait 构建,可以轻松指定自定义的十六进制序列化/反序列化。一旦实现,SerHex trait 通过其泛型类型参数进行配置(例如:SerHex<Compact> 用于没有前导零的十六进制值,或 SerHex<StrictPfx> 用于带前导零和 0x 前缀的值)。得益于 Rust 强大的编译器,只有配置实际使用的序列化/反序列化功能部分会被编译。使用 SerHex 最常见的方式是在为类型派生 SerializeDeserialize trait 时。

SerHex 自动为所有无符号整数类型实现,所有 Strict 变体为 [T;1][T;64] 的数组实现(当然,其中 T: SerHex)。我们跳过了长度为零的数组的默认实现,以及有符号整数和浮点数,因为没有特别直观的方式来表示这些值。

这个 crate 提供了许多有用的宏,用于在常见模式上实现 SerHex。如果没有宏适合你的需求,还提供了一些实用函数,使实现自定义变体尽可能轻松。

注意

如果你只是寻找通用的十六进制转换 trait,请查看广泛使用的 hex crate。这个 crate 相当专门用于可定制的 serde 互操作,如果你不需要这个功能,应该优先使用 hex crate 的通用 trait。

许可证

根据以下任一许可证授权:

  • Apache License, Version 2.0
  • MIT license

由你选择。

贡献

除非你明确声明,否则任何有意提交包含在作品中的贡献,如 Apache-2.0 许可证所定义,应按照上述双重许可,不附加任何额外条款或条件。

内容中提供的示例:

use serde_hex::{SerHex,StrictPfx,CompactPfx};

#[derive(Debug,PartialEq,Eq,Serialize,Deserialize)]
struct Foo {
    #[serde(with = "SerHex::<StrictPfx>")]
    bar: [u8;4],
    #[serde(with = "SerHex::<CompactPfx>")]
    bin: u64
}

fn it_works() {
    let foo = Foo { bar: [0,1,2,3], bin: 16 };
    let ser = serde_json::to_string(&foo).unwrap();
    let exp = r#"{"bar":"0x00010203","bin":"0x10"}"#;
    assert_eq!(ser,exp);
}

完整示例代码:

// 添加依赖到 Cargo.toml:
// serde-hex = "0.1.0"
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"

use serde::{Serialize, Deserialize};
use serde_hex::{SerHex, StrictPfx, CompactPfx};

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Example {
    // 使用 StrictPfx 配置:带前导零和 0x 前缀
    #[serde(with = "SerHex::<StrictPfx>")]
    strict_field: [u8; 4],
    
    // 使用 CompactPfx 配置:紧凑格式带 0x 前缀
    #[serde(with = "SerHex::<CompactPfx>")]
    compact_field: u64,
}

fn main() {
    // 创建示例结构体实例
    let example = Example {
        strict_field: [0, 1, 2, 3],
        compact_field: 16,
    };

    // 序列化为 JSON 字符串
    let serialized = serde_json::to_string(&example).unwrap();
    println!("Serialized: {}", serialized);

    // 预期输出:{"strict_field":"0x00010203","compact_field":"0x10"}
    let expected = r#"{"strict_field":"0x00010203","compact_field":"0x10"}"#;
    assert_eq!(serialized, expected);

    // 从 JSON 字符串反序列化
    let deserialized: Example = serde_json::from_str(&serialized).unwrap();
    println!("Deserialized: {:?}", deserialized);

    // 验证反序列化后的数据与原始数据一致
    assert_eq!(deserialized, example);
}

1 回复

serde-hex:Rust中的十六进制编码与解码扩展

概述

serde-hex是一个基于serde的Rust库扩展,专门用于处理十六进制数据的序列化与反序列化。它提供了高效且类型安全的方式,将二进制数据转换为十六进制字符串表示,或从十六进制字符串解析回原始数据。

核心特性

  • 支持固定大小数组和Vec<T>的十六进制编码
  • 提供紧凑和标准两种输出格式选项
  • 完全兼容serde生态系统
  • 零成本抽象,高性能处理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde-hex = "0.1"

基本用法示例

1. 结构体序列化

use serde::{Serialize, Deserialize};
use serde_hex::{SerHex, StrictPfx};

#[derive(Serialize, Deserialize)]
struct Transaction {
    #[serde(with = "SerHex::<StrictPfx>")]
    hash: [u8; 32],
    amount: u64,
}

let tx = Transaction {
    hash: [0xab; 32],
    amount: 1000,
};

// 序列化为JSON
let json = serde_json::to_string(&tx).unwrap();
println!("{}", json);
// 输出: {"hash":"0xababab...","amount":1000}

2. 向量数据编码

use serde_hex::{SerHex, Compact};

#[derive(Serialize, Deserialize)]
struct DataPacket {
    #[serde(with = "SerHex::<Compact>")]
    payload: Vec<u8>,
}

let packet = DataPacket {
    payload: vec![0xDE, 0xAD, 0xBE, 0xEF],
};

let json = serde_json::to_string(&packet).unwrap();
// 输出: {"payload":"deadbeef"}

3. 自定义配置选项

use serde_hex::{SerHex, Strict, prefixed};

#[derive(Serialize)]
struct CustomConfig {
    #[serde(with = "SerHex::<Strict>")]
    strict_hex: [u8; 4],
    
    #[serde(with = "prefixed")]
    prefixed_hex: Vec<u8>,
}

let data = CustomConfig {
    strict_hex: [1, 2, 3, 4],
    prefixed_hex: vec![0xFF, 0xEE],
};

4. 反序列化示例

use serde::Deserialize;
use serde_hex::SerHex;

#[derive(Deserialize)]
struct Config {
    #[serde(with = "SerHex")]
    api_key: [u8; 16],
}

let json_data = r#"{"api_key":"00112233445566778899aabbccddeeff"}"#;
let config: Config = serde_json::from_str(json_data).unwrap();

高级配置

serde-hex提供多种配置选项:

  • Strict: 严格模式(默认)
  • StrictPfx: 带前缀的严格模式
  • Compact: 紧凑模式
  • 自定义前缀和大小写设置

错误处理

use serde_hex::ParseHexError;

fn process_hex_data(hex_str: &str) -> Result<Vec<u8>, ParseHexError> {
    serde_hex::from_hex(hex_str)
}

性能建议

  • 对于固定大小数组,使用数组类型而非Vec以获得最佳性能
  • 在需要频繁序列化的场景,考虑使用Compact模式减少输出大小
  • 批量处理时使用from_hex/to_hex直接函数

这个库特别适合处理加密货币地址、哈希值、二进制配置数据等需要十六进制表示的场景。

完整示例demo

// 完整示例:展示serde-hex的各种用法
use serde::{Serialize, Deserialize};
use serde_json;
use serde_hex::{SerHex, Strict, StrictPfx, Compact, prefixed, from_hex, to_hex};

// 示例1:基本结构体序列化与反序列化
#[derive(Serialize, Deserialize, Debug)]
struct CryptoTransaction {
    #[serde(with = "SerHex::<StrictPfx>")] // 使用带前缀的严格模式
    transaction_hash: [u8; 32],
    #[serde(with = "SerHex::<Compact>")]   // 使用紧凑模式
    sender_address: Vec<u8>,
    amount: u64,
}

// 示例2:配置数据解析
#[derive(Deserialize, Debug)]
struct AppConfig {
    #[serde(with = "SerHex::<Strict>")]    // 使用严格模式(默认)
    secret_key: [u8; 32],
    #[serde(with = "prefixed")]            // 使用带前缀的模式
    api_token: Vec<u8>,
}

// 示例3:自定义错误处理
fn hex_processing_demo() -> Result<(), Box<dyn std::error::Error>> {
    // 直接使用from_hex/to_hex函数
    let data = vec![0x01, 0x02, 0x03, 0x04];
    let hex_string = to_hex::<Compact>(&data)?;
    println!("编码后的十六进制: {}", hex_string);
    
    let decoded_data = from_hex(&hex_string)?;
    println!("解码后的数据: {:?}", decoded_data);
    
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1:加密货币交易
    let transaction = CryptoTransaction {
        transaction_hash: [0xab; 32],
        sender_address: vec![0xde, 0xad, 0xbe, 0xef],
        amount: 1000000,
    };
    
    let json_output = serde_json::to_string(&transaction)?;
    println!("交易序列化: {}", json_output);
    
    // 示例2:配置解析
    let config_json = r#"
    {
        "secret_key": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
        "api_token": "0xffeeddccbbaa99887766554433221100"
    }"#;
    
    let config: AppConfig = serde_json::from_str(config_json)?;
    println!("解析的配置: {:?}", config);
    
    // 示例3:直接十六进制处理
    hex_processing_demo()?;
    
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_hex_conversion() {
        let original = vec![0x01, 0x02, 0x03, 0x04];
        let hex_str = to_hex::<Compact>(&original).unwrap();
        assert_eq!(hex_str, "01020304");
        
        let decoded = from_hex(&hex_str).unwrap();
        assert_eq!(decoded, original);
    }
    
    #[test]
    fn test_different_modes() {
        let data = vec![0xAB, 0xCD, 0xEF];
        
        // 测试不同模式
        let strict = to_hex::<Strict>(&data).unwrap();
        let strict_pfx = to_hex::<StrictPfx>(&data).unwrap();
        let compact = to_hex::<Compact>(&data).unwrap();
        
        println!("Strict: {}", strict);
        println!("StrictPfx: {}", strict_pfx);
        println!("Compact: {}", compact);
    }
}

这个完整示例展示了serde-hex库的主要功能:

  1. 结构体的序列化和反序列化,支持不同的十六进制编码模式
  2. 配置数据的解析和处理
  3. 直接使用from_hex/to_hex函数进行十六进制转换
  4. 错误处理和单元测试

示例中包含了严格模式、带前缀模式和紧凑模式的使用,以及如何在不同场景下选择合适的编码方式。

回到顶部