Rust高性能压缩库miniz_oxide_c_api的使用,提供跨平台DEFLATE压缩算法的轻量级Rust实现

Rust高性能压缩库miniz_oxide_c_api的使用,提供跨平台DEFLATE压缩算法的轻量级Rust实现

miniz_oxide是一个纯Rust实现的miniz DEFLATE/zlib编码器/解码器替代品,不使用任何unsafe代码。它可以在no_std环境下构建,但需要使用alloc和collections crate。

主要特性

  • 纯Rust实现,不使用unsafe代码
  • 支持no_std环境
  • 提供C API接口
  • 轻量级DEFLATE压缩算法实现
  • MIT许可证

版本要求

miniz_oxide 0.8.x需要至少Rust 1.56.0版本 miniz_oxide 0.7.x需要至少Rust 1.50.0版本

示例代码

use miniz_oxide::deflate::compress_to_vec;
use miniz_oxide::inflate::decompress_to_vec;

fn main() {
    // 原始数据
    let data = b"Hello, this is some test data to compress";
    
    // 压缩数据
    let compressed = compress_to_vec(data, 6);
    println!("Compressed size: {}", compressed.len());
    
    // 解压数据
    let decompressed = decompress_to_vec(&compressed).unwrap();
    assert_eq!(data, decompressed.as_slice());
    println!("Decompressed matches original!");
}

C API使用示例

miniz_oxide_c_api提供了C语言接口,可以用于C/C++项目中:

#include "miniz.h"  // 使用miniz_oxide_c_api提供的头文件

int main() {
    // 初始化压缩器
    tdefl_compressor *compressor = tdefl_compressor_alloc();
    
    const char *input = "Test data to compress";
    size_t input_size = strlen(input);
    
    // 预估最大输出大小
    size_t max_output_size = tdefl_compress_bound(input_size);
    void *output = malloc(max_output_size);
    
    // 压缩数据
    size_t compressed_size = max_output_size;
    tdefl_status status = tdefl_compress(compressor, input, &input_size, 
                                        output, &compressed_size, 
                                        TDEFL_WRITE_ZLIB_HEADER | TDEFL_DEFAULT_MAX_PROBES);
    
    if (status == TDEFL_STATUS_DONE) {
        printf("Compressed from %zu to %zu bytes\n", input_size, compressed_size);
    }
    
    // 释放资源
    free(output);
    tdefl_compressor_free(compressor);
    return 0;
}

构建和测试

# 运行测试
$ cargo test

# 运行基准测试
$ cargo bench --features=benching

在C/C++项目中使用

链接由build.sh生成的libminiz_oxide_c_api.a静态库,并使用miniz_oxide_c_api提供的miniz.h头文件。

许可证

该库(不包括用于测试的miniz C代码)采用MIT许可证。基于miniz C库的部分采用MIT许可证和非许可证双重许可。

完整示例demo

Rust完整示例

use miniz_oxide::deflate::{compress_to_vec, CompressionLevel};
use miniz_oxide::inflate::decompress_to_vec;

fn main() {
    // 原始数据
    let data = b"This is a longer text to demonstrate compression and decompression with miniz_oxide in Rust. It contains more data to show the compression ratio and performance.";
    
    // 压缩数据 - 使用默认压缩级别6
    let compressed_default = compress_to_vec(data, 6);
    println!("Default compression (level 6): {} -> {} bytes", data.len(), compressed_default.len());
    
    // 压缩数据 - 使用最快压缩级别1
    let compressed_fast = compress_to_vec(data, 1);
    println!("Fast compression (level 1): {} -> {} bytes", data.len(), compressed_fast.len());
    
    // 压缩数据 - 使用最佳压缩级别9
    let compressed_best = compress_to_vec(data, 9);
    println!("Best compression (level 9): {} -> {} bytes", data.len(), compressed_best.len());
    
    // 解压数据
    let decompressed = decompress_to_vec(&compressed_best).unwrap();
    assert_eq!(data, decompressed.as_slice());
    println!("Decompressed successfully, matches original data!");
    
    // 打印压缩比
    println!("Compression ratio (best): {:.2}%", 
        (compressed_best.len() as f32 / data.len() as f32) * 100.0);
}

C语言完整示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miniz.h"  // miniz_oxide_c_api提供的头文件

