Rust可变长度整数编码库varinteger的使用:高效处理可变长度整数压缩与解压

Rust可变长度整数编码库varinteger的使用:高效处理可变长度整数压缩与解压

varinteger是一个Rust模块,用于编码/解码可变长度整数(varints),不涉及任何IO操作。它受到Node.js varint模块的启发。

使用示例

extern crate varinteger;

let mut buf = [0; 512];

// 将1000编码为varint并写入buf,返回写入的字节数
let bytes_encoded = varinteger::encode(1000, &mut buf);

let mut value = 0u64;
// 从buf解码varint到value,返回解码的字节数
let bytes_decoded = varinteger::decode(&buf, &mut value);

println!("encoded and decoded {}", value);

完整示例

以下是一个更完整的示例,展示了如何使用varinteger库进行可变长度整数的压缩和解压:

extern crate varinteger;

fn main() {
    // 准备一个足够大的缓冲区
    let mut buffer = [0u8; 10];
    
    // 要编码的数值
    let numbers = [1, 127, 128, 255, 256, 1000, 65535, 1_000_000];
    
    for num in &numbers {
        // 编码数值到缓冲区
        let bytes_written = varinteger::encode(*num, &mut buffer);
        println!("Encoded {} into {} bytes: {:?}", 
                num, 
                bytes_written, 
                &buffer[..bytes_written]);
        
        // 从缓冲区解码
        let mut decoded = 0u64;
        let bytes_read = varinteger::decode(&buffer, &mut decoded);
        
        assert_eq!(*num, decoded);
        assert_eq!(bytes_written, bytes_read);
        
        println!("Decoded back to: {}\n", decoded);
    }
    
    // 演示连续编码多个数值
    let mut offset = 0;
    let mut multi_buffer = [0u8; 20];
    
    for num in &numbers {
        offset += varinteger::encode(*num, &mut multi_buffer[offset..]);
    }
    
    println!("All numbers encoded in sequence: {:?}\n", &multi_buffer[..offset]);
    
    // 从连续缓冲区中解码多个数值
    let mut pos = 0;
    while pos < offset {
        let mut value = 0u64;
        let bytes_read = varinteger::decode(&multi_buffer[pos..], &mut value);
        println!("Decoded value: {} ({} bytes)", value, bytes_read);
        pos += bytes_read;
    }
}

特点

  1. 纯内存操作,不涉及IO
  2. 简单的API:encode和decode两个主要函数
  3. 高效的可变长度整数编码/解码
  4. 支持大整数(u64)

安装

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

cargo add varinteger

或者在Cargo.toml中添加:

varinteger = "1.0.6"

许可证

MIT

完整示例代码

以下是一个更完整的示例,展示了varinteger库的更多用法:

extern crate varinteger;

fn main() {
    // 示例1: 基本编码解码
    let mut buffer = [0u8; 10];
    let num = 123456;
    
    // 编码
    let bytes_written = varinteger::encode(num, &mut buffer);
    println!("编码 {} 使用 {} 字节: {:?}", num, bytes_written, &buffer[..bytes_written]);
    
    // 解码
    let mut decoded = 0u64;
    let bytes_read = varinteger::decode(&buffer, &mut decoded);
    println!("解码结果: {}, 读取字节数: {}", decoded, bytes_read);
    
    // 示例2: 处理边界值
    let edge_cases = [0, 1, 127, 128, 255, 256, u64::MAX];
    for &case in &edge_cases {
        let bytes = varinteger::encode(case, &mut buffer);
        let mut result = 0u64;
        varinteger::decode(&buffer[..bytes], &mut result);
        println!("边界值测试: 原值={}, 编码后={:?}, 解码后={}", case, &buffer[..bytes], result);
    }
    
    // 示例3: 流式处理多个值
    let values = [10, 20, 30, 40, 50];
    let mut stream_buffer = [0u8; 50];
    let mut position = 0;
    
    // 流式编码
    for &val in &values {
        position += varinteger::encode(val, &mut stream_buffer[position..]);
    }
    println!("流式编码结果: {:?}", &stream_buffer[..position]);
    
    // 流式解码
    let mut read_pos = 0;
    while read_pos < position {
        let mut val = 0u64;
        let bytes = varinteger::decode(&stream_buffer[read_pos..], &mut val);
        println!("解码值: {}, 字节数: {}", val, bytes);
        read_pos += bytes;
    }
}

