1 use crate::cli::{IsTerminal, StdinStream, StdoutStream}; 2 use crate::p2; 3 use std::pin::Pin; 4 use std::task::{Context, Poll}; 5 use tokio::io::{self, AsyncRead, AsyncWrite}; 6 use wasmtime_wasi_io::streams::{InputStream, OutputStream}; 7 8 // Implementation for tokio::io::Empty 9 impl IsTerminal for tokio::io::Empty { is_terminal(&self) -> bool10 fn is_terminal(&self) -> bool { 11 false 12 } 13 } 14 impl StdinStream for tokio::io::Empty { p2_stream(&self) -> Box<dyn InputStream>15 fn p2_stream(&self) -> Box<dyn InputStream> { 16 Box::new(p2::pipe::ClosedInputStream) 17 } async_stream(&self) -> Box<dyn AsyncRead + Send + Sync>18 fn async_stream(&self) -> Box<dyn AsyncRead + Send + Sync> { 19 Box::new(tokio::io::empty()) 20 } 21 } 22 impl StdoutStream for tokio::io::Empty { p2_stream(&self) -> Box<dyn OutputStream>23 fn p2_stream(&self) -> Box<dyn OutputStream> { 24 Box::new(p2::pipe::SinkOutputStream) 25 } async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync>26 fn async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync> { 27 Box::new(tokio::io::empty()) 28 } 29 } 30 31 // Implementation for std::io::Empty 32 impl IsTerminal for std::io::Empty { is_terminal(&self) -> bool33 fn is_terminal(&self) -> bool { 34 false 35 } 36 } 37 impl StdinStream for std::io::Empty { p2_stream(&self) -> Box<dyn InputStream>38 fn p2_stream(&self) -> Box<dyn InputStream> { 39 Box::new(p2::pipe::ClosedInputStream) 40 } async_stream(&self) -> Box<dyn AsyncRead + Send + Sync>41 fn async_stream(&self) -> Box<dyn AsyncRead + Send + Sync> { 42 Box::new(tokio::io::empty()) 43 } 44 } 45 impl StdoutStream for std::io::Empty { p2_stream(&self) -> Box<dyn OutputStream>46 fn p2_stream(&self) -> Box<dyn OutputStream> { 47 Box::new(p2::pipe::SinkOutputStream) 48 } async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync>49 fn async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync> { 50 Box::new(tokio::io::empty()) 51 } 52 } 53 54 // Implementation for p2::pipe::ClosedInputStream 55 impl IsTerminal for p2::pipe::ClosedInputStream { is_terminal(&self) -> bool56 fn is_terminal(&self) -> bool { 57 false 58 } 59 } 60 impl StdinStream for p2::pipe::ClosedInputStream { p2_stream(&self) -> Box<dyn InputStream>61 fn p2_stream(&self) -> Box<dyn InputStream> { 62 Box::new(p2::pipe::ClosedInputStream) 63 } async_stream(&self) -> Box<dyn AsyncRead + Send + Sync>64 fn async_stream(&self) -> Box<dyn AsyncRead + Send + Sync> { 65 Box::new(tokio::io::empty()) 66 } 67 } 68 69 // Implementation for p2::pipe::SinkOutputStream 70 impl IsTerminal for p2::pipe::SinkOutputStream { is_terminal(&self) -> bool71 fn is_terminal(&self) -> bool { 72 false 73 } 74 } 75 impl StdoutStream for p2::pipe::SinkOutputStream { p2_stream(&self) -> Box<dyn OutputStream>76 fn p2_stream(&self) -> Box<dyn OutputStream> { 77 Box::new(p2::pipe::SinkOutputStream) 78 } async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync>79 fn async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync> { 80 Box::new(tokio::io::empty()) 81 } 82 } 83 84 // Implementation for p2::pipe::ClosedOutputStream 85 impl IsTerminal for p2::pipe::ClosedOutputStream { is_terminal(&self) -> bool86 fn is_terminal(&self) -> bool { 87 false 88 } 89 } 90 impl StdoutStream for p2::pipe::ClosedOutputStream { p2_stream(&self) -> Box<dyn OutputStream>91 fn p2_stream(&self) -> Box<dyn OutputStream> { 92 Box::new(p2::pipe::ClosedOutputStream) 93 } async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync>94 fn async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync> { 95 struct AlwaysClosed; 96 97 impl AsyncWrite for AlwaysClosed { 98 fn poll_write( 99 self: Pin<&mut Self>, 100 _cx: &mut Context<'_>, 101 _buf: &[u8], 102 ) -> Poll<io::Result<usize>> { 103 Poll::Ready(Ok(0)) 104 } 105 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { 106 Poll::Ready(Ok(())) 107 } 108 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { 109 Poll::Ready(Ok(())) 110 } 111 } 112 113 Box::new(AlwaysClosed) 114 } 115 } 116