Rust高性能压缩库cloudflare-zlib-sys的使用:Cloudflare优化的zlib系统绑定,提供快速数据压缩与解压

Rust高性能压缩库cloudflare-zlib-sys的使用:Cloudflare优化的zlib系统绑定,提供快速数据压缩与解压

简介

cloudflare-zlib-sys是Cloudflare优化的zlib C实现的Rust绑定库。该库为64位ARM和Intel CPU构建zlib实现,要求x86-64 CPU支持SSE 4.2或ARM64支持NEON & CRC。不支持32位架构。

该库的API/ABI与原始Zlib保持相同。

安装

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

cargo add cloudflare-zlib-sys

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

cloudflare-zlib-sys = "0.3.6"

示例代码

以下是一个使用cloudflare-zlib-sys进行数据压缩和解压的完整示例:

use cloudflare_zlib_sys::*;
use std::ffi::CString;
use std::ptr;

fn main() {
    // 原始数据
    let original_data = b"Hello, this is a test string for zlib compression and decompression!";
    
    // 压缩数据
    let compressed_data = compress_data(original_data);
    println!("Compressed size: {}", compressed_data.len());
    
    // 解压数据
    let decompressed_data = decompress_data(&compressed_data);
    println!("Decompressed data: {:?}", String::from_utf8_lossy(&decompressed_data));
}

fn compress_data(data: &[u8]) -> Vec<u8> {
    // 初始化zlib流
    let mut stream: z_stream = unsafe { std::mem::zeroed() };
    
    // 设置输出缓冲区
    let mut out_buffer = vec![0; data.len()];
    
    unsafe {
        // 初始化压缩
        deflateInit_(
            &mut stream as *mut _,
            Z_DEFAULT_COMPRESSION,
            CString::new("1.2.11").unwrap().as_ptr(),
            std::mem::size_of::<z_stream>() as i32,
        );
        
        // 设置输入数据
        stream.next_in = data.as_ptr() as *mut _;
        stream.avail_in = data.len() as u32;
        
        // 设置输出缓冲区
        stream.next_out = out_buffer.as_mut_ptr();
        stream.avail_out = out_buffer.len() as u32;
        
        // 执行压缩
        deflate(&mut stream as *mut _, Z_FINISH);
        
        // 结束压缩
        deflateEnd(&mut stream as *mut _);
        
        // 调整输出缓冲区大小以匹配实际压缩数据大小
        out_buffer.set_len(stream.total_out as usize);
    }
    
    out_buffer
}

fn decompress_data(data: &[u8]) -> Vec<u8> {
    // 初始化zlib流
    let mut stream: z_stream = unsafe { std::mem::zeroed() };
    
    // 设置输出缓冲区(初始大小为压缩数据的4倍)
    let mut out_buffer = vec![0; data.len() * 4];
    
    unsafe {
        // 初始化解压
        inflateInit_(
            &mut stream as *mut _,
            CString::new("1.2.11").unwrap().as_ptr(),
            std::mem::size_of::<z_stream>() as i32,
        );
        
        // 设置输入数据
        stream.next_in = data.as_ptr() as *mut _;
        stream.avail_in = data.len() as u32;
        
        // 设置输出缓冲区
        stream.next_out = out_buffer.as_mut_ptr();
        stream.avail_out = out_buffer.len() as u32;
        
        // 执行解压
        inflate(&mut stream as *mut _, Z_FINISH);
        
        // 结束解压
        inflateEnd(&mut stream as *mut _);
        
        // 调整输出缓冲区大小以匹配实际解压数据大小
        out_buffer.set_len(stream.total_out as usize);
    }
    
    out_buffer
}

完整示例代码

以下是基于上述示例的完整实现,增加了错误处理和更详细的注释:

use cloudflare_zlib_sys::*;
use std::ffi::CString;
use std::io::{self, Error, ErrorKind};

fn main() -> io::Result<()> {
    // 原始数据
    let original_data = b"Hello, this is a longer test string for zlib compression and decompression with cloudflare-zlib-sys!";
    println!("Original data size: {} bytes", original_data.len());
    
    // 压缩数据
    let compressed_data = compress_data(original_data)?;
    println!("Compressed size: {} bytes (ratio: {:.2}%)", 
        compressed_data.len(),
        (compressed_data.len() as f32 / original_data.len() as f32) * 100.0
    );
    
    // 解压数据
    let decompressed_data = decompress_data(&compressed_data)?;
    println!("Decompressed size: {} bytes", decompressed_data.len());
    
    // 验证数据完整性
    if original_data == decompressed_data.as_slice() {
        println!("Data integrity verified successfully!");
        Ok(())
    } else {
        Err(Error::new(ErrorKind::InvalidData, "Decompressed data does not match original"))
    }
}

