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;
}
}
特点
- 纯内存操作,不涉及IO
- 简单的API:encode和decode两个主要函数
- 高效的可变长度整数编码/解码
- 支持大整数(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);
}
性能提示
-
对于已知最大值的场景,可以预分配足够大的缓冲区:
// u32最多需要5字节 let mut buffer = [0u8; 5];
-
批量处理时,考虑重用缓冲区以减少分配。
-
对于网络传输,考虑结合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);
}
}
这个完整示例展示了:
- 基本varint编码解码功能
- 流式处理多个varint
- 自定义类型实现VarInt trait
- 错误处理模式
- 缓冲区管理最佳实践
运行示例将输出各种操作的结果,帮助理解varinteger库的实际使用方式。