pub use tokio::process::Child as DtactChild;
pub use tokio::process::ChildStderr as DtactChildStderr;
pub use tokio::process::ChildStdin as DtactChildStdin;
pub use tokio::process::ChildStdout as DtactChildStdout;
pub use tokio::process::Command as DtactCommand;
use std::future::Future;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
pub struct DtactCompat<T>(T);
impl<T> DtactCompat<T> {
pub const fn new(inner: T) -> Self {
Self(inner)
}
pub fn into_inner(self) -> T {
self.0
}
pub const fn get_ref(&self) -> &T {
&self.0
}
pub const fn get_mut(&mut self) -> &mut T {
&mut self.0
}
}
pub trait DtactCompatExt: Sized {
fn compat(self) -> DtactCompat<Self>;
}
impl DtactCompatExt for DtactChildStdout {
fn compat(self) -> DtactCompat<Self> {
DtactCompat(self)
}
}
impl DtactCompatExt for DtactChildStderr {
fn compat(self) -> DtactCompat<Self> {
DtactCompat(self)
}
}
impl DtactCompatExt for DtactChildStdin {
fn compat(self) -> DtactCompat<Self> {
DtactCompat(self)
}
}
impl<F: Future> Future for DtactCompat<F> {
type Output = F::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let inner = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
inner.poll(cx)
}
}
macro_rules! impl_read_compat {
($ty:ty) => {
impl futures_io::AsyncRead for DtactCompat<$ty> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
let this = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
let mut read_buf = tokio::io::ReadBuf::new(buf);
match tokio::io::AsyncRead::poll_read(this, cx, &mut read_buf) {
Poll::Ready(Ok(())) => Poll::Ready(Ok(read_buf.filled().len())),
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Pending => Poll::Pending,
}
}
}
};
}
macro_rules! impl_write_compat {
($ty:ty) => {
impl futures_io::AsyncWrite for DtactCompat<$ty> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
let this = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
tokio::io::AsyncWrite::poll_write(this, cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
let this = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
tokio::io::AsyncWrite::poll_flush(this, cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
let this = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
tokio::io::AsyncWrite::poll_shutdown(this, cx)
}
}
};
}
impl_read_compat!(DtactChildStdout);
impl_read_compat!(DtactChildStderr);
impl_write_compat!(DtactChildStdin);