gpt4 book ai didi

reference - 为什么我可以将不可变引用传递给 BufReader,而不是可变引用?

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

<分区>

我正在编写一个简单的基于 TCP 的回显服务器。当我尝试使用 BufReaderBufWriter 读取和写入 TcpStream 时,我发现传递 TcpStreamBufReader::new() 按值移动它的所有权,这样我就不能将它传递给 BufWriter。然后,我在this thread找到了答案。解决问题:

fn handle_client(stream: TcpStream) {
let mut reader = BufReader::new(&stream);
let mut writer = BufWriter::new(&stream);

// Receive a message
let mut message = String::new();
reader.read_line(&mut message).unwrap();

// ingored
}

这很简单而且有效。但是,我不太明白为什么这段代码有效。为什么我可以将不可变引用传递给 BufReader::new(),而不是可变引用?

可以找到整个程序here .

更多详情

在上面的代码中,我使用了reader.read_line(&mut message)。于是我打开了Rust标准库中BufRead的源码,看到了这个:

fn read_line(&mut self, buf: &mut String) -> Result<usize> {
// ignored
append_to_string(buf, |b| read_until(self, b'\n', b))
}

在这里我们可以看到它将自身(在我的例子中可能是一个 &mut BufReader)传递给 read_until()。接下来,我在同一个文件中找到了以下代码:

fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
-> Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = match r.fill_buf() {
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e)
};
match memchr::memchr(delim, available) {
Some(i) => {
buf.extend_from_slice(&available[..i + 1]);
(true, i + 1)
}
None => {
buf.extend_from_slice(available);
(false, available.len())
}
}
};
r.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}

这部分有两个地方使用了BufReader:r.fill_buf()r.consume(used)。我以为 r.fill_buf() 是我想看到的。因此,我去 Rust 标准库中的 BufReader 的代码中找到了这个:

fn fill_buf(&mut self) -> io::Result<&[u8]> {
// ignored
if self.pos == self.cap {
self.cap = try!(self.inner.read(&mut self.buf));
self.pos = 0;
}
Ok(&self.buf[self.pos..self.cap])
}

它似乎使用 self.inner.read(&mut self.buf)self.inner 读取数据。然后,我们看一下BufReaderBufReader::new() 的结构:

pub struct BufReader<R> {
inner: R,
buf: Vec<u8>,
pos: usize,
cap: usize,
}

// ignored
impl<R: Read> BufReader<R> {
// ignored
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}

// ignored
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
BufReader {
inner: inner,
buf: vec![0; cap],
pos: 0,
cap: 0,
}
}

// ignored
}

从上面的代码我们可以知道inner是一个实现了Read的类型。在我的例子中,inner 可能是一个 &TcpStream

我知道 Read.read() 的签名是:

fn read(&mut self, buf: &mut [u8]) -> Result<usize>

这里需要一个mutable 引用,但我只借给它一个immutable 引用。当程序在 fill_buf() 中到达 self.inner.read() 时,这应该是个问题吗?

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