futures_util/io/
allow_std.rs

1use futures_core::task::{Context, Poll};
2use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom};
3use std::pin::Pin;
4use std::string::String;
5use std::vec::Vec;
6use 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)]
19pub struct AllowStdIo<T>(T);
20
21impl<T> Unpin for AllowStdIo<T> {}
22
23macro_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
41impl<T> AllowStdIo<T> {
42    /// Creates a new `AllowStdIo` from an existing IO object.
43    pub fn new(io: T) -> Self {
44        Self(io)
45    }
46
47    /// Returns a reference to the contained IO object.
48    pub fn get_ref(&self) -> &T {
49        &self.0
50    }
51
52    /// Returns a mutable reference to the contained IO object.
53    pub fn get_mut(&mut self) -> &mut T {
54        &mut self.0
55    }
56
57    /// Consumes self and returns the contained IO object.
58    pub fn into_inner(self) -> T {
59        self.0
60    }
61}
62
63impl<T> io::Write for AllowStdIo<T>
64where
65    T: io::Write,
66{
67    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
68        self.0.write(buf)
69    }
70    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
71        self.0.write_vectored(bufs)
72    }
73    fn flush(&mut self) -> io::Result<()> {
74        self.0.flush()
75    }
76    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
77        self.0.write_all(buf)
78    }
79    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
80        self.0.write_fmt(fmt)
81    }
82}
83
84impl<T> AsyncWrite for AllowStdIo<T>
85where
86    T: io::Write,
87{
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
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
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
109    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
110        self.poll_flush(cx)
111    }
112}
113
114impl<T> io::Read for AllowStdIo<T>
115where
116    T: io::Read,
117{
118    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
119        self.0.read(buf)
120    }
121    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
122        self.0.read_vectored(bufs)
123    }
124    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
125        self.0.read_to_end(buf)
126    }
127    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
128        self.0.read_to_string(buf)
129    }
130    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
131        self.0.read_exact(buf)
132    }
133}
134
135impl<T> AsyncRead for AllowStdIo<T>
136where
137    T: io::Read,
138{
139    fn poll_read(
140        mut self: Pin<&mut Self>,
141        _: &mut Context<'_>,
142        buf: &mut [u8],
143    ) -> Poll<io::Result<usize>> {
144        Poll::Ready(Ok(try_with_interrupt!(self.0.read(buf))))
145    }
146
147    fn poll_read_vectored(
148        mut self: Pin<&mut Self>,
149        _: &mut Context<'_>,
150        bufs: &mut [IoSliceMut<'_>],
151    ) -> Poll<io::Result<usize>> {
152        Poll::Ready(Ok(try_with_interrupt!(self.0.read_vectored(bufs))))
153    }
154}
155
156impl<T> io::Seek for AllowStdIo<T>
157where
158    T: io::Seek,
159{
160    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
161        self.0.seek(pos)
162    }
163}
164
165impl<T> AsyncSeek for AllowStdIo<T>
166where
167    T: io::Seek,
168{
169    fn poll_seek(
170        mut self: Pin<&mut Self>,
171        _: &mut Context<'_>,
172        pos: SeekFrom,
173    ) -> Poll<io::Result<u64>> {
174        Poll::Ready(Ok(try_with_interrupt!(self.0.seek(pos))))
175    }
176}
177
178impl<T> io::BufRead for AllowStdIo<T>
179where
180    T: io::BufRead,
181{
182    fn fill_buf(&mut self) -> io::Result<&[u8]> {
183        self.0.fill_buf()
184    }
185    fn consume(&mut self, amt: usize) {
186        self.0.consume(amt)
187    }
188}
189
190impl<T> AsyncBufRead for AllowStdIo<T>
191where
192    T: io::BufRead,
193{
194    fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
195        let this: *mut Self = &mut *self as *mut _;
196        Poll::Ready(Ok(try_with_interrupt!(unsafe { &mut *this }.0.fill_buf())))
197    }
198
199    fn consume(mut self: Pin<&mut Self>, amt: usize) {
200        self.0.consume(amt)
201    }
202}