1 回复

Rust可变长度整数编码库varinteger的使用指南

介绍

varinteger是一个Rust库,用于高效地压缩和解压可变长度整数。它实现了可变长度整数编码方案,类似于Protocol Buffers中使用的varint编码,可以有效地压缩小整数,同时也能处理大整数。

这种编码方式特别适合网络传输和磁盘存储场景,其中数值较小的整数出现频率较高,可以显著减少数据大小。

主要特性

  • 支持有符号和无符号整数
  • 编码后的字节数取决于数值大小(小数值占用更少字节)
  • 提供基本类型(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128)的支持
  • 零开销抽象,性能接近手写代码

使用方法

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

[dependencies]
varinteger = "0.7"

基本使用示例

use varinteger::{encode, decode};

fn main() {
    // 编码无符号整数
    let num: u32 = 300;
    let mut buffer = [0u8; 5];
    let bytes_used = encode(num, &mut buffer).unwrap();
    println!("Encoded {:?} into {:?} bytes", num, &buffer[..bytes_used]);
    
    // 解码无符号整数
    let (decoded_num, bytes_used) = decode::<u32>(&buffer).unwrap();
    println!("Decoded back to {}", decoded_num);
    
    // 编码有符号整数
    let signed_num: i32 = -150;
    let mut signed_buffer = [0u8; 5];
    let bytes_used = encode(signed_num, &mut signed_buffer).unwrap();
    println!("Encoded {:?} into {:?} bytes", signed_num, &signed_buffer[..bytes_used]);
    
    // 解码有符号整数
    let (decoded_signed, bytes_used) = decode::<i32>(&signed_buffer).unwrap();
    println!("Decoded back to {}", decoded_signed);
}

流式处理示例

use varinteger::{encode, decode_from_stream};
use std::io::Cursor;

fn main() {
    // 模拟从流中读取多个varint
    let data = [0x96, 0x01, 0xFE, 0x01, 0xFF, 0xFF, 0x03];
    let mut cursor = Cursor::new(&data);
    
    // 解码第一个数
    let (first, bytes_read) = decode_from_stream::<u32, _>(&mut cursor).unwrap();
    println!("First number: {}, bytes read: {}", first, bytes_read);
    
    // 解码第二个数
    let (second, bytes_read) = decode_from_stream::<u32, _>(&mut cursor).unwrap();
    println!("Second number: {}, bytes read: {}", second, bytes_read);
    
    // 解码第三个数
    let (third, bytes_read) = decode_from_stream::<u32, _>(&mut cursor).unwrap();
    println!("Third number: {}, bytes read: {}", third, bytes_read);
}

高级用法:自定义类型

use varinteger::{VarInt, VLQ};

#[derive(Debug, Default)]
struct MyCustomInt(i32);

impl VarInt for MyCustomInt {
    fn encode_var(self, dst: &mut [u8]) -> Result<usize, varinteger::EncodeError> {
        self.0.encode_var(dst)
    }

    fn decode_var src: &[u8]) -> Result<(Self, usize), varinteger::DecodeError> {
        i32::decode_var(src).map(|(v, s)| (MyCustomInt(v), s))
    }
}

fn main() {
    let num = MyCustomInt(500);
    let mut buffer = [0u8; 5];
    let bytes_used = num.encode_var(&mut buffer).unwrap();
    println!("Encoded custom type: {:?} bytes", &buffer[..bytes_used]);
    
    let (decoded, _) = MyCustomInt::decode_var(&buffer).unwrap();
    println!("Decoded custom type: {:?}", decoded);
}

