async-rs / async-rs/async-std

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

Open
#778 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Rust
Stars
4.1k
Forks
339
PR merge metrics
No merged PRs in 30d

Description

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

```rust
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);
}
});
}
```

```txt
this is
a multi line

file
```

Results in:
```sh
$ 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:

```rust
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.