async-std icon indicating copy to clipboard operation
async-std copied to clipboard

Stdin read_line doesn't really read lines (when used like in the example)

Open internetionals opened this issue 4 years ago • 0 comments

When you write a simple consumer and feed it an entire file of multiple lines over stdin the behavior is not as expected:

fn main() {
  async_std::task::block_on(async {
    let mut line = String::new();
    let stdin = async_std::io::stdin();
    loop {
      stdin.read_line(&mut line).await.unwrap();
      println!("read({})", line);
    }
  });
}
this is
a multi line

file

Results in:

$ cargo run < test.txt | head -n 30
read(this is
)
read(this is
a multi line
)
read(this is
a multi line

)
read(this is
a multi line

file
)
read(this is
a multi line

file
)
read(this is
a multi line

file
)
read(this is
a multi line

file
)
read(this is
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', src/libstd/io/stdio.rs:805:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I've found that this variant works correctly, but is not as the example suggests this API should be used. So it's either a documentation or an implementation bug:

fn main() {
    async_std::task::block_on(async {
        let stdin = async_std::io::stdin();
        let mut buffer = String::new();
        loop {
            match stdin.read_line(&mut buffer).await {
                Ok(0) => {
                    // EOF
                    break;
                },
                Ok(length) => {
                    let line = buffer.get(0..length).unwrap();
                    eprintln!("read({})", line);
                    buffer.replace_range(0..length, "");
                },
                Err(err) => {
                    eprintln!("Error reading from stdin: {}", err);
                    break;
                }
            }
        }
    });
}

This behaviour was seen with async-std 1.5.0 on both macOS and Arch Linux.

internetionals avatar May 14 '20 09:05 internetionals