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
- Locked stdin for asynchronous read.
- Locked stdout for asynchronous read.