在这种情况下,我应该使用read_exact吗?Rust

qaxu7uf2  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(168)

我尝试在rust中实现FastCGI协议。当我遇到问题时,我问了一个关于stackoverflow(the question is this)的问题。正如你所看到的,我的问题的答案是这样的:
然后使用read_exact读取响应的头,提取其内容长度,并再次使用read_exact获取响应的内容:
我真的没有问题。但从那以后,我遇到了一些人(无论是在网上还是在现实生活中),他们说了一些非常类似的话:):
避免使用“exact”函数,因为它们可能会默默地吞下一些流内容,请参阅文档。
所以我的问题是。我应该在我的特定情况下使用read_exact吗?那些说不要使用read_exact的人是对的吗?为什么我应该占用它,或者为什么我占用它?如果你需要更多关于我的情况的上下文,所有的东西都在我在这篇文章开始时提出的问题中

4uqofj5v

4uqofj5v1#

你确定那些不鼓励使用read_exact的人指的是铁 rust 吗?在搜索这个的时候,我只能找到谈论其他语言的人。

使用read_exact应该没问题。

首先,我们可以看到,它不会读取超出文档中所需的字节数:
如果此函数返回错误,则不指定已读取的字节数,但读取的字节数绝不会超过完全填充缓冲区所需的字节数。
使用read_exact时我们丢失的唯一信息是我们在遇到错误和任何ErrorKind::Interrupted错误时读取的确切字节数。然而,在阅读中断错误的文档时,我们可以看到它如下所述。
此操作已中断。
中断的操作通常可以重试。
除非您明确使用了某个库,该库声明在出现中断错误后继续读取之前需要执行其他操作,否则您可以假定此操作可以重试,直到读取完字节或出现指示无法再阅读的错误。如果您在通用std::io::Read输入上使用read_exact,可以安全地假设调用者已经适当地处理了这个用例。
您也可以通过阅读read_exact的标准库实现来验证这一点是否正确。我还没有看到任何主流库选择为read_exact提供自己的实现,但理论上这是可能的。然而,他们仍然应该遵守read_exact的文档,这会产生与之前相同的结论。

pub trait Read {
    #[stable(feature = "read_exact", since = "1.6.0")]
    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
        default_read_exact(self, buf)
    }

    // etc...
}

pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
    while !buf.is_empty() {
        match this.read(buf) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(error::const_io_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}
nwlqm0z1

nwlqm0z12#

我知道只有一种情况read_exact可能会丢失数据,那就是如果出现错误(Interrupted除外)。在这种情况下,在错误发生之前已经读取的数据将丢失,但在大多数情况下,由于数据不完整,您将无法对该数据执行任何操作,而只能处理错误本身。

相关问题