merge_io/
lib.rs

1//! Merge two separate [`AsyncRead`](futures::io::AsyncRead) and
2//! [`AsyncWrite`](futures::io::AsyncWrite) objects into a single I/O stream.
3//!
4//! # Examples
5//!
6//! ```
7//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
8//! # futures::executor::block_on(async {
9//! use merge_io::MergeIO;
10//! use futures::io::Cursor;
11//! use futures::{AsyncReadExt, AsyncWriteExt};
12//!
13//! // Prepare `reader` to read data from...
14//! let reader = Cursor::new(vec![1, 2, 3, 4]);
15//!
16//! // ... and `writer` to read data to.
17//! let writer: Vec<u8> = vec![];
18//!
19//! // Merge `reader` and `writer` into a single I/O stream.
20//! let mut stream = MergeIO::new(reader, writer);
21//!
22//! // Read data from stream.
23//! let mut read_buf = Vec::<u8>::with_capacity(1024);
24//! stream.read_to_end(&mut read_buf).await?;
25//!
26//! // We got what was in the `reader`!
27//! assert_eq!(&read_buf, &[1, 2, 3, 4]);
28//!
29//! // Write data to stream.
30//! stream.write_all(&[10, 20, 30, 40]).await?;
31//!
32//! // `writer` now contains what we wrote!
33//! assert_eq!(stream.writer(), &[10, 20, 30, 40]);
34//!
35//! # Ok(())
36//! # })
37//! # }
38//! ```
39
40#![warn(missing_debug_implementations, rust_2018_idioms, missing_docs)]
41
42use futures_io::{AsyncRead, AsyncWrite};
43use std::io::{IoSlice, IoSliceMut, Result};
44use std::pin::Pin;
45use std::task::{Context, Poll};
46
47/// Merged I/O, delegates reads and writes to the provided
48/// [`AsyncRead`](futures::io::AsyncRead) (`R`) and
49/// [`AsyncWrite`](futures::io::AsyncWrite) (`W`).
50#[derive(Debug)]
51pub struct MergeIO<R, W>
52where
53    R: AsyncRead + Unpin,
54    W: AsyncWrite + Unpin,
55{
56    reader: R,
57    writer: W,
58}
59
60impl<R, W> MergeIO<R, W>
61where
62    R: AsyncRead + Unpin,
63    W: AsyncWrite + Unpin,
64{
65    /// Creates new [`MergeIO`](crate::MergeIO), that reads to `reader` and
66    /// writes to `writer`.
67    pub fn new(reader: R, writer: W) -> Self {
68        MergeIO { reader, writer }
69    }
70
71    /// Provides access to `reader`.
72    pub fn reader(&self) -> &R {
73        &self.reader
74    }
75
76    /// Provides access to `writer`.
77    pub fn writer(&self) -> &W {
78        &self.writer
79    }
80
81    /// Provides `mut` access to `reader`.
82    pub fn reader_mut(&mut self) -> &mut R {
83        &mut self.reader
84    }
85
86    /// Provides `mut` access to `writer`.
87    pub fn writer_mut(&mut self) -> &mut W {
88        &mut self.writer
89    }
90
91    /// Deconstructs `MergeIO` into the `reader` and `writer`.
92    pub fn into_inner(self) -> (R, W) {
93        (self.reader, self.writer)
94    }
95}
96
97impl<R, W> AsyncRead for MergeIO<R, W>
98where
99    R: AsyncRead + Unpin,
100    W: AsyncWrite + Unpin,
101{
102    fn poll_read(
103        self: Pin<&mut Self>,
104        cx: &mut Context<'_>,
105        buf: &mut [u8],
106    ) -> Poll<Result<usize>> {
107        AsyncRead::poll_read(Pin::new(&mut self.get_mut().reader), cx, buf)
108    }
109
110    fn poll_read_vectored(
111        self: Pin<&mut Self>,
112        cx: &mut Context<'_>,
113        bufs: &mut [IoSliceMut<'_>],
114    ) -> Poll<Result<usize>> {
115        AsyncRead::poll_read_vectored(Pin::new(&mut self.get_mut().reader), cx, bufs)
116    }
117}
118
119impl<R, W> AsyncWrite for MergeIO<R, W>
120where
121    R: AsyncRead + Unpin,
122    W: AsyncWrite + Unpin,
123{
124    fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
125        AsyncWrite::poll_write(Pin::new(&mut self.get_mut().writer), cx, buf)
126    }
127
128    fn poll_write_vectored(
129        self: Pin<&mut Self>,
130        cx: &mut Context<'_>,
131        bufs: &[IoSlice<'_>],
132    ) -> Poll<Result<usize>> {
133        AsyncWrite::poll_write_vectored(Pin::new(&mut self.get_mut().writer), cx, bufs)
134    }
135
136    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
137        AsyncWrite::poll_flush(Pin::new(&mut self.get_mut().writer), cx)
138    }
139
140    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
141        AsyncWrite::poll_close(Pin::new(&mut self.get_mut().writer), cx)
142    }
143}