use eyre::eyre;
use futures::{Sink, SinkExt, Stream, StreamExt};
use super::message::WireMessage;
use super::traits::{MessageStream, StreamError};
pub trait Transport<SinkItem, Item>
where
Self: Stream<Item = Result<Item, <Self as Sink<SinkItem>>::Error>>,
Self: Sink<SinkItem, Error = <Self as Transport<SinkItem, Item>>::TransportError>,
{
type TransportError: std::error::Error + Send + Sync + 'static;
}
impl<T, SinkItem, Item, E> Transport<SinkItem, Item> for T
where
T: ?Sized + Stream<Item = Result<Item, E>> + Sink<SinkItem, Error = E>,
E: std::error::Error + Send + Sync + 'static,
{
type TransportError = E;
}
pub struct TransportStream<T>(pub T);
impl<T> TransportStream<T> {
pub fn new(transport: T) -> Self {
Self(transport)
}
pub fn into_inner(self) -> T {
self.0
}
}
#[async_trait::async_trait(?Send)]
impl<T> MessageStream for TransportStream<T>
where
T: Transport<WireMessage, WireMessage> + Unpin + Send,
{
async fn send(&mut self, msg: WireMessage) -> Result<(), StreamError> {
SinkExt::send(&mut self.0, msg)
.await
.map_err(|err| StreamError::Other(eyre!(err)))
}
async fn recv(&mut self) -> Option<Result<WireMessage, StreamError>> {
StreamExt::next(&mut self.0)
.await
.map(|res| res.map_err(|err| StreamError::Other(eyre!(err))))
}
}
#[cfg(feature = "framed-transport")]
pub mod framed;
#[cfg(feature = "framed-transport")]
pub use framed::{FramedError, framed_json};