use std::{ops::Deref, sync::Arc};
use async_trait::async_trait;
use bytes::Bytes;
use smol::future::FutureExt;
#[async_trait]
pub trait Pipe: Send + Sync + 'static {
fn send(&self, to_send: Bytes);
async fn recv(&self) -> std::io::Result<Bytes>;
fn protocol(&self) -> &str;
fn peer_metadata(&self) -> &str;
fn peer_addr(&self) -> String;
}
#[async_trait]
impl<P: Pipe + ?Sized, T: Deref<Target = P> + Send + Sync + 'static> Pipe for T {
fn send(&self, to_send: Bytes) {
self.deref().send(to_send)
}
async fn recv(&self) -> std::io::Result<Bytes> {
self.deref().recv().await
}
fn protocol(&self) -> &str {
self.deref().protocol()
}
fn peer_metadata(&self) -> &str {
self.deref().peer_metadata()
}
fn peer_addr(&self) -> String {
self.deref().peer_addr()
}
}
#[async_trait]
pub trait PipeListener: Sized + Send + Sync {
async fn accept_pipe(&self) -> std::io::Result<Arc<dyn Pipe>>;
fn or<T: PipeListener>(self, other: T) -> OrPipeListener<Self, T> {
OrPipeListener {
left: self,
right: other,
}
}
}
pub struct OrPipeListener<T: PipeListener + Sized, U: PipeListener + Sized> {
left: T,
right: U,
}
#[async_trait]
impl<T: PipeListener, U: PipeListener> PipeListener for OrPipeListener<T, U> {
async fn accept_pipe(&self) -> std::io::Result<Arc<dyn Pipe>> {
self.left.accept_pipe().or(self.right.accept_pipe()).await
}
}