如何检查std::io::Cursor是否有未消耗的数据?

4
我正在编写一个涉及TCP套接字的低级网络应用程序,通常需要处理二进制数据流。当有一些数据可用时,我将其读入u8数组中,然后包装到std::io::Cursor<&[u8]>中,并将其传递给处理程序。在处理程序中,我经常需要知道Cursor中是否还有更多数据。

假设handle函数接收数据,然后使用handle_chunk函数分块处理它们。为简单起见,假定块大小固定为10个字节;如果数据大小不可被10整除,则会出现错误。这个简单的逻辑可以按以下方式实现:

fn handle(mut data: Cursor<&[u8]>) {
    while !data.empty() {
        if let Err(err) = handle_chunk(&mut data) {
            eprintln!("Error while handling data: {}", err);
        }
    }
}

fn handle_chunk(data: &mut Cursor<&[u8]>) -> Result<(), String> {
    // Returns Err("unexpected EOF".to_string()) if chunk is incomplete
    // ...
}

然而,Cursor没有一个empty()方法或其他可以告诉您是否有更多数据要处理的方法。我能想到的有效解决方案是:

fn handle(data: Cursor<&[u8]>) {
    let data = data.into_inner();
    let len = data.len();
    let mut data = Cursor::new(data);

    while (data.position() as usize) < len - 1 {
        if let Err(err) = handle_chunk(&mut data) {
            eprintln!("Error while handling data: {}", err);
        }
    }
}

这看起来很不专业和不优雅。有更好的解决方案吗?也许Rust标准库中有一个不同的工具比Cursor更适合这里?
1个回答

5

您可以使用Cursor::get_ref来简化代码,以避免分解输入并将其重新组合:

fn handle(mut data: Cursor<&[u8]>) {
    let len = data.get_ref().len();

    while (data.position() as usize) < len - 1 {
        if let Err(err) = handle_chunk(&mut data) {
            eprintln!("Error while handling data: {}", err);
        }
    }
}

现在,你还没有展示需要使用 Cursor 的代码。许多时候,人们认为需要将 &[u8] 转换成实现了 Read 接口的东西,但其实不需要。 Read 接口已经被实现在 &'a [u8] 上:

use std::io::Read;

fn handle(mut data: &[u8]) {
    while !data.is_empty() {
        if let Err(err) = handle_chunk(&mut data) {
            eprintln!("Error while handling data: {}", err);
        }
    }
}

fn handle_chunk<R: Read>(mut data: R) -> Result<(), String> {
    let mut b = [0; 10];
    data.read_exact(&mut b).unwrap();
    println!("Chunk: {:?}", b);
    Ok(())
}

fn main() {
    let d: Vec<u8> = (0..20).collect();
    handle(&d)
}

通过使用 &mut data 并将 mut data: &[u8] 引用传递,代码将直接更新切片变量以使其前进。但是,我们无法轻松地向后移动。

empty() 方法

Rust 风格表明,empty 方法应该是一个动词——这会删除数据(如果可能的话)。您想要的方法应该被称为 is_empty,如在切片中所见。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接