Treat Stdin as an async Stream?

Is there a way to treat an std::io::Stdin as an async Stream of lines?
I would like to write code like this

let stdin = stdin();
while let Some(line) = stdin.next().await { 
    ...
}

in an async function.

What I am trying to do is to intersperse an update stream from the telegram_bot crate with a stream of command line inputs, however I am not sure how to implement Stream for Stdin.
I know there is async_std::io::Stdin, which provides async functions of Stdin, but it doesn't implement Stream for some reason.

Would be glad if someone could give me some advice on this.

tl;dr

use async_std::io::prelude::*;
use async_std::io::BufReader;

let mut stdin = BufReader::new(stdin());
let mut lines = stdin.lines();
while let Some(line) = lines.next().await {
    ...
}

The async_std::io::StdIn is not impl Stream for the same reason as the std::io::Stdin is not impl Iterator. They're byte stream like tcp stream or files, but handling each bytes individually by default would results too much overhead.

So the stdlib provides a set of traits to handle byte streams, namely std::io::{Read, BufRead, Write}. The .lines() method is defined under the BufRead trait since line separation cannot be made efficiently without internal buffer.

Async world has similar traits. But the ::futures crate tends to separate the base traits for implementors and the extension traits for consumers. For example it has trait AsyncRead with only core methods consumers hardly ever ever call directly, and trait AsyncReadExt with bunch of utility methods and blanket impl.

::async_std tries to hide this complexity in its docs. So it advertises to use async_std::io::prelude::*; which imports all the base and ext traits, and just use the ext methods directly.

3 Likes

Perfect, thanks a lot. Sometimes it is kind of hard to find the function you are looking for, because it is implemented through a trait and is not shown by the rust docs. But BufReadExt::lines returns Lines, which does implement Stream! Exactly what I was missing.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.