tokio_io/
async_read.rs

1use bytes::BufMut;
2use futures::{Async, Poll};
3use std::io as std_io;
4
5#[allow(deprecated)]
6use codec::{Decoder, Encoder, Framed};
7use split::{ReadHalf, WriteHalf};
8use {framed, split, AsyncWrite};
9
10/// Read bytes asynchronously.
11///
12/// This trait inherits from `std::io::Read` and indicates that an I/O object is
13/// **non-blocking**. All non-blocking I/O objects must return an error when
14/// bytes are unavailable instead of blocking the current thread.
15///
16/// Specifically, this means that the `poll_read` function will return one of
17/// the following:
18///
19/// * `Ok(Async::Ready(n))` means that `n` bytes of data was immediately read
20///   and placed into the output buffer, where `n` == 0 implies that EOF has
21///   been reached.
22///
23/// * `Ok(Async::NotReady)` means that no data was read into the buffer
24///   provided. The I/O object is not currently readable but may become readable
25///   in the future. Most importantly, **the current future's task is scheduled
26///   to get unparked when the object is readable**. This means that like
27///   `Future::poll` you'll receive a notification when the I/O object is
28///   readable again.
29///
30/// * `Err(e)` for other errors are standard I/O errors coming from the
31///   underlying object.
32///
33/// This trait importantly means that the `read` method only works in the
34/// context of a future's task. The object may panic if used outside of a task.
35pub trait AsyncRead: std_io::Read {
36    /// Prepares an uninitialized buffer to be safe to pass to `read`. Returns
37    /// `true` if the supplied buffer was zeroed out.
38    ///
39    /// While it would be highly unusual, implementations of [`io::Read`] are
40    /// able to read data from the buffer passed as an argument. Because of
41    /// this, the buffer passed to [`io::Read`] must be initialized memory. In
42    /// situations where large numbers of buffers are used, constantly having to
43    /// zero out buffers can be expensive.
44    ///
45    /// This function does any necessary work to prepare an uninitialized buffer
46    /// to be safe to pass to `read`. If `read` guarantees to never attempt to
47    /// read data out of the supplied buffer, then `prepare_uninitialized_buffer`
48    /// doesn't need to do any work.
49    ///
50    /// If this function returns `true`, then the memory has been zeroed out.
51    /// This allows implementations of `AsyncRead` which are composed of
52    /// multiple subimplementations to efficiently implement
53    /// `prepare_uninitialized_buffer`.
54    ///
55    /// This function isn't actually `unsafe` to call but `unsafe` to implement.
56    /// The implementer must ensure that either the whole `buf` has been zeroed
57    /// or `read_buf()` overwrites the buffer without reading it and returns
58    /// correct value.
59    ///
60    /// This function is called from [`read_buf`].
61    ///
62    /// [`io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
63    /// [`read_buf`]: #method.read_buf
64    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
65        for i in 0..buf.len() {
66            buf[i] = 0;
67        }
68
69        true
70    }
71
72    /// Attempt to read from the `AsyncRead` into `buf`.
73    ///
74    /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
75    ///
76    /// If no data is available for reading, the method returns
77    /// `Ok(Async::NotReady)` and arranges for the current task (via
78    /// `cx.waker()`) to receive a notification when the object becomes
79    /// readable or is closed.
80    fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, std_io::Error> {
81        match self.read(buf) {
82            Ok(t) => Ok(Async::Ready(t)),
83            Err(ref e) if e.kind() == std_io::ErrorKind::WouldBlock => return Ok(Async::NotReady),
84            Err(e) => return Err(e.into()),
85        }
86    }
87
88    /// Pull some bytes from this source into the specified `BufMut`, returning
89    /// how many bytes were read.
90    ///
91    /// The `buf` provided will have bytes read into it and the internal cursor
92    /// will be advanced if any bytes were read. Note that this method typically
93    /// will not reallocate the buffer provided.
94    fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, std_io::Error>
95    where
96        Self: Sized,
97    {
98        if !buf.has_remaining_mut() {
99            return Ok(Async::Ready(0));
100        }
101
102        unsafe {
103            let n = {
104                let b = buf.bytes_mut();
105
106                self.prepare_uninitialized_buffer(b);
107
108                try_ready!(self.poll_read(b))
109            };
110
111            buf.advance_mut(n);
112            Ok(Async::Ready(n))
113        }
114    }
115
116    /// Provides a `Stream` and `Sink` interface for reading and writing to this
117    /// I/O object, using `Decode` and `Encode` to read and write the raw data.
118    ///
119    /// Raw I/O objects work with byte sequences, but higher-level code usually
120    /// wants to batch these into meaningful chunks, called "frames". This
121    /// method layers framing on top of an I/O object, by using the `Codec`
122    /// traits to handle encoding and decoding of messages frames. Note that
123    /// the incoming and outgoing frame types may be distinct.
124    ///
125    /// This function returns a *single* object that is both `Stream` and
126    /// `Sink`; grouping this into a single object is often useful for layering
127    /// things like gzip or TLS, which require both read and write access to the
128    /// underlying object.
129    ///
130    /// If you want to work more directly with the streams and sink, consider
131    /// calling `split` on the `Framed` returned by this method, which will
132    /// break them into separate objects, allowing them to interact more easily.
133    #[deprecated(since = "0.1.7", note = "Use tokio_codec::Decoder::framed instead")]
134    #[allow(deprecated)]
135    fn framed<T: Encoder + Decoder>(self, codec: T) -> Framed<Self, T>
136    where
137        Self: AsyncWrite + Sized,
138    {
139        framed::framed(self, codec)
140    }
141
142    /// Helper method for splitting this read/write object into two halves.
143    ///
144    /// The two halves returned implement the `Read` and `Write` traits,
145    /// respectively.
146    ///
147    /// To restore this read/write object from its `ReadHalf` and `WriteHalf`
148    /// use `unsplit`.
149    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
150    where
151        Self: AsyncWrite + Sized,
152    {
153        split::split(self)
154    }
155}
156
157impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
158    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
159        (**self).prepare_uninitialized_buffer(buf)
160    }
161}
162
163impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
164    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
165        (**self).prepare_uninitialized_buffer(buf)
166    }
167}
168
169impl<'a> AsyncRead for &'a [u8] {
170    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
171        false
172    }
173}