int main() {
    // 初始化压缩器
    tdefl_compressor *compressor = tdefl_compressor_alloc();
    if (!compressor) {
        fprintf(stderr, "Failed to allocate compressor\n");
        return 1;
    }
    
    const char *input = "This is a sample text to demonstrate miniz_oxide C API compression and decompression functionality.";
    size_t input_size = strlen(input);
    
    // 预估最大输出大小并分配内存
    size_t max_output_size = tdefl_compress_bound(input_size);
    void *compressed_output = malloc(max_output_size);
    if (!compressed_output) {
        fprintf(stderr, "Memory allocation failed\n");
        tdefl_compressor_free(compressor);
        return 1;
    }
    
    // 压缩数据
    size_t compressed_size = max_output_size;
    tdefl_status status = tdefl_compress(
        compressor, 
        input, 
        &input_size,
        compressed_output, 
        &compressed_size,
        TDEFL_WRITE_ZLIB_HEADER | TDEFL_DEFAULT_MAX_PROBES
    );
    
    if (status != TDEFL_STATUS_DONE) {
        fprintf(stderr, "Compression failed with status: %d\n", status);
        free(compressed_output);
        tdefl_compressor_free(compressor);
        return 1;
    }
    
    printf("Original size: %zu, Compressed size: %zu\n", input_size, compressed_size);
    
    // 初始化解压器
    tinfl_decompressor *decompressor = tinfl_decompressor_alloc();
    if (!decompressor) {
        fprintf(stderr, "Failed to allocate decompressor\n");
        free(compressed_output);
        tdefl_compressor_free(compressor);
        return 1;
    }
    
    // 预估解压后大小并分配内存
    size_t decompressed_size = input_size;  // 我们知道原始大小
    void *decompressed_output = malloc(decompressed_size);
    if (!decompressed_output) {
        fprintf(stderr, "Memory allocation failed\n");
        free(compressed_output);
        tdefl_compressor_free(compressor);
        tinfl_decompressor_free(decompressor);
        return 1;
    }
    
    // 解压数据
    size_t in_bytes = compressed_size;
    size_t out_bytes = decompressed_size;
    tinfl_status decomp_status = tinfl_decompress(
        decompressor,
        compressed_output,
        &in_bytes,
        decompressed_output,
        &out_bytes,
        TINFL_FLAG_PARSE_ZLIB_HEADER
    );
    
    if (decomp_status != TINFL_STATUS_DONE) {
        fprintf(stderr, "Decompression failed with status: %d\n", decomp_status);
    } else {
        printf("Decompressed successfully. Original and decompressed data match: %s\n", 
               memcmp(input, decompressed_output, input_size) == 0 ? "true" : "false");
    }
    
    // 释放所有资源
    free(compressed_output);
    free(decompressed_output);
    tdefl_compressor_free(compressor);
    tinfl_decompressor_free(decompressor);
    
    return 0;
}

1 回复

Rust高性能压缩库miniz_oxide_c_api使用指南

miniz_oxide_c_api是一个提供跨平台DEFLATE压缩算法的轻量级Rust实现库,它是miniz_oxide的C API封装版本。

特性

  • 纯Rust实现,无unsafe代码
  • 支持DEFLATE压缩/解压缩算法
  • 轻量级,无额外依赖
  • 提供C API接口,方便与其他语言交互
  • 性能接近zlib

安装

在Cargo.toml中添加依赖:

[dependencies]
miniz_oxide_c_api = "0.1"

基本使用示例

压缩数据

use miniz_oxide_c_api::compress;

fn main() {
    let input_data = b"This is some test data to compress";
    
    // 压缩级别范围0-10,6是默认值
    let compressed_data = compress::compress_to_vec(input_data, 6).unwrap();
    
    println!("Compressed size: {} bytes", compressed_data.len());
}

解压数据

use miniz_oxide_c_api::decompress;

fn main() {
    let compressed_data = /* 从某处获取压缩数据 */;
    
    let decompressed_data = decompress::decompress_to_vec(&compressed_data).unwrap();
    
    println!("Decompressed data: {:?}", String::from_utf8_lossy(&decompressed_data));
}

流式压缩/解压缩

对于大文件处理,可以使用流式API:

流式压缩

use miniz_oxide_c_api::stream::{compress, Action, Status, Flush};

fn stream_compress(input: &[u8]) -> Vec<u8> {
    let mut compressor = compress::Stream::new();
    let mut output = Vec::new();
    let mut input_pos = 0;
    
    loop {
        let (status, bytes_read, bytes_written) = compressor.compress(
            &input[input_pos..],
            &mut output,
            Flush::Finish
        );
        
        input_pos += bytes_read;
        
        if status == Status::StreamEnd {
            break;
        }
    }
    
    output
}

流式解压

use miniz_oxide_c_api::stream::{decompress, Status, Flush};

fn stream_decompress(input: &[u8]) -> Vec<u8> {
    let mut decompressor = decompress::Stream::new();
    let mut output = Vec::new();
    let mut input_pos = 0;
    
    loop {
        let (status, bytes_read, bytes_written) = decompressor.decompress(
            &input[input_pos..],
            &mut output,
            Flush::Finish
        );
        
        input_pos += bytes_read;
        
        if status == Status::StreamEnd {
            break;
        }
    }
    
    output
}

完整示例demo

下面是一个完整的压缩和解压示例:

use miniz_oxide_c_api::{compress, decompress};

fn main() {
    // 原始数据
    let original_data = b"This is a test string that will be compressed and then decompressed";
    println!("Original data size: {} bytes", original_data.len());

    // 压缩数据
    let compressed_data = compress::compress_to_vec(original_data, 6).unwrap();
    println!("Compressed size: {} bytes", compressed_data.len());
    
    // 解压数据
    let decompressed_data = decompress::decompress_to_vec(&compressed_data).unwrap();
    println!("Decompressed size: {} bytes", decompressed_data.len());
    
    // 验证数据是否一致
    assert_eq!(original_data, decompressed_data.as_slice());
    println!("Decompressed data matches original!");
}

性能提示

  1. 对于小数据块,一次性压缩(compress_to_vec)通常比流式API更快
  2. 压缩级别越高(接近10),压缩率越高但速度越慢
  3. 解压速度通常不受压缩级别影响

跨语言使用(C API)

miniz_oxide_c_api提供了C兼容的API,可以在其他语言中使用:

#include <stddef.h>
#include <stdint.h>

// 压缩函数
size_t miniz_compress(uint8_t *dest, size_t *dest_len, 
                     const uint8_t *source, size_t source_len, 
                     int level);

// 解压函数
size_t miniz_decompress(uint8_t *dest, size_t *dest_len,
                       const uint8_t *source, size_t source_len);

注意事项

  • 确保解压时提供足够大的输出缓冲区
  • 检查所有操作的返回状态
  • 对于生产环境,考虑添加错误处理和边界检查

这个库非常适合需要轻量级DEFLATE压缩/解压且希望避免zlib依赖的项目。

回到顶部