fn compress_data(data: &[u8]) -> io::Result<Vec<u8>> {
    // 初始化zlib流结构体
    let mut stream: z_stream = unsafe { std::mem::zeroed() };
    
    // 创建输出缓冲区,初始大小与输入相同(压缩后通常会更小)
    let mut out_buffer = vec![0; data.len()];
    
    unsafe {
        // 初始化压缩流
        let version = CString::new("1.2.11").unwrap();
        let result = deflateInit_(
            &mut stream as *mut _,
            Z_DEFAULT_COMPRESSION,  // 使用默认压缩级别
            version.as_ptr(),
            std::mem::size_of::<z_stream>() as i32
        );
        
        if result != Z_OK {
            return Err(Error::new(ErrorKind::Other, "Failed to initialize zlib compression"));
        }
        
        // 设置输入数据指针和长度
        stream.next_in = data.as_ptr() as *mut _;
        stream.avail_in = data.len() as u32;
        
        // 设置输出缓冲区指针和长度
        stream.next_out = out_buffer.as_mut_ptr();
        stream.avail_out = out_buffer.len() as u32;
        
        // 执行压缩操作,使用Z_FINISH表示这是最后一块数据
        let result = deflate(&mut stream as *mut _, Z_FINISH);
        if result != Z_STREAM_END {
            deflateEnd(&mut stream as *mut _);
            return Err(Error::new(ErrorKind::Other, "Compression failed"));
        }
        
        // 结束压缩流
        if deflateEnd(&mut stream as *mut _) != Z_OK {
            return Err(Error::new(ErrorKind::Other, "Failed to end compression stream"));
        }
        
        // 调整输出缓冲区大小以匹配实际压缩数据大小
        out_buffer.set_len(stream.total_out as usize);
    }
    
    Ok(out_buffer)
}

fn decompress_data(data: &[u8]) -> io::Result<Vec<u8>> {
    // 初始化zlib流结构体
    let mut stream: z_stream = unsafe { std::mem::zeroed() };
    
    // 创建输出缓冲区,初始大小是压缩数据的4倍(解压后数据通常比压缩数据大)
    let mut out_buffer = vec![0; data.len() * 4];
    
    unsafe {
        // 初始化解压流
        let version = CString::new("1.2.11").unwrap();
        let result = inflateInit_(
            &mut stream as *mut _,
            version.as_ptr(),
            std::mem::size_of::<z_stream>() as i32
        );
        
        if result != Z_OK {
            return Err(Error::new(ErrorKind::Other, "Failed to initialize zlib decompression"));
        }
        
        // 设置输入数据指针和长度
        stream.next_in = data.as_ptr() as *mut _;
        stream.avail_in = data.len() as u32;
        
        // 设置输出缓冲区指针和长度
        stream.next_out = out_buffer.as_mut_ptr();
        stream.avail_out = out_buffer.len() as u32;
        
        // 执行解压操作,使用Z_FINISH表示这是最后一块数据
        let result = inflate(&mut stream as *mut _, Z_FINISH);
        if result != Z_STREAM_END {
            inflateEnd(&mut stream as *mut _);
            return Err(Error::new(ErrorKind::Other, "Decompression failed"));
        }
        
        // 结束解压流
        if inflateEnd(&mut stream as *mut _) != Z_OK {
            return Err(Error::new(ErrorKind::Other, "Failed to end decompression stream"));
        }
        
        // 调整输出缓冲区大小以匹配实际解压数据大小
        out_buffer.set_len(stream.total_out as usize);
    }
    
    Ok(out_buffer)
}

注意事项

  1. 该库需要64位CPU架构支持
  2. 对于Intel CPU,需要支持SSE 4.2指令集
  3. 对于ARM CPU,需要支持NEON和CRC指令
  4. 32位架构不受支持

许可证

该库使用Zlib许可证。


1 回复

以下是根据提供的内容整理的完整指南,包含示例代码和详细说明:

Rust高性能压缩库cloudflare-zlib-sys使用指南

简介

cloudflare-zlib-sys是Cloudflare优化的zlib系统绑定库,提供了比标准zlib更快速的数据压缩与解压功能。这个库是Cloudflare对zlib进行性能优化后的Rust绑定版本,特别适合需要高性能压缩/解压的场景。

主要特性

  • 比标准zlib更快的压缩和解压速度
  • 与标准zlib API兼容
  • 针对现代CPU架构优化
  • 支持所有标准zlib压缩级别

