写入Rust的Write_all的详细方法

时间:2016-03-27 08:52:15

标签: io rust

我创建了一个帮助程序,将切片中的所有数据写入Write类型,但它非常详细且容易出错。我想知道是否有更好的方法可以忽略ErrorKind::Interrupted(来自EINTR)。

fn _write_all<OutputType> (w : &mut OutputType, buf : &[u8]) -> Result<(), io::Error>
where OutputType: Write {
    let mut total_written : usize = 0;
    while total_written < buf.len() {
        match w.write(&buf[total_written..]) {
            Err(e) => {
                match e.kind() {
                    ErrorKind::Interrupted => continue,
                    _ => return Err(e),
                }
            },
            Ok(cur_written) => {
                if cur_written == 0 {
                     return Err(Error::new(ErrorKind::UnexpectedEof, "Write EOF"));
                }
                total_written += cur_written;
            }
        }
    }
    Ok(())
}

我感觉大多数用户将使用try!宏而忽略ErrorKind::Interrupted,并且当程序因为系统忙EINTR而开始失败时会感到惊讶。

如果有更好的方式来写这个,我会非常渴望听到它。

输入也会出现类似的问题,包括嵌套匹配。

对于记录,RFC 517 (IO / OS Reform)表示write_all忽略EINTR个错误,但the documentation for Write::write_all提到write_all返回遇到的第一个错误,需要类似的循环如上所述。

1 个答案:

答案 0 :(得分:3)

文档错误。如果std::io::Write::write_all返回std::io::Write::writeErrorKind::Interrupted 会重新重试in the source

fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
    while !buf.is_empty() {
        match self.write(buf) {
            Ok(0) => return Err(Error::new(ErrorKind::WriteZero,
                                           "failed to write whole buffer")),
            Ok(n) => buf = &buf[n..],
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}