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

kre*_*reo 4 stream rust

我正在编写一个处理 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
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是,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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但这看起来很古怪而且不优雅。有更好的解决方案吗?也许 Rust 标准库中有一个不同的工具比 更适合这里Cursor

She*_*ter 5

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

\n\n
fn handle(mut data: Cursor<&[u8]>) {\n    let len = data.get_ref().len();\n\n    while (data.position() as usize) < len - 1 {\n        if let Err(err) = handle_chunk(&mut data) {\n            eprintln!("Error while handling data: {}", err);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,您还没有显示任何需要Cursor. 很多时候,人们认为需要将 a 转换&[u8]为实现 的东西Read,但事实并非如此。Read实施用于&\'a [u8]

\n\n
use std::io::Read;\n\nfn handle(mut data: &[u8]) {\n    while !data.is_empty() {\n        if let Err(err) = handle_chunk(&mut data) {\n            eprintln!("Error while handling data: {}", err);\n        }\n    }\n}\n\nfn handle_chunk<R: Read>(mut data: R) -> Result<(), String> {\n    let mut b = [0; 10];\n    data.read_exact(&mut b).unwrap();\n    println!("Chunk: {:?}", b);\n    Ok(())\n}\n\nfn main() {\n    let d: Vec<u8> = (0..20).collect();\n    handle(&d)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

通过拥有mut data: &[u8]并使用&mut data,代码将更新切片变量以使其向前推进。但我们不能轻易倒退。

\n\n
\n

一种empty()方法

\n
\n\n

Rust 风格表示empty方法将是动词\xe2\x80\x94 这将删除数据(如果可能的话)。应该调用你想要的方法is_empty,如切片上所示。

\n