安装方法

在Cargo.toml中添加依赖:

[dependencies]
cloudflare-zlib-sys = "1.1.0"

完整示例代码

use cloudflare_zlib_sys::*;
use std::ffi::CString;
use std::os::raw::c_uint;
use std::mem;

fn main() {
    // 示例数据
    let data = b"This is a test string to demonstrate compression and decompression with cloudflare-zlib-sys";
    
    // 压缩数据
    let compressed = compress_data(data);
    println!("Compressed size: {} (from {})", compressed.len(), data.len());
    
    // 解压数据
    if let Some(decompressed) = decompress_data(&compressed, data.len()) {
        println!("Decompressed matches original: {}", decompressed == data);
    } else {
        println!("Decompression failed!");
    }
    
    // 流式压缩示例
    let stream_compressed = stream_compress(data);
    println!("Stream compressed size: {}", stream_compressed.len());
}

// 基础压缩函数
fn compress_data(input: &[u8]) -> Vec<u8> {
    // 估算输出缓冲区大小
    let bound = unsafe { compressBound(input.len() as c_uint) };
    let mut output = vec![0u8; bound as usize];
    
    let mut out_len = bound;
    
    unsafe {
        compress(
            output.as_mut_ptr(),
            &mut out_len,
            input.as_ptr(),
            input.len() as c_uint,
            Z_DEFAULT_COMPRESSION,
        );
    }
    
    output.truncate(out_len as usize);
    output
}

// 基础解压函数
fn decompress_data(compressed: &[u8], original_size: usize) -> Option<Vec<u8>> {
    let mut output = vec![0u8; original_size];
    let mut out_len = original_size as c_uint;
    
    let result = unsafe {
        uncompress(
            output.as_mut_ptr(),
            &mut out_len,
            compressed.as_ptr(),
            compressed.len() as c_uint,
        )
    };
    
    if result == Z_OK {
        output.truncate(out_len as usize);
        Some(output)
    } else {
        None
    }
}

// 流式压缩函数
fn stream_compress(input: &[u8]) -> Vec<u8> {
    let mut stream: z_stream = unsafe { mem::zeroed() };
    let mut output = Vec::with_capacity(input.len() / 2);
    let mut out_buf = [0u8; 1024];
    
    unsafe {
        deflateInit_(&mut stream, Z_DEFAULT_COMPRESSION, 
                    CString::new("1.2.11").unwrap().as_ptr(), 
                    mem::size_of::<z_stream>() as i32);
        
        stream.next_in = input.as_ptr() as *mut _;
        stream.avail_in = input.len() as c_uint;
        
        loop {
            stream.next_out = out_buf.as_mut_ptr() as *mut _;
            stream.avail_out = out_buf.len() as c_uint;
            
            let ret = deflate(&mut stream, Z_FINISH);
            
            let produced = out_buf.len() - stream.avail_out as usize;
            output.extend_from_slice(&out_buf[..produced]);
            
            if ret == Z_STREAM_END {
                break;
            }
        }
        
        deflateEnd(&mut stream);
    }
    
    output
}

性能建议

  1. 对于大文件,使用流式处理(如上面的示例)而不是一次性处理

  2. 根据数据类型选择合适的压缩级别:

    • Z_NO_COMPRESSION: 最快但不压缩
    • Z_BEST_SPEED: 快速压缩
    • Z_DEFAULT_COMPRESSION: 平衡压缩率和速度
    • Z_BEST_COMPRESSION: 最高压缩率但较慢
  3. 重用z_stream结构体以避免重复分配内存

错误处理

所有函数返回Z_OK(0)表示成功,其他值表示错误。常见错误码:

pub const Z_OK: i32 = 0;
pub const Z_STREAM_END: i32 = 1;
pub const Z_NEED_DICT: i32 = 2;
pub const Z_ERRNO: i32 = -1;
pub const Z_STREAM_ERROR: i32 = -2;
pub const Z_DATA_ERROR: i32 = -3;
pub const Z_MEM_ERROR: i32 = -4;
pub const Z_BUF_ERROR: i32 = -5;
pub const Z_VERSION_ERROR: i32 = -6;

注意事项

  1. 这个库是zlib的系统绑定,使用时需要系统安装zlib库
  2. 在多线程环境中使用时,每个线程应该使用自己的z_stream结构体
  3. 压缩和解压时使用相同的压缩级别和策略可以获得最佳性能

通过使用cloudflare-zlib-sys,你可以在Rust应用中享受到Cloudflare优化的zlib性能,特别适合网络服务、数据处理等高性能场景。

回到顶部