futures_util/io/
allow_std.rs

1use futures_core::{Async, Poll, task};
2use futures_io::{AsyncRead, AsyncWrite};
3use std::{fmt, io};
4use std::string::String;
5use std::vec::Vec;
6
7/// A simple wrapper type which allows types which implement only
8/// implement `std::io::Read` or `std::io::Write`
9/// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`.
10///
11/// If these types issue an error with the kind `io::ErrorKind::WouldBlock`,
12/// it is expected that they will notify the current task on readiness.
13/// Synchronous `std` types should not issue errors of this kind and
14/// are safe to use in this context. However, using these types with
15/// `AllowStdIo` will cause the event loop to block, so they should be used
16/// with care.
17#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
18pub struct AllowStdIo<T>(T);
19
20macro_rules! try_with_interrupt {
21    ($e:expr) => {
22        loop {
23            match $e {
24                Ok(e) => {
25                    break e;
26                }
27                Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {
28                    continue;
29                }
30                Err(e) => {
31                    return Err(e);
32                }
33            }
34        }
35    }
36}
37
38impl<T> AllowStdIo<T> {
39    /// Creates a new `AllowStdIo` from an existing IO object.
40    pub fn new(io: T) -> Self {
41        AllowStdIo(io)
42    }
43
44    /// Returns a reference to the contained IO object.
45    pub fn get_ref(&self) -> &T {
46        &self.0
47    }
48
49    /// Returns a mutable reference to the contained IO object.
50    pub fn get_mut(&mut self) -> &mut T {
51        &mut self.0
52    }
53
54    /// Consumes self and returns the contained IO object.
55    pub fn into_inner(self) -> T {
56        self.0
57    }
58}
59
60impl<T> io::Write for AllowStdIo<T> where T: io::Write {
61    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
62        self.0.write(buf)
63    }
64    fn flush(&mut self) -> io::Result<()> {
65        self.0.flush()
66    }
67    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
68        self.0.write_all(buf)
69    }
70    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
71        self.0.write_fmt(fmt)
72    }
73}
74
75impl<T> AsyncWrite for AllowStdIo<T> where T: io::Write {
76    fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
77        -> Poll<usize, io::Error>
78    {
79        Ok(Async::Ready(try_with_interrupt!(io::Write::write(&mut self.0, buf))))
80    }
81
82    fn poll_flush(&mut self, _: &mut task::Context) -> Poll<(), io::Error> {
83        Ok(Async::Ready(try_with_interrupt!(io::Write::flush(self))))
84    }
85
86    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
87        self.poll_flush(cx)
88    }
89}
90
91impl<T> io::Read for AllowStdIo<T> where T: io::Read {
92    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
93        self.0.read(buf)
94    }
95    // TODO: implement the `initializer` fn when it stabilizes.
96    // See rust-lang/rust #42788
97    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
98        self.0.read_to_end(buf)
99    }
100    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
101        self.0.read_to_string(buf)
102    }
103    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
104        self.0.read_exact(buf)
105    }
106}
107
108impl<T> AsyncRead for AllowStdIo<T> where T: io::Read {
109    fn poll_read(&mut self, _: &mut task::Context, buf: &mut [u8])
110        -> Poll<usize, io::Error>
111    {
112        Ok(Async::Ready(try_with_interrupt!(io::Read::read(&mut self.0, buf))))
113    }
114}