use crate::lockers::{StdinLocker, StdoutLocker};
use async_std::fs::File;
use async_std::io::{self, IoSlice, IoSliceMut, Read, Seek, Write};
use async_std::net::TcpStream;
#[cfg(unix)]
use async_std::os::unix::{
io::{AsRawFd, RawFd},
net::UnixStream,
};
#[cfg(target_os = "wasi")]
use async_std::os::wasi::io::{AsRawFd, RawFd};
#[cfg(feature = "char-device")]
use char_device::AsyncStdCharDevice;
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, FromSocketlike, IntoFilelike, IntoSocketlike};
use std::fmt::{self, Debug};
use std::pin::Pin;
use std::task::{Context, Poll};
use system_interface::io::ReadReady;
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
use {duplex::HalfDuplex, socketpair::AsyncStdSocketpairStream};
#[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,
},
};
pub struct AsyncStreamReader {
resources: ReadResources,
}
pub struct AsyncStreamWriter {
resources: WriteResources,
}
pub struct AsyncStreamDuplexer {
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 Write + 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(AsyncStdCharDevice),
TcpStream(TcpStream),
#[cfg(unix)]
UnixStream(UnixStream),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketpairStream(AsyncStdSocketpairStream),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThreadFunc(
Option<(
AsyncStdSocketpairStream,
JoinHandle<io::Result<AsyncStdSocketpairStream>>,
)>,
),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThread(
Option<(
AsyncStdSocketpairStream,
JoinHandle<io::Result<Box<dyn HalfDuplex + Send>>>,
)>,
),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
SocketedThreadReadReady(
Option<(
AsyncStdSocketpairStream,
JoinHandle<io::Result<Box<dyn HalfDuplexReadReady + Send>>>,
)>,
),
}
impl AsyncStreamReader {
#[inline]
pub fn stdin() -> io::Result<Self> {
todo!("async stdin")
}
#[inline]
#[must_use]
pub fn file<Filelike: IntoFilelike + Read + Write + Seek>(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<Socketlike: IntoSocketlike>(socketlike: Socketlike) -> Self {
Self::_tcp_stream(TcpStream::from_into_socketlike(socketlike))
}
#[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!("async pipe reader")
}
#[cfg(not(target_os = "wasi"))] pub fn read_from_command(_command: Command) -> io::Result<Self> {
todo!("async command read")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdout(_child_stdout: ChildStdout) -> Self {
todo!("async child stdout")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stderr(_child_stderr: ChildStderr) -> Self {
todo!("async child stderr")
}
#[cfg(not(target_os = "wasi"))] pub fn piped_thread(_boxed_read: Box<dyn Read + Send>) -> io::Result<Self> {
todo!("async 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!("async bytes")
}
#[inline]
#[must_use]
fn handle(resources: ReadResources) -> Self {
Self { resources }
}
}
impl AsyncStreamWriter {
#[inline]
pub fn stdout() -> io::Result<Self> {
todo!("async stdout")
}
#[inline]
#[must_use]
pub fn file<Filelike: IntoFilelike + Read + Write + Seek>(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<Socketlike: IntoSocketlike>(socketlike: Socketlike) -> Self {
Self::_tcp_stream(TcpStream::from_into_socketlike(socketlike))
}
#[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!("async pipe writer")
}
#[cfg(not(target_os = "wasi"))] pub fn write_to_command(_command: Command) -> io::Result<Self> {
todo!("async command write")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdin(_child_stdin: ChildStdin) -> Self {
todo!("async child stdin")
}
#[cfg(not(target_os = "wasi"))] pub fn piped_thread(_boxed_write: Box<dyn Write + Send>) -> io::Result<Self> {
todo!("async 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 AsyncStreamDuplexer {
#[inline]
pub fn stdin_stdout() -> io::Result<Self> {
todo!("async stdin_stdout")
}
#[cfg(feature = "char-device")]
#[inline]
#[must_use]
pub fn char_device(char_device: AsyncStdCharDevice) -> Self {
Self::handle(DuplexResources::CharDevice(char_device))
}
#[inline]
#[must_use]
pub fn tcp_stream<Socketlike: IntoSocketlike>(socketlike: Socketlike) -> Self {
Self::_tcp_stream(TcpStream::from_into_socketlike(socketlike))
}
#[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!("async pipe reader/writer")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
#[must_use]
pub fn socketpair_stream(stream: AsyncStdSocketpairStream) -> Self {
Self::handle(DuplexResources::SocketpairStream(stream))
}
#[cfg(not(target_os = "wasi"))] pub fn duplex_with_command(_command: Command) -> io::Result<Self> {
todo!("async command duplex")
}
#[cfg(not(target_os = "wasi"))] #[inline]
#[must_use]
pub fn child_stdout_stdin(_child_stdout: ChildStdout, _child_stdin: ChildStdin) -> Self {
todo!("async 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!("async 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!("async 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!("async socketed_thread")
}
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
pub fn socketed_thread_func(
_func: Box<
dyn Send + FnOnce(AsyncStdSocketpairStream) -> io::Result<AsyncStdSocketpairStream>,
>,
) -> io::Result<Self> {
todo!("async socketed_thread_func")
}
#[inline]
#[must_use]
fn handle(resources: DuplexResources) -> Self {
Self { resources }
}
}
impl Read for AsyncStreamReader {
#[inline]
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
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!("async pipe read"),
ReadResources::Stdin(_stdin) => todo!("async stdin read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("async piped_thread read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("async child stdout read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("async child stderr read"),
}
}
#[inline]
fn poll_read_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &mut [IoSliceMut<'_>],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
ReadResources::File(file) => Pin::new(file).poll_read_vectored(cx, bufs),
ReadResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).poll_read_vectored(cx, bufs)
}
#[cfg(unix)]
ReadResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).poll_read_vectored(cx, bufs)
}
ReadResources::PipeReader(_pipe_reader) => todo!("async pipe read"),
ReadResources::Stdin(_stdin) => todo!("async stdin read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("async piped_thread read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("async child stdout read"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("async child stderr read"),
}
}
}
impl Write for AsyncStreamWriter {
#[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!("async pipe write"),
WriteResources::Stdout(_stdout) => todo!("async stdout write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async 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!("async pipe write"),
WriteResources::Stdout(_stdout) => todo!("async stdout write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child write"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async 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!("async pipe flush"),
WriteResources::Stdout(_stdout) => todo!("async stdout flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child flush"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async child stdin flush"),
}
}
#[inline]
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
WriteResources::File(file) => Pin::new(file).poll_close(cx),
WriteResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_close(cx),
#[cfg(unix)]
WriteResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_close(cx),
WriteResources::PipeWriter(_pipe_writer) => todo!("async pipe close"),
WriteResources::Stdout(_stdout) => todo!("async stdout close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child close"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async child stdin close"),
}
}
}
impl Read for AsyncStreamDuplexer {
#[inline]
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
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!("async stdin_stdout read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("async 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!("async duplex resources"),
#[cfg(all(not(target_os = "wasi"), feature = "socketpair"))]
DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("async duplex resources"),
}
}
#[inline]
fn poll_read_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &mut [IoSliceMut<'_>],
) -> Poll<io::Result<usize>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => {
Pin::new(tcp_stream).poll_read_vectored(cx, bufs)
}
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => {
Pin::new(unix_stream).poll_read_vectored(cx, bufs)
}
DuplexResources::StdinStdout(_stdin_stdout) => todo!("async stdin_stdout read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child read"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("async child stdout/stdin read")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => {
Pin::new(char_device).poll_read_vectored(cx, bufs)
}
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_read_vectored(cx, bufs)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("async duplex resources"),
}
}
}
impl Write for AsyncStreamDuplexer {
#[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!("async stdout write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("async 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!("async stdout write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child write"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async 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!("async stdout flush"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child flush"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("async 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!("async duplex resources"),
}
}
#[inline]
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match &mut self.resources {
DuplexResources::TcpStream(tcp_stream) => Pin::new(tcp_stream).poll_close(cx),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => Pin::new(unix_stream).poll_close(cx),
DuplexResources::StdinStdout(_stdin_stdout) => todo!("async stdout close"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child close"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_child_stdout_stdin) => {
todo!("async child stdout/stdin close")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => Pin::new(char_device).poll_close(cx),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
Pin::new(socketpair_stream).poll_close(cx)
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("async duplex resources"),
}
}
}
impl Duplex for AsyncStreamDuplexer {}
#[cfg(not(windows))]
impl AsRawFd for AsyncStreamReader {
#[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!("async pipe as_raw_fd"),
ReadResources::Stdin(_stdin) => todo!("async stdin as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("async piped_thread as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("async child stdout as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("async child stderr as_raw_fd"),
}
}
}
#[cfg(not(windows))]
impl AsRawFd for AsyncStreamWriter {
#[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!("async pipe as_raw_fd"),
WriteResources::Stdout(_stdout) => todo!("async stdout as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child as_raw_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async child stdin as_raw_fd"),
}
}
}
#[cfg(not(windows))]
impl AsRawReadWriteFd for AsyncStreamDuplexer {
#[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!("async stdout as_raw_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_raw_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async 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!("async stdout as_raw_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_raw_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async duplex resources"),
}
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for AsyncStreamReader {
#[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!("async pipe as_raw_handle_or_socket"),
ReadResources::Stdin(_stdin) => todo!("async stdin as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => {
todo!("async piped_thread as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => {
todo!("async child stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => {
todo!("async child stderr as_raw_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for AsyncStreamWriter {
#[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!("async pipe as_raw_handle_or_socket"),
WriteResources::Stdout(_stdout) => todo!("async stdout as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => {
todo!("async piped_thread as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => {
todo!("async child stdin as_raw_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsRawReadWriteHandleOrSocket for AsyncStreamDuplexer {
#[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!("async stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async duplex resources"),
}
}
#[inline]
fn as_raw_write_handle_or_socket(&self) -> RawHandleOrSocket {
match &self.resources {
DuplexResources::TcpStream(tcp_stream) => tcp_stream.as_raw_handle_or_socket(),
#[cfg(unix)]
DuplexResources::UnixStream(unix_stream) => unix_stream.as_raw_handle_or_socket(),
DuplexResources::StdinStdout(_stdin_stdout) => {
todo!("async stdout as_raw_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_raw_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async child stdout/stdin as_raw_handle_or_socket")
}
#[cfg(feature = "char-device")]
DuplexResources::CharDevice(char_device) => char_device.as_raw_handle_or_socket(),
#[cfg(feature = "socketpair")]
DuplexResources::SocketpairStream(socketpair_stream) => {
socketpair_stream.as_raw_handle_or_socket()
}
DuplexResources::PipeReaderWriter(_)
| DuplexResources::SocketedThreadFunc(_)
| DuplexResources::SocketedThread(_)
| DuplexResources::SocketedThreadReadReady(_) => todo!("async duplex resources"),
}
}
}
#[cfg(not(windows))]
impl AsFd for AsyncStreamReader {
#[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!("async pipe as_fd"),
ReadResources::Stdin(_stdin) => todo!("async stdin as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => todo!("async piped_thread as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => todo!("async child stdout as_fd"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => todo!("async child stderr as_fd"),
}
}
}
#[cfg(not(windows))]
impl AsFd for AsyncStreamWriter {
#[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!("async pipe as_fd"),
WriteResources::Stdout(_stdout) => todo!("async stdout as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => todo!("async piped_thread as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child as_fd"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => todo!("async child stdin as_fd"),
}
}
}
#[cfg(not(windows))]
impl AsReadWriteFd for AsyncStreamDuplexer {
#[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!("async stdout as_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_read_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async 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!("async stdout as_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_write_fd"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async duplex resources"),
}
}
}
#[cfg(windows)]
impl AsHandleOrSocket for AsyncStreamReader {
#[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!("async pipe as_handle_or_socket"),
ReadResources::Stdin(_stdin) => todo!("async stdin as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::PipedThread(_piped_thread) => {
todo!("async piped_thread as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::Child(_child) => todo!("async child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStdout(_child_stdout) => {
todo!("async child stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
ReadResources::ChildStderr(_child_stderr) => {
todo!("async child stderr as_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsHandleOrSocket for AsyncStreamWriter {
#[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!("async pipe as_handle_or_socket"),
WriteResources::Stdout(_stdout) => todo!("async stdout as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::PipedThread(_piped_thread) => {
todo!("async piped_thread as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
WriteResources::Child(_child) => todo!("async child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
WriteResources::ChildStdin(_child_stdin) => {
todo!("async child stdin as_handle_or_socket")
}
}
}
}
#[cfg(windows)]
impl AsReadWriteHandleOrSocket for AsyncStreamDuplexer {
#[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!("async stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async 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!("async stdout as_handle_or_socket")
}
#[cfg(not(target_os = "wasi"))]
DuplexResources::Child(_child) => todo!("async child as_handle_or_socket"),
#[cfg(not(target_os = "wasi"))]
DuplexResources::ChildStdoutStdin(_stdout_stdin) => {
todo!("async 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!("async 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 AsyncStreamReader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("AsyncStreamReader")
.field("raw_grip", &self.as_raw_grip())
.finish()
}
}
impl Debug for AsyncStreamWriter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("AsyncStreamWriter")
.field("raw_grip", &self.as_raw_grip())
.finish()
}
}
impl Debug for AsyncStreamDuplexer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("AsyncStreamDuplexer")
.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 {}