mod codec;
use bytes::Bytes;
use futures::{Sink, SinkExt, Stream, StreamExt};
use std::{
fmt, io,
pin::Pin,
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_util::codec::{FramedRead, FramedWrite};
use wokio::task::{MaybeSend, MaybeSync};
pub use codec::*;
pub trait DynRead: AsyncRead + MaybeSend + MaybeSync + 'static {}
impl<T> DynRead for T where T: AsyncRead + MaybeSend + MaybeSync + 'static + ?Sized {}
pub trait DynWrite: AsyncWrite + MaybeSend + MaybeSync + 'static {}
impl<T> DynWrite for T where T: AsyncWrite + MaybeSend + MaybeSync + 'static + ?Sized {}
pub trait DynSink: Sink<Bytes, Error = io::Error> + MaybeSend + MaybeSync + 'static {}
impl<T> DynSink for T where T: Sink<Bytes, Error = io::Error> + MaybeSend + MaybeSync + 'static + ?Sized {}
pub trait DynStream: Stream<Item = io::Result<Bytes>> + MaybeSend + MaybeSync + 'static {}
impl<T> DynStream for T where T: Stream<Item = io::Result<Bytes>> + MaybeSend + MaybeSync + 'static + ?Sized {}
struct FilterFlush<W> {
inner: W,
pub flush_allowed: bool,
}
impl<W> FilterFlush<W> {
pub fn new(inner: W) -> Self {
Self { inner, flush_allowed: false }
}
}
impl<W> AsyncWrite for FilterFlush<W>
where
W: AsyncWrite + Unpin,
{
fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
Pin::new(&mut Pin::into_inner(self).inner).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
if !self.flush_allowed {
return Poll::Ready(Ok(()));
}
Pin::new(&mut Pin::into_inner(self).inner).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
Pin::new(&mut Pin::into_inner(self).inner).poll_shutdown(cx)
}
}
pub struct IoTx<W>(FramedWrite<FilterFlush<W>, IntegrityCodec>);
impl<W> fmt::Debug for IoTx<W>
where
W: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("IoTx").field(&self.0.get_ref().inner).finish()
}
}
impl<W> IoTx<W>
where
W: AsyncWrite,
{
pub fn new(write: W) -> Self {
Self::with_codec(write, IntegrityCodec::new())
}
pub fn with_capacity(write: W, capacity: usize) -> Self {
Self::with_codec_and_capacity(write, IntegrityCodec::new(), capacity)
}
pub fn with_codec(write: W, codec: IntegrityCodec) -> Self {
Self(FramedWrite::new(FilterFlush::new(write), codec))
}
pub fn with_codec_and_capacity(write: W, codec: IntegrityCodec, capacity: usize) -> Self {
Self(FramedWrite::with_capacity(FilterFlush::new(write), codec, capacity))
}
}
impl<W> Sink<Bytes> for IoTx<W>
where
W: AsyncWrite + Unpin,
{
type Error = io::Error;
#[inline]
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::into_inner(self).0.poll_ready_unpin(cx)
}
#[inline]
fn start_send(self: Pin<&mut Self>, item: Bytes) -> Result<(), Self::Error> {
Pin::into_inner(self).0.start_send_unpin(item)
}
#[inline]
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
let this = Pin::into_inner(self);
this.0.get_mut().flush_allowed = true;
let res = this.0.poll_flush_unpin(cx);
this.0.get_mut().flush_allowed = false;
res
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
let this = Pin::into_inner(self);
this.0.get_mut().flush_allowed = true;
let res = this.0.poll_close_unpin(cx);
this.0.get_mut().flush_allowed = false;
res
}
}
pub struct IoRx<R>(FramedRead<R, IntegrityCodec>);
impl<R> fmt::Debug for IoRx<R>
where
R: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("IoRx").field(&self.0.get_ref()).finish()
}
}
impl<R> IoRx<R>
where
R: AsyncRead,
{
pub fn new(read: R) -> Self {
Self::with_codec(read, IntegrityCodec::new())
}
pub fn with_capacity(read: R, capacity: usize) -> Self {
Self::with_codec_and_capacity(read, IntegrityCodec::new(), capacity)
}
pub fn with_codec(read: R, codec: IntegrityCodec) -> Self {
Self(FramedRead::new(read, codec))
}
pub fn with_codec_and_capacity(read: R, codec: IntegrityCodec, capacity: usize) -> Self {
Self(FramedRead::with_capacity(read, codec, capacity))
}
}
impl<R> Stream for IoRx<R>
where
R: AsyncRead + Unpin,
{
type Item = Result<Bytes, io::Error>;
#[inline]
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
Pin::into_inner(self).0.poll_next_unpin(cx).map_ok(|v| v.freeze())
}
}
pub type IoTxBox = IoTx<Pin<Box<dyn DynWrite>>>;
pub type IoRxBox = IoRx<Pin<Box<dyn DynRead>>>;
pub enum StreamBox {
TxRx(TxRxBox),
Io(IoBox),
}
impl StreamBox {
pub fn into_tx_rx(self) -> TxRxBox {
match self {
Self::TxRx(tx_rx) => tx_rx,
Self::Io(IoBox { read, write }) => {
let tx = IoTxBox::new(write);
let rx = IoRxBox::new(read);
TxRxBox::new(tx, rx)
}
}
}
pub fn into_tx_rx_with_capacity(self, capacity: usize) -> TxRxBox {
match self {
Self::TxRx(tx_rx) => tx_rx,
Self::Io(IoBox { read, write }) => {
let tx = IoTxBox::with_capacity(write, capacity);
let rx = IoRxBox::with_capacity(read, capacity);
TxRxBox::new(tx, rx)
}
}
}
}
impl From<TxRxBox> for StreamBox {
fn from(value: TxRxBox) -> Self {
Self::TxRx(value)
}
}
impl From<IoBox> for StreamBox {
fn from(value: IoBox) -> Self {
Self::Io(value)
}
}
pub(crate) type TxBox = Pin<Box<dyn DynSink>>;
pub(crate) type RxBox = Pin<Box<dyn DynStream>>;
pub struct TxRxBox {
pub tx: TxBox,
pub rx: RxBox,
}
impl TxRxBox {
pub fn new(tx: impl DynSink, rx: impl DynStream) -> Self {
Self { tx: Box::pin(tx), rx: Box::pin(rx) }
}
pub fn into_split(self) -> (TxBox, RxBox) {
let Self { tx, rx } = self;
(tx, rx)
}
}
impl Sink<Bytes> for TxRxBox {
type Error = io::Error;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
self.get_mut().tx.poll_ready_unpin(cx)
}
fn start_send(self: Pin<&mut Self>, item: Bytes) -> io::Result<()> {
self.get_mut().tx.start_send_unpin(item)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
self.get_mut().tx.poll_flush_unpin(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
self.get_mut().tx.poll_close_unpin(cx)
}
}
impl Stream for TxRxBox {
type Item = io::Result<Bytes>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
self.get_mut().rx.poll_next_unpin(cx)
}
}
pub(crate) type ReadBox = Pin<Box<dyn DynRead>>;
pub(crate) type WriteBox = Pin<Box<dyn DynWrite>>;
pub struct IoBox {
pub read: ReadBox,
pub write: WriteBox,
}
impl IoBox {
pub fn new(read: impl DynRead, write: impl DynWrite) -> Self {
Self { read: Box::pin(read), write: Box::pin(write) }
}
pub fn into_split(self) -> (ReadBox, WriteBox) {
let Self { read, write } = self;
(read, write)
}
}
impl AsyncRead for IoBox {
fn poll_read(self: Pin<&mut Self>, cx: &mut Context, buf: &mut ReadBuf) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().read).poll_read(cx, buf)
}
}
impl AsyncWrite for IoBox {
fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
Pin::new(&mut self.get_mut().write).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().write).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().write).poll_shutdown(cx)
}
}