1 use futures_core::task::{Context, Poll};
2 #[cfg(feature = "read-initializer")]
3 use futures_io::Initializer;
4 use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom};
5 use std::pin::Pin;
6 use std::{fmt, io};
7 
8 /// A simple wrapper type which allows types which implement only
9 /// implement `std::io::Read` or `std::io::Write`
10 /// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`.
11 ///
12 /// If these types issue an error with the kind `io::ErrorKind::WouldBlock`,
13 /// it is expected that they will notify the current task on readiness.
14 /// Synchronous `std` types should not issue errors of this kind and
15 /// are safe to use in this context. However, using these types with
16 /// `AllowStdIo` will cause the event loop to block, so they should be used
17 /// with care.
18 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
19 pub struct AllowStdIo<T>(T);
20 
21 impl<T> Unpin for AllowStdIo<T> {}
22 
23 macro_rules! try_with_interrupt {
24     ($e:expr) => {
25         loop {
26             match $e {
27                 Ok(e) => {
28                     break e;
29                 }
30                 Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {
31                     continue;
32                 }
33                 Err(e) => {
34                     return Poll::Ready(Err(e));
35                 }
36             }
37         }
38     };
39 }
40 
41 impl<T> AllowStdIo<T> {
42     /// Creates a new `AllowStdIo` from an existing IO object.
new(io: T) -> Self43     pub fn new(io: T) -> Self {
44         Self(io)
45     }
46 
47     /// Returns a reference to the contained IO object.
get_ref(&self) -> &T48     pub fn get_ref(&self) -> &T {
49         &self.0
50     }
51 
52     /// Returns a mutable reference to the contained IO object.
get_mut(&mut self) -> &mut T53     pub fn get_mut(&mut self) -> &mut T {
54         &mut self.0
55     }
56 
57     /// Consumes self and returns the contained IO object.
into_inner(self) -> T58     pub fn into_inner(self) -> T {
59         self.0
60     }
61 }
62 
63 impl<T> io::Write for AllowStdIo<T>
64 where
65     T: io::Write,
66 {
write(&mut self, buf: &[u8]) -> io::Result<usize>67     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
68         self.0.write(buf)
69     }
write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>70     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
71         self.0.write_vectored(bufs)
72     }
flush(&mut self) -> io::Result<()>73     fn flush(&mut self) -> io::Result<()> {
74         self.0.flush()
75     }
write_all(&mut self, buf: &[u8]) -> io::Result<()>76     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
77         self.0.write_all(buf)
78     }
write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()>79     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
80         self.0.write_fmt(fmt)
81     }
82 }
83 
84 impl<T> AsyncWrite for AllowStdIo<T>
85 where
86     T: io::Write,
87 {
poll_write( mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>88     fn poll_write(
89         mut self: Pin<&mut Self>,
90         _: &mut Context<'_>,
91         buf: &[u8],
92     ) -> Poll<io::Result<usize>> {
93         Poll::Ready(Ok(try_with_interrupt!(self.0.write(buf))))
94     }
95 
poll_write_vectored( mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<io::Result<usize>>96     fn poll_write_vectored(
97         mut self: Pin<&mut Self>,
98         _: &mut Context<'_>,
99         bufs: &[IoSlice<'_>],
100     ) -> Poll<io::Result<usize>> {
101         Poll::Ready(Ok(try_with_interrupt!(self.0.write_vectored(bufs))))
102     }
103 
poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>>104     fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
105         try_with_interrupt!(self.0.flush());
106         Poll::Ready(Ok(()))
107     }
108 
poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>109     fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
110         self.poll_flush(cx)
111     }
112 }
113 
114 impl<T> io::Read for AllowStdIo<T>
115 where
116     T: io::Read,
117 {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>118     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
119         self.0.read(buf)
120     }
read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>121     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
122         self.0.read_vectored(bufs)
123     }
124     #[cfg(feature = "read-initializer")]
initializer(&self) -> Initializer125     unsafe fn initializer(&self) -> Initializer {
126         self.0.initializer()
127     }
read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize>128     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
129         self.0.read_to_end(buf)
130     }
read_to_string(&mut self, buf: &mut String) -> io::Result<usize>131     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
132         self.0.read_to_string(buf)
133     }
read_exact(&mut self, buf: &mut [u8]) -> io::Result<()>134     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
135         self.0.read_exact(buf)
136     }
137 }
138 
139 impl<T> AsyncRead for AllowStdIo<T>
140 where
141     T: io::Read,
142 {
poll_read( mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &mut [u8], ) -> Poll<io::Result<usize>>143     fn poll_read(
144         mut self: Pin<&mut Self>,
145         _: &mut Context<'_>,
146         buf: &mut [u8],
147     ) -> Poll<io::Result<usize>> {
148         Poll::Ready(Ok(try_with_interrupt!(self.0.read(buf))))
149     }
150 
poll_read_vectored( mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll<io::Result<usize>>151     fn poll_read_vectored(
152         mut self: Pin<&mut Self>,
153         _: &mut Context<'_>,
154         bufs: &mut [IoSliceMut<'_>],
155     ) -> Poll<io::Result<usize>> {
156         Poll::Ready(Ok(try_with_interrupt!(self.0.read_vectored(bufs))))
157     }
158 
159     #[cfg(feature = "read-initializer")]
initializer(&self) -> Initializer160     unsafe fn initializer(&self) -> Initializer {
161         self.0.initializer()
162     }
163 }
164 
165 impl<T> io::Seek for AllowStdIo<T>
166 where
167     T: io::Seek,
168 {
seek(&mut self, pos: SeekFrom) -> io::Result<u64>169     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
170         self.0.seek(pos)
171     }
172 }
173 
174 impl<T> AsyncSeek for AllowStdIo<T>
175 where
176     T: io::Seek,
177 {
poll_seek( mut self: Pin<&mut Self>, _: &mut Context<'_>, pos: SeekFrom, ) -> Poll<io::Result<u64>>178     fn poll_seek(
179         mut self: Pin<&mut Self>,
180         _: &mut Context<'_>,
181         pos: SeekFrom,
182     ) -> Poll<io::Result<u64>> {
183         Poll::Ready(Ok(try_with_interrupt!(self.0.seek(pos))))
184     }
185 }
186 
187 impl<T> io::BufRead for AllowStdIo<T>
188 where
189     T: io::BufRead,
190 {
fill_buf(&mut self) -> io::Result<&[u8]>191     fn fill_buf(&mut self) -> io::Result<&[u8]> {
192         self.0.fill_buf()
193     }
consume(&mut self, amt: usize)194     fn consume(&mut self, amt: usize) {
195         self.0.consume(amt)
196     }
197 }
198 
199 impl<T> AsyncBufRead for AllowStdIo<T>
200 where
201     T: io::BufRead,
202 {
poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>>203     fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
204         let this: *mut Self = &mut *self as *mut _;
205         Poll::Ready(Ok(try_with_interrupt!(unsafe { &mut *this }.0.fill_buf())))
206     }
207 
consume(mut self: Pin<&mut Self>, amt: usize)208     fn consume(mut self: Pin<&mut Self>, amt: usize) {
209         self.0.consume(amt)
210     }
211 }
212