私は単純なTCPベースのエコーサーバを作成しています。 BufReader
とBufWriter
を使用してTcpStream
に読み書きしようとすると、TcpStream
をBufReader::new()
に渡すと所有権が移動し、BufWriter
に渡すことができませんでした。なぜ可変参照ではなく、BufReaderへの不変参照を渡すだけですか?
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
}
これはシンプルであり、それは動作します:その後、私は問題を解決this threadで答えを見つけました。しかし、私はこのコードがなぜ機能するのかを理解できません。変更可能な参照ではなく、BufReader::new()
への不変参照を渡すのはなぜですか?
プログラム全体はhereです。上記のコードで
詳細
、Iはreader.read_line(&mut message)
を用います。だから私は錆標準ライブラリにBufRead
のソースコードを開いて、この見た:ここ
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
// ignored
append_to_string(buf, |b| read_until(self, b'\n', b))
}
を我々はそれがread_until()
に(私の場合は&mut BufReader
てもよい)、自己を渡していることがわかります。次に、私は同じファイルに次のコードを見つけました:r.fill_buf()
とr.consume(used)
:この部分で
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
を使用して2つの場所があります。私はr.fill_buf()
が私が見たいと思っていたと思った。したがって、私は錆標準ライブラリにBufReader
のコードに行って、これを見つけた:それはself.inner
からデータを読み取るためにself.inner.read(&mut self.buf)
を使用するように
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])
}
に思えます。その後、我々はBufReader
の構造を見て、BufReader::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>
ここは可変参照が必要ですが、私はそれを不変参照を貸しました。これは、self.inner.read()
がfill_buf()
に達すると問題になるのでしょうか?
で[なぜそれが読んで実現することが可能であるの重複ファイルへの不変参照?](http://stackoverflow.com/q/31503488/155423)。 – Shepmaster
@Shepmaster私は当初、TcpStreamがFileとは異なる方法で動作すると考えました。しかし、Lukas Kalbertodtの答えを読んだ後、私は突然、その背後にある考え方は同じであることに気付きました。あなたのリンクをありがとう。 –