Rust LEB128编解码库leb128-tokio的使用:高效处理可变长度整数编码与异步流
// 示例代码:使用leb128-tokio进行LEB128编码和解码
use leb128_tokio::{read, write};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 创建内存缓冲区
let mut buffer = Vec::new();
// 编码示例:将多个整数编码为LEB128格式
write::signed(&mut buffer, -12345).await?;
write::unsigned(&mut buffer, 67890).await?;
// 创建异步读取器
let mut reader = &buffer[..];
// 解码示例:从缓冲区读取LEB128编码的整数
let decoded_signed: i64 = read::signed(&mut reader).await?;
let decoded_unsigned: u64 = read::unsigned(&mut reader).await?;
println!("Decoded signed: {}", decoded_signed);
println!("Decoded unsigned: {}", decoded_unsigned);
Ok(())
}
// 完整示例:使用leb128-tokio处理异步流中的可变长度整数编码
use leb128_tokio::{read, write};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 连接到服务器(示例中使用本地回环地址)
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
// 编码并发送数据
let numbers = vec![123, 4567, 89012, -345, -6789];
for &num in &numbers {
if num >= 0 {
write::unsigned(&mut stream, num as u64).await?;
} else {
write::signed(&mut stream, num as i64).await?;
}
}
// 刷新缓冲区确保所有数据都已发送
stream.flush().await?;
// 从流中读取并解码数据
let mut received_numbers = Vec::new();
while let Ok(num) = read::signed(&mut stream).await {
received_numbers.push(num);
}
println!("Received numbers: {:?}", received_numbers);
Ok(())
}
// 高级示例:使用leb128-tokio进行批量编码和解码
use leb128_tokio::{read, write};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use bytes::{BytesMut, BufMut};
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 创建字节缓冲区
let mut buffer = BytesMut::new().writer();
// 批量编码多个整数
let numbers_to_encode = vec![1, 127, 128, 255, 256, 65535, 65536];
for &num in &numbers_to_encode {
write::unsigned(&mut buffer, num).await?;
}
// 获取编码后的字节数据
let encoded_data = buffer.into_inner().freeze();
println!("Encoded data length: {} bytes", encoded_data.len());
// 创建读取器并批量解码
let mut reader = encoded_data.reader();
let mut decoded_numbers = Vec::new();
while let Ok(num) = read::unsigned(&mut reader).await {
decoded_numbers.push(num);
}
println!("Original numbers: {:?}", numbers_to_encode);
println!("Decoded numbers: {:?}", decoded_numbers);
// 验证数据一致性
assert_eq!(numbers_to_encode, decoded_numbers);
println!("Data verification successful!");
Ok(())
}
// 错误处理示例:使用leb128-tokio进行健壮的编解码
use leb128_tokio::{read, write};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Leb128Error {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Decoding error: invalid LEB128 format")]
DecodingError,
}
#[tokio::main]
async fn main() -> Result<(), Leb128Error> {
let mut buffer = Vec::new();
// 安全编码
write::unsigned(&mut buffer, 42).await?;
write::signed(&mut buffer, -100).await?;
// 安全解码
let mut reader = &buffer[..];
let first: u64 = read::unsigned(&mut reader).await.map_err(|_| Leb128Error::DecodingError)?;
let second: i64 = read::signed(&mut reader).await.map_err(|_| Leb128Error::DecodingError)?;
println!("Decoded: {}, {}", first, second);
// 处理流结束情况
match read::unsigned(&mut reader).await {
Ok(num) => println!("Extra number: {}", num),
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
println!("Reached end of stream as expected");
}
Err(e) => return Err(Leb128Error::Io(e)),
}
Ok(())
}
1 回复
Rust LEB128编解码库leb128-tokio的使用指南
概述
leb128-tokio是一个专门为Rust异步环境设计的LEB128(Little Endian Base 128)编解码库。它提供了高效的可变长度整数编码解决方案,特别适合处理网络协议、序列化格式和异步数据流中的整数编码需求。
主要特性
- 完整的LEB128编码和解码支持
- 与tokio异步运行时无缝集成
- 零拷贝解码操作
- 支持有符号和无符号整数类型
- 高效的错误处理机制
安装方法
在Cargo.toml中添加依赖:
[dependencies]
leb128-tokio = "0.3"
tokio = { version = "1.0", features = ["full"] }
基本使用方法
编码示例
use leb128_tokio::write::encode_u64;
use tokio::io::BufWriter;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut buffer = Vec::new();
let mut writer = BufWriter::new(&mut buffer);
// 编码无符号整数
encode_u64(&mut writer, 624485).await?;
writer.flush().await?;
println!("编码结果: {:?}", buffer);
Ok(())
}
解码示例
use leb128_tokio::read::decode_u64;
use tokio::io::BufReader;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let data = vec![0xE5, 0x8E, 0x26]; // 624485的LEB128编码
let mut reader = BufReader::new(&data[..]);
// 解码无符号整数
let value = decode_u64(&mut reader).await?;
println!("解码结果: {}", value); // 输出: 624485
Ok(())
}
异步流处理示例
从异步流中读取LEB128编码数据
use leb128_tokio::read::decode_u64_stream;
use tokio_stream::StreamExt;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 模拟异步数据流
let encoded_data = vec![0xE5, 0x8E, 0x26, 0x7F];
let mut stream = tokio_stream::iter(encoded_data);
while let Some(byte) = stream.next().await {
// 在实际应用中,这里会构建完整的LEB128字节序列
// 然后使用decode_u64_stream进行解码
print!("{:02X} ", byte);
}
Ok(())
}
批量编码示例
use leb128_tokio::write::encode_u64;
use tokio::io::AsyncWriteExt;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let numbers = [624485, 127, 128, 255, 16384];
let mut buffer = Vec::new();
let mut writer = tokio::io::BufWriter::new(&mut buffer);
for &num in &numbers {
encode_u64(&mut writer, num).await?;
}
writer.flush().await?;
println!("批量编码结果: {:?}", buffer);
Ok(())
}
错误处理
use leb128_tokio::read::decode_u64;
use tokio::io::BufReader;
#[tokio::main]
async fn main() {
let invalid_data = vec![0x80, 0x80, 0x80, 0x80, 0x80]; // 无效的编码序列
let mut reader = BufReader::new(&invalid_data[..]);
match decode_u64(&mut reader).await {
Ok(value) => println!("解码值: {}", value),
Err(e) => eprintln!("解码错误: {}", e),
}
}
性能建议
- 使用BufReader/BufWriter包装I/O对象以减少系统调用
- 批量处理数据时考虑使用缓冲策略
- 对于高频次编码操作,可预分配足够大小的缓冲区
注意事项
- 确保正确处理字节序问题
- 注意整数溢出和边界情况
- 在异步上下文中使用时注意await点的正确放置
这个库特别适合需要处理Protocol Buffers、WebAssembly二进制格式或其他使用LEB128编码格式的异步应用场景。
完整示例代码
use leb128_tokio::{write::encode_u64, read::decode_u64};
use tokio::io::{BufReader, BufWriter, AsyncWriteExt};
use tokio_stream::StreamExt;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 编码示例
println!("=== 编码示例 ===");
let mut encode_buffer = Vec::new();
let mut writer = BufWriter::new(&mut encode_buffer);
// 编码无符号整数624485
encode_u64(&mut writer, 624485).await?;
writer.flush().await?;
println!("编码结果: {:?}", encode_buffer);
// 解码示例
println!("\n=== 解码示例 ===");
let mut reader = BufReader::new(&encode_buffer[..]);
let decoded_value = decode_u64(&mut reader).await?;
println!("解码结果: {}", decoded_value);
// 批量编码示例
println!("\n=== 批量编码示例 ===");
let numbers = [624485, 127, 128, 255, 16384];
let mut batch_buffer = Vec::new();
let mut batch_writer = BufWriter::new(&mut batch_buffer);
for &num in &numbers {
encode_u64(&mut batch_writer, num).await?;
}
batch_writer.flush().await?;
println!("批量编码结果: {:?}", batch_buffer);
// 异步流处理示例
println!("\n=== 异步流处理示例 ===");
let encoded_data = vec![0xE5, 0x8E, 0x26, 0x7F];
let mut stream = tokio_stream::iter(encoded_data);
print!("流数据: ");
while let Some(byte) = stream.next().await {
print!("{:02X} ", byte);
}
println!();
// 错误处理示例
println!("\n=== 错误处理示例 ===");
let invalid_data = vec![0x80, 0x80, 0x80, 0x80, 0x80];
let mut error_reader = BufReader::new(&invalid_data[..]);
match decode_u64(&mut error_reader).await {
Ok(value) => println!("解码值: {}", value),
Err(e) => eprintln!("解码错误: {}", e),
}
Ok(())
}