mod envelope;
pub mod framing;
mod stdio;
use std::future::Future;
use std::io;
use thiserror::Error;
use crate::raw::RawMessage;
use crate::server::LanguageServer;
pub use stdio::{StdioReader, StdioTransport, StdioWriter};
#[derive(Debug, Error)]
pub enum TransportError {
#[error("io error: {0}")]
Io(#[from] io::Error),
#[error("connection closed by peer")]
Closed,
#[error("malformed message: {0}")]
Malformed(String),
#[error("message exceeds size limit ({length} > {limit} bytes)")]
OversizedMessage { length: usize, limit: usize },
#[error("serialization error: {0}")]
Serde(#[from] serde_json::Error),
}
pub trait Transport: Send + 'static {
type Reader: TransportReader;
type Writer: TransportWriter;
fn split(self) -> (Self::Reader, Self::Writer);
}
pub trait TransportReader: Send + 'static {
fn recv(
&mut self,
) -> impl Future<Output = std::result::Result<RawMessage, TransportError>> + Send;
}
pub trait TransportWriter: Send + 'static {
fn send(
&mut self,
msg: RawMessage,
) -> impl Future<Output = std::result::Result<(), TransportError>> + Send;
fn shutdown(self) -> impl Future<Output = std::result::Result<(), TransportError>> + Send;
}
pub fn stdio<S: LanguageServer>(server: S) -> StdioBuilder<S> {
StdioBuilder {
server,
concurrency_limit: crate::DEFAULT_CONCURRENCY_LIMIT,
}
}
pub struct StdioBuilder<S> {
server: S,
concurrency_limit: usize,
}
impl<S: LanguageServer> StdioBuilder<S> {
pub fn concurrency_limit(mut self, limit: usize) -> Self {
self.concurrency_limit = limit;
self
}
pub async fn serve(self) -> crate::Result<()> {
let transport = StdioTransport::new();
match crate::dispatcher::run(self.server, transport, self.concurrency_limit).await? {
crate::dispatcher::Outcome::TransportClosed => Ok(()),
crate::dispatcher::Outcome::Exit(code) => std::process::exit(code),
}
}
}