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),
    }
}

性能建议

  1. 使用BufReader/BufWriter包装I/O对象以减少系统调用
  2. 批量处理数据时考虑使用缓冲策略
  3. 对于高频次编码操作,可预分配足够大小的缓冲区

注意事项

  • 确保正确处理字节序问题
  • 注意整数溢出和边界情况
  • 在异步上下文中使用时注意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(())
}
回到顶部