Rust Base85编解码库base85的使用,支持高效二进制数据与ASCII字符串转换

Rust Base85编解码库base85的使用,支持高效二进制数据与ASCII字符串转换

base85是一个用于Base85编码的Rust库,遵循RFC1924规范,采用Mozilla Public License 2.0许可证发布。

描述

Base85编码有多种变体。最流行的变体通常被称为ascii85,以在Adobe产品中使用而闻名。本库实现的不是该算法。

RFC1924中实现的变体最初用于编码IPv6地址。它与其他版本使用相同的概念,但使用的字符集对嵌入源代码更友好,无需转义。在解码过程中会忽略ASCII空白字符(\n、\r、\t、空格)。Base85编码字符串比原始二进制数据大25%,比更常见的base64算法(33%)更高效。这种编码与JSON配合非常好,开销更低且不需要字符转义。

使用方法

虽然这是我第一个真正的Rust代码,但代码经过了充分测试,API也很简单:

  • encode()将字节切片转换为字符串
  • decode()将字符串引用转换为字节向量(u8)

这两个调用都在RAM中工作,因此处理大文件可能不是一个好主意。

安装

在项目目录中运行以下Cargo命令:

cargo add base85

或者在Cargo.toml中添加以下行:

base85 = "2.0.0"

完整示例代码

use base85;

fn main() {
    // 原始二进制数据
    let binary_data = b"Hello, Base85!";
    
    // 编码为Base85字符串
    let encoded = base85::encode(binary_data);
    println!("Encoded: {}", encoded);
    
    // 解码回二进制数据
    match base85::decode(&encoded) {
        Ok(decoded) => {
            println!("Decoded: {:?}", decoded);
            assert_eq!(binary_data.as_ref(), decoded.as_slice());
        },
        Err(e) => println!("Decoding error: {}", e),
    }
}

扩展示例代码

use base85;
use std::fs;

fn main() {
    // 示例1:编码解码短字符串
    let short_str = b"Rust Base85 encoding";
    let encoded_short = base85::encode(short_str);
    println!("Short string encoded: {}", encoded_short);
    
    if let Ok(decoded_short) = base85::decode(&encoded_short) {
        println!("Short string decoded: {:?}", String::from_utf8_lossy(&decoded_short));
    }

    // 示例2:处理文件内容
    if let Ok(file_data) = fs::read("example.bin") {
        // 编码文件内容
        let encoded_file = base85::encode(&file_data);
        println!("File encoded length: {}", encoded_file.len());
        
        // 解码文件内容
        match base85::decode(&encoded_file) {
            Ok(decoded_file) => {
                println!("File decoded length: {}", decoded_file.len());
                assert_eq!(file_data, decoded_file);
            },
            Err(e) => println!("File decoding error: {}", e),
        }
    }

    // 示例3:处理包含空白字符的编码字符串
    let encoded_with_whitespace = "Hello\nWorld\tBase85";
    match base85::decode(encoded_with_whitespace) {
        Ok(decoded) => {
            println!("Decoded with whitespace: {:?}", String::from_utf8_lossy(&decoded));
        },
        Err(e) => println!("Error decoding with whitespace: {}", e),
    }
}

贡献

我虽然编程有一段时间了,但在Rust方面还是个初学者。欢迎提出建议和贡献。虽然出于历史原因在GitHub上有一个镜像仓库,但此crate的官方仓库在GitLab。非常欢迎将问题和PR提交到该位置。

许可证

MPL-2.0-no-copyleft-exception


1 回复

Rust Base85编解码库base85使用指南

介绍

base85是一个Rust实现的Base85(Ascii85)编解码库,用于在二进制数据和ASCII字符串之间进行高效转换。Base85编码比Base64更高效,能将4字节二进制数据编码为5个ASCII字符。

特性

  • 支持标准Ascii85编码(RFC 1924)
  • 支持Z85编码(ZeroMQ规范)
  • 高性能实现
  • 无依赖纯Rust实现

使用方法

首先在Cargo.toml中添加依赖:

[dependencies]
base85 = "0.3"

基本编码解码

use base85::{Ascii85, Codec};

fn main() {
    // 原始数据
    let data = b"hello world";
    
    // 编码
    let encoded = Ascii85.encode(data);
    println!("Encoded: {}", encoded);
    // 输出: Encoded: <~87cURDZ*#TDfTZ)~>
    
    // 解码
    let decoded = Ascii85.decode(&encoded).unwrap();
    println!("Decoded: {:?}", decoded);
    // 输出: Decoded: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
}

使用Z85编码

