stdio
and Unix only.Expand description
Utilities to deal with stdin/stdout communication channel for Language Servers.
Typically Language Servers serves on stdin/stdout by default. But generally they cannot be read
or written asynchronously usually, due to technical reasons.
(Eg. tokio::io::stdin
delegates reads
to blocking threads.)
This mod defines PipeStdin
and PipeStdout
for only stdin/stdout with pipe-like
backends, which actually supports asynchronous reads and writes. This currently means one of:
- FIFO pipes. Eg. named pipes mkfifo(3) and unnamed pipes pipe(2).
- Sockets. Eg. TCP connections and UNIX domain sockets unix(7).
- Character devices. Eg. tty(4) or pty(7).
When calling PipeStdin::lock
, it locks the stdin using std::io::stdin
, set its mode to
asynchronous, and exposes an a raw Read
interface bypassing the std’s buffer.
§Caveats
Since PipeStd{in,out}
bypass the std’s internal buffer. You should not leave any data in that
buffer (via std::io::stdin
, print!
-like macros and etc.). Otherwise they will be
ignored during PipeStd{in,out}
operations, which is typically a logic error.
§Asynchrous I/O drivers
§async-io
Wrapping PipeStd{in,out}
inside async_io::Async<T>
works. This should also work for other
drivers with a similar generic asynchronous adapter interface.
For async-io
>= 2, feature async-io
should be enabled to let Async<PipeStd{in,out}>
implements Async{Read,Write}
. async-io
< 2 does not require it to work.
See more details in: https://github.com/smol-rs/async-io/pull/142
use futures::AsyncWriteExt;
let mut stdout = async_io::Async::new(async_lsp::stdio::PipeStdout::lock()?)?;
// For `async-io` >= 2, this requires `async-io` feature to work.
stdout.write_all(b"never spawns blocking tasks").await?;
// This always work.
(&stdout).write_all(b"never spawns blocking tasks").await?;
§tokio
There are methods PipeStd{in,out}::{lock,try_into}_tokio
gated under feature tokio
to
work with tokio
runtime. The returned type implements corresponding
tokio::io::Async{Read,Write}
interface.
use tokio::io::AsyncWriteExt;
let mut stdout = async_lsp::stdio::PipeStdout::lock_tokio()?;
stdout.write_all(b"never spawns blocking tasks").await?;
Structs§
- Pipe
Stdin - Locked stdin for asynchronous read.
- Pipe
Stdout - Locked stdout for asynchronous read.