性能提示

  1. 对于已知最大值的场景,可以预分配足够大的缓冲区:

    // u32最多需要5字节
    let mut buffer = [0u8; 5];
    
  2. 批量处理时,考虑重用缓冲区以减少分配。

  3. 对于网络传输,考虑结合bytes或byteorder crate使用。

错误处理

所有编码解码操作都返回Result类型,应适当处理可能的错误:

match encode(value, &mut buffer) {
    Ok(bytes_written) => println!("Used {} bytes", bytes_written),
    Err(e) => eprintln!("Encoding failed: {:?}", e),
}

varinteger库提供了简单高效的方式来处理可变长度整数编码,特别适合协议实现和数据序列化场景。

完整示例Demo

下面是一个综合使用varinteger库的完整示例:

use varinteger::{encode, decode, decode_from_stream, VarInt, VLQ};
use std::io::Cursor;

// 自定义类型示例
#[derive(Debug, Default, PartialEq)]
struct CustomInt(i64);

impl VarInt for CustomInt {
    fn encode_var(self, dst: &mut [u8]) -> Result<usize, varinteger::EncodeError> {
        self.0.encode_var(dst)
    }

    fn decode_var(src: &[u8]) -> Result<(Self, usize), varinteger::DecodeError> {
        i64::decode_var(src).map(|(v, s)| (CustomInt(v), s))
    }
}

fn main() {
    // 基本编码解码演示
    basic_encoding_demo();
    
    // 流式处理演示
    stream_demo();
    
    // 自定义类型演示
    custom_type_demo();
}

fn basic_encoding_demo() {
    println!("\n=== 基本编码解码演示 ===");
    
    let numbers = [0u32, 1, 127, 128, 300, 65535, 1_000_000];
    
    for &num in &numbers {
        let mut buffer = [0u8; 5]; // u32最多需要5字节
        let bytes_used = encode(num, &mut buffer).unwrap();
        
        let (decoded, _) = decode::<u32>(&buffer[..bytes_used]).unwrap();
        
        println!("原始值: {:7} → 编码为: {:?} → 解码值: {}", 
            num, &buffer[..bytes_used], decoded);
    }
}

fn stream_demo() {
    println!("\n=== 流式处理演示 ===");
    
    // 准备包含多个varint的字节流
    let mut data = Vec::new();
    let numbers = [100u32, 200, 300, 400, 500];
    
    for &num in &numbers {
        let mut buffer = [0u8; 5];
        let bytes_used = encode(num, &mut buffer).unwrap();
        data.extend_from_slice(&buffer[..bytes_used]);
    }
    
    println!("编码后的字节流: {:?}", data);
    
    let mut cursor = Cursor::new(&data);
    let mut decoded_numbers = Vec::new();
    
    while cursor.position() < data.len() as u64 {
        match decode_from_stream::<u32, _>(&mut cursor) {
            Ok((num, _)) => decoded_numbers.push(num),
            Err(e) => {
                eprintln!("解码错误: {:?}", e);
                break;
            }
        }
    }
    
    println!("解码后的数字: {:?}", decoded_numbers);
}

fn custom_type_demo() {
    println!("\n=== 自定义类型演示 ===");
    
    let custom_numbers = [
        CustomInt(0),
        CustomInt(-1),
        CustomInt(42),
        CustomInt(-1000),
        CustomInt(1_000_000),
    ];
    
    for num in custom_numbers {
        let mut buffer = [0u8; 10]; // i64最多需要10字节
        let bytes_used = num.encode_var(&mut buffer).unwrap();
        
        let (decoded, _) = CustomInt::decode_var(&buffer[..bytes_used]).unwrap();
        
        println!("自定义类型: {:?} → 编码为: {:?} → 解码为: {:?}",
            num, &buffer[..bytes_used], decoded);
    }
}

这个完整示例展示了:

  1. 基本varint编码解码功能
  2. 流式处理多个varint
  3. 自定义类型实现VarInt trait
  4. 错误处理模式
  5. 缓冲区管理最佳实践

运行示例将输出各种操作的结果,帮助理解varinteger库的实际使用方式。

回到顶部