BufReader and Writer

I've been coding for about 3 weeks in Rust and loving it. I've drafted a few questions here, but found the answer moments before clicking the Create Topic button. But this one has me stumped.

I have a pipe. I want to call pipe.read_line(), pipe.read_exact(), and pipe.write_all(). To call read_line(), I pass the pipe to a BufReader. But BufReader then owns the pipe so I see no way to later call pipe.write_all().

Here's my code:

use crate::server::Server;
use std::ffi::OsString;
use named_pipe::PipeClient;
use std::io::{Read, BufRead, BufReader, Write};
use anyhow::Context;
use crate::bytevec::ByteVec;

impl Server {
    pub fn main(pipe_name: &str) -> anyhow::Result<()> {
        let mut server = Server{};
        let pipe_name = OsString::from(pipe_name);
        let mut pipe = BufReader::new(PipeClient::connect(pipe_name)?);
        let mut line = String::new();
        let bytes_read = pipe.read_line(&mut line)?;
        if 0 == bytes_read {
            return Ok(());
        }
        let message_length: usize = line.trim().parse().context(
            "expected the message length")?;
        let mut buffer = ByteVec::new();
        buffer.0.resize(message_length, 0);
        pipe.read_exact(&mut buffer.0)?;
        let result = server.serve(buffer);
        pipe.write_all(&result.0)?;
        Ok(())
    }
}

The compiler complains. I understand the error 100%. I don't understand how to practically work around it.

error[E0599]: no method named `write_all` found for struct `std::io::BufReader<named_pipe::PipeClient>` in the current scope
  --> src\server\winmain.rs:24:14
   |
24 |         pipe.write_all(&result.0)?;
   |              ^^^^^^^^^ method not found in `std::io::BufReader<named_pipe::PipeClient>`

warning: unused import: `Write`
 --> src\server\winmain.rs:4:41
  |
4 | use std::io::{Read, BufRead, BufReader, Write};
  |                                         ^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

Thanks for your help!

One way to accomplish it in this case is to get the PipeClient back out of the BufReader which can be done by changing the last line to either

pipe.into_inner().write_all(&result.0)?;

or

pipe.get_mut().write_all(&result.0)?;

The first one takes the pipe out of the BufReader and the second one just borrows the pipe from BufReader

Well that's certainly annoying. One would think that the bufread/write would also implement the other trait and just pass it through. You will probably have to use get_mut or implement it a BufReaderWriter yourself.

Thank you! That looks much more idiomatic than what I tried.

Thanks! I did indeed implement my own BufReaderWriter, but I'll also give drewkett's suggestion a try.

This would be nice for sockets, but it would cause bugs in cases like BufWriter<File>, when unflushed data in the BufWriter can affect the Read output. :frowning:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.