Если BufReader берет на себя управление потоком, как я могу читать и писать строки на нем?

Я хочу прочитать строку из TCPStream, написать еще одну строку, а затем повторить. Проблема в том, что BufReader::new берет на себя ответственность за мою переменную TCPStream:

let stream = ...; // TCPStream

let reader = BufReader::new(stream); // moved its value

// can't use stream here anymore

Что такое простое решение?

Ответ 1

Решение: используйте ссылки.

let mut stream = ...;
let reader = BufReader::new(&stream);
let writer = BufWriter::new(&stream);

Объяснение

Если мы более внимательно посмотрим на BufReader::new, то увидим, что он принимает аргумент inner типа R, где R - это просто любой тип, который реализует Read:

impl<R: Read> BufReader<R> {
    pub fn new(inner: R) -> BufReader<R> { ... }
}

Затем мы взглянем на Read и увидим эту реализацию:

impl<'a> Read for &'a TcpStream

Итак, мы можем просто передать ссылку на функцию new следующим образом:

let reader = BufReader::new(&stream);

Мы сделаем то же самое для BufWriter и Write и увидим, что эта реализация действительно существует:

impl<'a> Write for &'a TcpStream

Итак, мы снова можем использовать неизменную ссылку для создания BufWriter.

Ответ 2

У вас есть несколько возможностей:

  • не используйте BufReader
  • временно заимствовать поток из BufReader с помощью get_mut
  • полностью отбросить BufReader и восстановить поток, используя into_inner

Я бы лично посоветовал не использовать BufReader, если вам действительно не нужно буферизовать ввод; для одной строки это не кажется нужным.

В противном случае, если вы закончили буферизацию, вы можете восстановить базовый поток, а если нет, вы можете временно его заблокировать.

Предостережение. Имейте в виду, что буферизация BufReader буферизует, поэтому, когда вы занимаете/восстанавливаете внутренний поток, вы коротко замыкаете буферные данные; для чтения этого вопроса, в вашем случае (написании) это должно быть хорошо.