use base85::{Z85, Codec};

fn main() {
    let data = b"Rust is awesome!";
    
    // Z85编码
    let encoded = Z85.encode(data);
    println!("Z85 encoded: {}", encoded);
    
    // Z85解码
    let decoded = Z85.decode(&encoded).unwrap();
    assert_eq!(decoded, data);
}

处理大文件

use base85::{Ascii85, Codec};
use std::io::{Read, Write};

fn encode_file(input_path: &str, output_path: &str) -> std::io::Result<()> {
    let mut input_file = std::fs::File::open(input_path)?;
    let mut output_file = std::fs::File::create(output_path)?;
    
    // 分块读取和编码
    let mut buffer = vec![0u8; 4096];
    loop {
        let bytes_read = input_file.read(&mut buffer)?;
        if bytes_read == 0 {
            break;
        }
        let encoded = Ascii85.encode(&buffer[..bytes_read]);
        writeln!(output_file, "{}", encoded)?;
    }
    
    Ok(())
}

自定义配置

use base85::{Config, Codec};

fn main() {
    let custom_config = Config::new()
        .with_padding(false)  // 不使用填充
        .with_delimiters(None, None);  // 不使用分隔符
    
    let data = b"custom configuration";
    let encoded = custom_config.encode(data);
    println!("Custom encoded: {}", encoded);
}

性能提示

  • 对于大型数据,考虑使用分块处理
  • 如果不需要分隔符,可以禁用它们以提高性能
  • Z85通常比Ascii85有更好的性能

错误处理

解码时可能会出错,应该正确处理错误:

use base85::Ascii85;

fn safe_decode(encoded: &str) -> Result<Vec<u8>, String> {
    Ascii85.decode(encoded)
        .map_err(|e| format!("Decoding failed: {}", e))
}

完整示例

下面是一个完整的Base85编解码示例,包含文件处理、自定义配置和错误处理:

use base85::{Ascii85, Z85, Config, Codec};
use std::fs;
use std::io::{self, Read, Write};

fn main() -> io::Result<()> {
    // 1. 基本编码解码演示
    let data = b"Rust Base85 demo";
    println!("原始数据: {:?}", data);
    
    // Ascii85编码
    let ascii85_encoded = Ascii85.encode(data);
    println!("Ascii85编码: {}", ascii85_encoded);
    
    // Ascii85解码
    let ascii85_decoded = Ascii85.decode(&ascii85_encoded).unwrap();
    println!("Ascii85解码: {:?}", ascii85_decoded);
    
    // Z85编码
    let z85_encoded = Z85.encode(data);
    println!("Z85编码: {}", z85_encoded);
    
    // Z85解码
    let z85_decoded = Z85.decode(&z85_encoded).unwrap();
    println!("Z85解码: {:?}", z85_decoded);
    
    // 2. 文件编码演示
    // 创建测试文件
    fs::write("test.txt", "This is a test file for Base85 encoding")?;
    
    // 编码文件
    encode_file_to_base85("test.txt", "encoded.txt")?;
    println!("文件编码完成");
    
    // 3. 自定义配置演示
    let custom_config = Config::new()
        .with_padding(false)
        .with_delimiters(None, None);
    
    let custom_encoded = custom_config.encode(data);
    println!("自定义配置编码: {}", custom_encoded);
    
    // 4. 错误处理演示
    match safe_decode("invalid base85 string") {
        Ok(decoded) => println!("解码成功: {:?}", decoded),
        Err(e) => println!("解码错误: {}", e),
    }
    
    Ok(())
}

/// 将文件内容编码为Base85格式
fn encode_file_to_base85(input_path: &str, output_path: &str) -> io::Result<()> {
    let mut input_file = fs::File::open(input_path)?;
    let mut output_file = fs::File::create(output_path)?;
    
    let mut buffer = vec![0u8; 4096];
    loop {
        let bytes_read = input_file.read(&mut buffer)?;
        if bytes_read == 0 {
            break;
        }
        let encoded = Ascii85.encode(&buffer[..bytes_read]);
        writeln!(output_file, "{}", encoded)?;
    }
    
    Ok(())
}

/// 安全解码Base85字符串
fn safe_decode(encoded: &str) -> Result<Vec<u8>, String> {
    Ascii85.decode(encoded)
        .map_err(|e| format!("解码失败: {}", e))
}

这个示例展示了:

  1. 基本的Ascii85和Z85编解码操作
  2. 文件编码处理
  3. 自定义配置使用
  4. 错误处理机制

要运行这个示例,请确保在Cargo.toml中添加了base85依赖。

回到顶部