读取字节时填充用户提供的缓冲区的惯用方法是什么?

What is an idiomatic way to fill a user-supplied buffer when reading bytes?

Read::read returns 它实际读取的字节数,可以小于请求的缓冲区。在许多情况下,多次调用 read 以完全填充缓冲区是可以接受的。

我有这段代码,但看起来很笨拙:

use std::io::{self, Read};

fn read_complete<R>(mut rdr: R, buf: &mut [u8]) -> io::Result<()>
    where R: Read
{
    let mut total_read = 0;

    loop {
        let window = &mut buf[total_read..];
        let bytes_read = try!(rdr.read(window));

        // Completely filled the buffer
        if window.len() == bytes_read {
            return Ok(());
        }

        // Unable to read anything
        if bytes_read == 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to read complete buffer"));
        }

        // Partial read, continue
        total_read += bytes_read;
    }
}

fn main() {}

标准库中是否有一个函数可以为我抽象出这项工作?

This answer applies to versions of Rust before 1.6.0

据我所知还没有。

查看 byteorder crate's source,那里也定义了一个 read_all 方法:

fn read_full<R: io::Read + ?Sized>(rdr: &mut R, buf: &mut [u8]) -> Result<()> {
    let mut nread = 0usize;
    while nread < buf.len() {
        match rdr.read(&mut buf[nread..]) {
            Ok(0) => return Err(Error::UnexpectedEOF),
            Ok(n) => nread += n,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
            Err(e) => return Err(From::from(e))
        }
    }
    Ok(())
}

请注意,这处理中断的 IO 操作。

还有一个 proposed RFC,它是几个月前提交的,进入了最后的评论期,然后进行了足够的更改,以至于它被 out 的最后评论期和正在等待另一次复飞。

原来这出乎意料的复杂。 :P

由于 RFC mentioned in the other answer is accepted, implemented, and available in Rust 1.6.0, you can just use the Reader::read_exact() 方法:

try!(r.read_exact(&mut buf))

或者,使用 ? 运算符 introduced in Rust 1.13.0:

r.read_exact(&mut buf)?