use crate::lockers::{StdinLocker, StdoutLocker};
#[cfg(feature = "char-device")]
use char_device::TokioCharDevice;
use duplex::Duplex;
use io_extras::grip::{AsRawGrip, AsRawReadWriteGrip};
#[cfg(windows)]
use io_extras::os::windows::{
AsHandleOrSocket, AsRawHandleOrSocket, AsRawReadWriteHandleOrSocket, AsReadWriteHandleOrSocket,
BorrowedHandleOrSocket, RawHandleOrSocket,
};
use io_lifetimes::{FromFilelike, IntoFilelike};
use std::fmt::{self, Debug};
use std::io::IoSlice;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, RawFd};
use std::pin::Pin;
use std::task::{Context, Poll};
use system_interface::io::ReadReady;
use tokio::fs::File;
use tokio::io::{self, AsyncRead, AsyncSeek, AsyncWrite, ReadBuf};
use tokio::net::TcpStream;
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
use {duplex::HalfDuplex, socketpair::TokioSocketpairStream};
#[cfg(not(windows))]
use {
io_extras::os::rustix::{AsRawReadWriteFd, AsReadWriteFd},
io_lifetimes::{AsFd, BorrowedFd},
};
#[cfg(not(target_os = "wasi"))]
use {
os_pipe::{PipeReader, PipeWriter},
std::{
process::{Child, ChildStderr, ChildStdin, ChildStdout, Command},
thread::JoinHandle,
},
};
#[cfg(unix)]
use {
std::os::unix::io::{AsRawFd, RawFd},
tokio::net::UnixStream,
};
pub struct TokioStreamReader {
resources: ReadResources,
}
pub struct TokioStreamWriter {
resources: WriteResources,
}
pub struct TokioStreamDuplexer {
resources: DuplexResources,
}
#[allow(dead_code)] enum ReadResources {
File(File),
TcpStream(TcpStream),
#[cfg(unix)]
UnixStream(UnixStream),
#[cfg(not(target_os = "wasi"))] PipeReader(PipeReader),
Stdin(StdinLocker),
#[cfg(not(target_os = "wasi"))] PipedThread(Option<(PipeReader, JoinHandle<io::Result<()>>)>),
#[cfg(not(target_os = "wasi"))] Child(Child),
#[cfg(not(target_os = "wasi"))] ChildStdout(ChildStdout),
#[cfg(not(target_os = "wasi"))] ChildStderr(ChildStderr),
}
#[allow(dead_code)] enum WriteResources {
File(File),
TcpStream(TcpStream),
#[cfg(unix)]
UnixStream(UnixStream),
#[cfg(not(target_os = "wasi"))] PipeWriter(PipeWriter),
Stdout(StdoutLocker),
#[cfg(not(target_os = "wasi"))] PipedThread(
Option<(
PipeWriter,
JoinHandle<io::Result<Box<dyn AsyncWrite + Send>>>,
)>,
),
#[cfg(not(target_os = "wasi"))] Child(Child),
#[cfg(not(target_os = "wasi"))] ChildStdin(ChildStdin),
}
#[allow(dead_code)] enum DuplexResources {
#[cfg(not(target_os = "wasi"))] PipeReaderWriter((PipeReader, PipeWriter)),
StdinStdout((StdinLocker, StdoutLocker)),
#[cfg(not(target_os = "wasi"))] Child(Child),
#[cfg(not(target_os = "wasi"))] ChildStdoutStdin((ChildStdout, ChildStdin)),
#[cfg(feature = "char-device")]
CharDevice(TokioCharDevice),
TcpStream(TcpStream),
#[cfg(unix)]
UnixStream(UnixStream),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketpairStream(TokioSocketpairStream),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThreadFunc(
Option<(
TokioSocketpairStream,
JoinHandle<io::Result<TokioSocketpairStream>>,
)>,
),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThread(
Option<(
TokioSocketpairStream,
JoinHandle<io::Result<Box<dyn HalfDuplex + Send>>>,
)>,
),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThreadReadReady(
Option<(
TokioSocketpairStream,
JoinHandle<io::Result<Box<dyn HalfDuplexReadReady + Send>>>,
)>,
),
}
impl TokioStreamReader {
#[inline]
pub fn stdin() -> io::Result<Self> {
todo!("tokio stdin")
}
#[inline]
#[must_use]
pub fn file<Filelike: IntoFilelike + AsyncRead + AsyncWrite + AsyncSeek>(
filelike: Filelike,
) -> Self {
Self::_file(File::from_into_filelike(filelike))
}
#[inline]
#[must_use]
fn _file(file: File) -> Self {
Self::handle(ReadResources::File(file))
}
#[inline]
#[must_use]
pub fn tcp_stream(tcp_stream: TcpStream) -> Self {
Self::_tcp_stream(tcp_stream)
}
#[inline]
#[must_use]
fn _tcp_stream(tcp_stream: TcpStream) -> Self {
Self::handle(ReadResources::TcpStream(tcp_stream))
}
#[cfg(unix)]
#[inline]
#[must_use]
pub fn unix_stream(unix_stream: UnixStream) -> Self {
Self::handle(ReadResources::UnixStream(unix_stream))
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn pipe_reader(_pipe_reader: PipeReader) -> Self {
todo!("tokio pipe reader")
}
#[cfg(not(target_os = "wasi"))] pub fn read_from_command(_command: Command) -> io::Result<Self> {
todo!("tokio command read")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdout(_child_stdout: ChildStdout) -> Self {
todo!("tokio child stdout")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stderr(_child_stderr: ChildStderr) -> Self {
todo!("tokio child stderr")
}
#[cfg(not(target_os = "wasi"))] pub fn piped_thread(_boxed_read: Box<dyn AsyncRead + Send>) -> io::Result<Self> {
todo!("tokio piped_thread reader")
}
#[inline]
#[cfg(not(target_os = "wasi"))] pub fn str<S: AsRef<str>>(s: S) -> io::Result<Self> {
Self::bytes(s.as_ref().as_bytes())
}
#[cfg(not(target_os = "wasi"))] pub fn bytes(_bytes: &[u8]) -> io::Result<Self> {
todo!("tokio bytes")
}
#[inline]
#[must_use]
fn handle(resources: ReadResources) -> Self {
Self { resources }
}
}
impl TokioStreamWriter {
#[inline]
pub fn stdout() -> io::Result<Self> {
todo!("tokio stdout")
}
#[inline]
#[must_use]
pub fn file<Filelike: IntoFilelike + AsyncRead + AsyncWrite + AsyncSeek>(
filelike: Filelike,
) -> Self {
Self::_file(File::from_into_filelike(filelike))
}
#[inline]
#[must_use]
fn _file(file: File) -> Self {
Self::handle(WriteResources::File(file))
}
#[inline]
#[must_use]
pub fn tcp_stream(tcp_stream: TcpStream) -> Self {
Self::_tcp_stream(tcp_stream)
}
#[inline]
#[must_use]
fn _tcp_stream(tcp_stream: TcpStream) -> Self {
Self::handle(WriteResources::TcpStream(tcp_stream))
}
#[cfg(unix)]
#[inline]
#[must_use]
pub fn unix_stream(unix_stream: UnixStream) -> Self {
Self::handle(WriteResources::UnixStream(unix_stream))
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn pipe_writer(_pipe_writer: PipeWriter) -> Self {
todo!("tokio pipe writer")
}
#[cfg(not(target_os = "wasi"))] pub fn write_to_command(_command: Command) -> io::Result<Self> {
todo!("tokio command write")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdin(_child_stdin: ChildStdin) -> Self {
todo!("tokio child stdin")
}
#[cfg(not(target_os = "wasi"))] pub fn piped_thread(_boxed_write: Box<dyn AsyncWrite + Send>) -> io::Result<Self> {
todo!("tokio piped_thread writer")
}
pub async fn null() -> io::Result<Self> {
#[cfg(not(windows))]
{
Ok(Self::_file(File::create("/dev/null").await?))
}
#[cfg(windows)]
{
Ok(Self::_file(File::create("nul").await?))
}
}
#[inline]
fn handle(resources: WriteResources) -> Self {
Self { resources }
}
}
impl TokioStreamDuplexer {
#[inline]
pub fn stdin_stdout() -> io::Result<Self> {
todo!("tokio stdin_stdout")
}
#[cfg(feature = "char-device")]
#[inline]
#[must_use]
pub fn char_device(char_device: TokioCharDevice) -> Self {
Self::handle(DuplexResources::CharDevice(char_device))
}
#[inline]
#[must_use]
pub fn tcp_stream(tcp_stream: TcpStream) -> Self {
Self::_tcp_stream(tcp_stream)
}
#[inline]
#[must_use]
fn _tcp_stream(tcp_stream: TcpStream) -> Self {
Self::handle(DuplexResources::TcpStream(tcp_stream))
}
#[cfg(unix)]
#[must_use]
pub fn unix_stream(unix_stream: UnixStream) -> Self {
Self::handle(DuplexResources::UnixStream(unix_stream))
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn pipe_reader_writer(_pipe_reader: PipeReader, _pipe_writer: PipeWriter) -> Self {
todo!("tokio pipe reader/writer")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
#[must_use]
pub fn socketpair_stream(stream: TokioSocketpairStream) -> Self {
Self::handle(DuplexResources::SocketpairStream(stream))
}
#[cfg(not(target_os = "wasi"))] pub fn duplex_with_command(_command: Command) -> io::Result<Self> {
todo!("tokio command duplex")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdout_stdin(_child_stdout: ChildStdout, _child_stdin: ChildStdin) -> Self {
todo!("tokio child stdin/stdout")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub fn socketed_thread_read_first(
_boxed_duplex: Box<dyn HalfDuplex + Send>,
) -> io::Result<Self> {
todo!("tokio socketed_thread_read_first")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub fn socketed_thread_write_first(
_boxed_duplex: Box<dyn HalfDuplex + Send>,
) -> io::Result<Self> {
todo!("tokio socketed_thread_write_first")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub fn socketed_thread(_boxed_duplex: Box<dyn HalfDuplexReadReady + Send>) -> io::Result<Self> {
todo!("tokio socketed_thread")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub fn socketed_thread_func(
_func: Box<dyn Send + FnOnce(TokioSocketpairStream) -> io::Result<TokioSocketpairStream>>,
) -> io::Result<Self> {
todo!("tokio socketed_thread_func")
}
#[inline]
#[must_use]
fn handle(resources: DuplexResources) -> Self {
Self { resources }
}
}
impl AsyncRead for TokioStreamReader {
#[inline]
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<()>> {
match &mut self.resources {
ReadResources::File(file) => Pin::new(file).poll_read(cx, buf),
ReadResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_read(cx, buf),
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_read(cx, buf),
ReadResources::PipeReader(_pipe_reader) => todo!("tokio pipe read"),
ReadResources::Stdin(_stdin) => todo!("tokio stdin read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("tokio piped_thread read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("tokio child read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("tokio child stdout read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("tokio child stderr read"),
}
}
}
impl AsyncWrite for TokioStreamWriter {
#[inline]
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
WriteResources::File(file) => Pin::new(file).poll_write(cx, buf),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_write(cx, buf),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_write(cx, buf),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe write"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin write"),
}
}
fn poll_write_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
WriteResources::File(file) => Pin::new(file).poll_write_vectored(cx, bufs),
WriteResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).poll_write_vectored(cx, bufs)
}
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).poll_write_vectored(cx, bufs)
}
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe write"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin write"),
}
}
#[inline]
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
WriteResources::File(file) => Pin::new(file).poll_flush(cx),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_flush(cx),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_flush(cx),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe flush"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin flush"),
}
}
#[inline]
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
WriteResources::File(file) => Pin::new(file).poll_shutdown(cx),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_shutdown(cx),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_shutdown(cx),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe close"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin close"),
}
}
}
impl AsyncRead for TokioStreamDuplexer {
#[inline]
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<()>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_read(cx, buf),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_read(cx, buf),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdin_stdout read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("tokio child stdout/stdin read")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).poll_read(cx, buf),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_read(cx, buf)
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::PipeReaderWriter(_) => todo!("tokio duplex resources"),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
impl AsyncWrite for TokioStreamDuplexer {
#[inline]
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_write(cx, buf),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_write(cx, buf),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin write")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).poll_write(cx, buf),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_write(cx, buf)
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::PipeReaderWriter(_) => todo!("tokio duplex resources"),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
fn poll_write_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).poll_write_vectored(cx, bufs)
}
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).poll_write_vectored(cx, bufs)
}
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin write")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => {
Pin::new(char_device).poll_write_vectored(cx, bufs)
}
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_write_vectored(cx, bufs)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_flush(cx),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_flush(cx),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout flush"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child flush"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("tokio child stdout/stdin flush")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).poll_flush(cx),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_flush(cx)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_shutdown(cx),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_shutdown(cx),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout close"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child close"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("tokio child stdout/stdin close")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).poll_shutdown(cx),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_shutdown(cx)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
impl Duplex for TokioStreamDuplexer {}
#[cfg(not(windows))]
impl AsRawFd for TokioStreamReader {
#[inline]
fn as_raw_fd(&self) -> RawFd {
match &self.resources {
ReadResources::File(file) => file.as_raw_fd(),
ReadResources::TcpStream(tcp_stream) => tcp_stream.as_raw_fd(),
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => unix_stream.as_raw_fd(),
ReadResources::PipeReader(_pipe_reader) => todo!("tokio pipe as_raw_fd"),
ReadResources::Stdin(_stdin) => todo!("tokio stdin as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("tokio piped_thread as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("tokio child as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("tokio child stdout as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("tokio child stderr as_raw_fd"),
}
}
}
#[cfg(not(windows))]
impl AsRawFd for TokioStreamWriter {
#[inline]
fn as_raw_fd(&self) -> RawFd {
match &self.resources {
WriteResources::File(file) => Pin::new(file).as_raw_fd(),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).as_raw_fd(),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => Pin::new(unix_stream).as_raw_fd(),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe as_raw_fd"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin as_raw_fd"),
}
}
}
#[cfg(not(windows))]
impl AsRawReadWriteFd for TokioStreamDuplexer {
#[inline]
fn as_raw_read_fd(&self) -> RawFd {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).as_raw_fd(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).as_raw_fd(),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout as_raw_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_raw_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_raw_read_fd")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).as_raw_fd(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).as_raw_fd()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn as_raw_write_fd(&self) -> RawFd {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).as_raw_fd(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).as_raw_fd(),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout as_raw_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_raw_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_raw_write_fd")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).as_raw_fd(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).as_raw_fd()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for TokioStreamReader {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
match &self.resources {
ReadResources::File(file) => file.as_raw_handle_or_socket(),
ReadResources::TcpStream(tcp_stream) => tcp_stream.as_raw_handle_or_socket(),
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => unix_stream.as_raw_handle_or_socket(),
ReadResources::PipeReader(_pipe_reader) => todo!("tokio pipe as_raw_handle_or_socket"),
ReadResources::Stdin(_stdin) => todo!("tokio stdin as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => {
todo!("tokio piped_thread as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("tokio child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => {
todo!("tokio child stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => {
todo!("tokio child stderr as_raw_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for TokioStreamWriter {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
match &self.resources {
WriteResources::File(file) => Pin::new(file).as_raw_handle_or_socket(),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).as_raw_handle_or_socket(),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).as_raw_handle_or_socket()
}
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe as_raw_handle_or_socket"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => {
todo!("tokio piped_thread as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => {
todo!("tokio child stdin as_raw_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsRawReadWriteHandleOrSocket for TokioStreamDuplexer {
#[inline]
fn as_raw_read_handle_or_socket(&self) -> RawHandleOrSocket {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).as_raw_handle_or_socket()
}
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).as_raw_handle_or_socket()
}
DuplexResources::StdinStdout(_stdin_stdout) => {
todo!("tokio stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_raw_handle_or_socket")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => {
Pin::new(char_device).as_raw_handle_or_socket()
}
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).as_raw_handle_or_socket()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn as_raw_write_handle_or_socket(&self) -> RawHandleOrSocket {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).as_raw_handle_or_socket()
}
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).as_raw_handle_or_socket()
}
DuplexResources::StdinStdout(_stdin_stdout) => {
todo!("tokio stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_raw_handle_or_socket")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => {
Pin::new(char_device).as_raw_handle_or_socket()
}
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).as_raw_handle_or_socket()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
#[cfg(not(windows))]
impl AsFd for TokioStreamReader {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
match &self.resources {
ReadResources::File(file) => file.as_fd(),
ReadResources::TcpStream(tcp_stream) => tcp_stream.as_fd(),
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => unix_stream.as_fd(),
ReadResources::PipeReader(_pipe_reader) => todo!("tokio pipe as_fd"),
ReadResources::Stdin(_stdin) => todo!("tokio stdin as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("tokio piped_thread as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("tokio child as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("tokio child stdout as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("tokio child stderr as_fd"),
}
}
}
#[cfg(not(windows))]
impl AsFd for TokioStreamWriter {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
match &self.resources {
WriteResources::File(file) => file.as_fd(),
WriteResources::TcpStream(tcp_stream) => tcp_stream.as_fd(),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => unix_stream.as_fd(),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe as_fd"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("tokio piped_thread as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("tokio child stdin as_fd"),
}
}
}
#[cfg(not(windows))]
impl AsReadWriteFd for TokioStreamDuplexer {
#[inline]
fn as_read_fd(&self) -> BorrowedFd<'_> {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => tcp_stream.as_fd(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => unix_stream.as_fd(),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout as_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_read_fd")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => char_device.as_fd(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => socketpair_stream.as_fd(),
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn as_write_fd(&self) -> BorrowedFd<'_> {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => tcp_stream.as_fd(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => unix_stream.as_fd(),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("tokio stdout as_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_write_fd")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => char_device.as_fd(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => socketpair_stream.as_fd(),
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
#[cfg(windows)]
impl AsHandleOrSocket for TokioStreamReader {
#[inline]
fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
match &self.resources {
ReadResources::File(file) => file.as_handle_or_socket(),
ReadResources::TcpStream(tcp_stream) => tcp_stream.as_handle_or_socket(),
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => unix_stream.as_handle_or_socket(),
ReadResources::PipeReader(_pipe_reader) => todo!("tokio pipe as_handle_or_socket"),
ReadResources::Stdin(_stdin) => todo!("tokio stdin as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => {
todo!("tokio piped_thread as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("tokio child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => {
todo!("tokio child stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => {
todo!("tokio child stderr as_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsHandleOrSocket for TokioStreamWriter {
#[inline]
fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
match &self.resources {
WriteResources::File(file) => file.as_handle_or_socket(),
WriteResources::TcpStream(tcp_stream) => tcp_stream.as_handle_or_socket(),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => unix_stream.as_handle_or_socket(),
WriteResources::PipeWriter(_pipe_writer) => todo!("tokio pipe as_handle_or_socket"),
WriteResources::Stdout(_stdout) => todo!("tokio stdout as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => {
todo!("tokio piped_thread as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("tokio child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => {
todo!("tokio child stdin as_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsReadWriteHandleOrSocket for TokioStreamDuplexer {
#[inline]
fn as_read_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => tcp_stream.as_handle_or_socket(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => unix_stream.as_handle_or_socket(),
DuplexResources::StdinStdout(_stdin_stdout) => {
todo!("tokio stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_handle_or_socket")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => char_device.as_handle_or_socket(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
socketpair_stream.as_handle_or_socket()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
#[inline]
fn as_write_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => tcp_stream.as_handle_or_socket(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => unix_stream.as_handle_or_socket(),
DuplexResources::StdinStdout(_stdin_stdout) => {
todo!("tokio stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("tokio child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("tokio child stdout/stdin as_handle_or_socket")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => char_device.as_handle_or_socket(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
socketpair_stream.as_handle_or_socket()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("tokio duplex resources"),
}
}
}
impl Drop for ReadResources {
fn drop(&mut self) {
match self {
#[cfg(not(target_os = "wasi"))] Self::PipedThread(piped_thread) => {
let (pipe_reader, join_handle) = piped_thread.take().unwrap();
drop(pipe_reader);
match join_handle.join().unwrap() {
Ok(()) => (),
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => (),
Err(e) => Err(e).unwrap(),
}
}
_ => {}
}
}
}
impl Drop for WriteResources {
fn drop(&mut self) {
match self {
#[cfg(not(target_os = "wasi"))] Self::PipedThread(piped_thread) => {
if let Some((pipe_writer, join_handle)) = piped_thread.take() {
drop(pipe_writer);
join_handle.join().unwrap().unwrap();
}
}
_ => {}
}
}
}
impl Drop for DuplexResources {
fn drop(&mut self) {
match self {
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
Self::SocketedThreadFunc(socketed_thread) => {
if let Some((socketpair, join_handle)) = socketed_thread.take() {
drop(socketpair);
join_handle.join().unwrap().unwrap();
}
}
_ => {}
}
}
}
impl Debug for TokioStreamReader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TokioStreamReader")
.field("raw_grip", &self.as_raw_grip())
.finish()
}
}
impl Debug for TokioStreamWriter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TokioStreamWriter")
.field("raw_grip", &self.as_raw_grip())
.finish()
}
}
impl Debug for TokioStreamDuplexer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TokioStreamDuplexer")
.field("raw_read_grip", &self.as_raw_read_grip())
.field("raw_write_grip", &self.as_raw_write_grip())
.finish()
}
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub trait HalfDuplexReadReady: HalfDuplex + ReadReady {}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
impl<T: HalfDuplex + ReadReady> HalfDuplexReadReady for T {}