gpt4 book ai didi

loops - 是否可以编写一个调用 BufRead::fill_buf 的函数,直到中断错误不再发生而不使用 unsafe?

转载 作者:行者123 更新时间:2023-11-29 08:31:03 25 4
gpt4 key购买 nike

是否可以编写一个调用BufRead::fill_buf 直到io::ErrorKind::Interrupted 的函数?不使用 unsafe 就不再发生?

对于不安全的代码,它是:

use std::{
io::{self, BufRead},
slice,
};

fn fill_buf_and_ignore_interrupts(reader: &mut impl BufRead) -> io::Result<&[u8]> {
let (buf_ptr, buf_len) = loop {
match reader.fill_buf() {
Ok(buf) => (buf.as_ptr(), buf.len()),
Err(e) => {
if e.kind() != io::ErrorKind::Interrupted {
return Err(e);
}
}
}
};
Ok(unsafe { slice::from_raw_parts(buf_ptr, buf_len) })
}

如果我尝试returnbreak Ok(buf),我从借用检查器中得到一个错误:

error[E0499]: cannot borrow `*reader` as mutable more than once at a time
--> src/lib.rs:8:15
|
6 | fn fill_buf_and_ignore_interrupts(reader: &mut impl BufRead) -> io::Result<&[u8]> {
| - let's call the lifetime of this reference `'1`
7 | let (buf_ptr, buf_len) = loop {
8 | match reader.fill_buf() {
| ^^^^^^ mutable borrow starts here in previous iteration of loop
9 | Ok(buf) => return Ok(buf),
| ------- returning this value requires that `*reader` is borrowed for `'1`

我试图用递归替换循环,但错误仍然存​​在。我也尝试过使用 #![feature(nll​​)],但它也不起作用。

最佳答案

您不能,也不应该出于下面突出显示的原因(它们与引用返回或不安全无关)。 fill_buf由于文档中的一个重要警告,它并不像您认为的那样工作:

Returns the contents of the internal buffer, filling it with more data from the inner reader if it is empty.

换句话说,如果 trait 正确实现并遵循文档中规定的契约,则在没有 consume 的情况下对 fill_buf 的后续调用将是空操作。因此,如果您在调用 fill_buf 的任何地方忘记了该要求,那么只做一个而没有另一个会充满风险。

两种解决方案:

  • 如果您要读到流的末尾(这是 BufReader 在很多其他语言中所做的),只需 BufRead::read_to_end() , BufRead::read_line()BufRead::read_until()。如果你能识别一个分隔符,read_until 可以很容易地被处理成一个可迭代的结构
  • 如果您尝试查看数据并可能等待更多数据,则需要实现自己的特征。这不是经常需要的,因为大多数试图查看流的人都在寻找 Pattern 或单个字节,BufRead 涵盖了它。

作为一个简短的总结,fill_buf 并没有按照您的想法行事,您不需要多次调用它而不消耗缓冲区的内部状态。如果您不想这样做,那么 BufRead 的低级方法不是完成这项工作的工具。

关于loops - 是否可以编写一个调用 BufRead::fill_buf 的函数,直到中断错误不再发生而不使用 unsafe?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57832526/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com