readwrite/
lib.rs

1#![deny(missing_docs)]
2#![forbid(unsafe_code)]
3
4//! Given two things, one of which implements `std::io::Read` and other implements `std::io::Write`, make a single socket-like object which implmenets `Read + Write`. Note that you can't write to it while waiting for data to come from read part.
5//!
6//! There is also AsyncRead / AsyncWrite analogue, see `ReadWriteAsync` struct.
7
8use std::io::{Read, Result, Write};
9
10/// Combined reader and writer
11pub struct ReadWrite<R: Read, W: Write>(pub R, pub W);
12
13impl<R: Read, W: Write> From<(R, W)> for ReadWrite<R, W> {
14    fn from((r, w): (R, W)) -> Self {
15        ReadWrite(r, w)
16    }
17}
18impl<R: Read, W: Write> ReadWrite<R, W> {
19    /// Bundle separate reader and writer into a combined pseudo-socket
20    pub fn new(r: R, w: W) -> Self {
21        ReadWrite(r, w)
22    }
23    /// Borrow inner objects
24    pub fn borrow(&self) -> (&R, &W) {
25        (&self.0, &self.1)
26    }
27    /// Borrow the reader
28    pub fn borrow_read(&self) -> &R {
29        &self.0
30    }
31    /// Borrow the writer
32    pub fn borrow_write(&self) -> &W {
33        &self.1
34    }
35    /// Mutably borrow inner objects
36    pub fn borrow_mut(&mut self) -> (&mut R, &mut W) {
37        (&mut self.0, &mut self.1)
38    }
39    /// Mutably borrow the reader
40    pub fn borrow_mut_read(&mut self) -> &mut R {
41        &mut self.0
42    }
43    /// Mutably borrow the writer
44    pub fn borrow_mut_write(&mut self) -> &mut W {
45        &mut self.1
46    }
47    /// Convert ReadWrite back into individual reader and writer pair
48    pub fn into_inner(self) -> (R, W) {
49        (self.0, self.1)
50    }
51    /// Convert ReadWrite back into the reader, dropping the writer
52    pub fn into_reader(self) -> R {
53        self.0
54    }
55    /// Convert ReadWrite back into the writer, dropping the reader
56    pub fn into_writer(self) -> W {
57        self.1
58    }
59}
60
61impl<R: Read, W: Write> Read for ReadWrite<R, W> {
62    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
63        self.0.read(buf)
64    }
65
66    fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> Result<usize> {
67        self.0.read_vectored(bufs)
68    }
69}
70impl<R: Read, W: Write> Write for ReadWrite<R, W> {
71    fn write(&mut self, buf: &[u8]) -> Result<usize> {
72        self.1.write(buf)
73    }
74    fn flush(&mut self) -> Result<()> {
75        self.1.flush()
76    }
77
78    fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> Result<usize> {
79        self.1.write_vectored(bufs)
80    }
81}
82
83#[cfg(all(feature = "tokio"))]
84mod tokio {
85    use tokio_dep::io::{AsyncRead, AsyncWrite};
86
87    use std::pin::Pin;
88
89    pin_project_lite::pin_project! {
90        /// Combined async reader and writer, `tokio 1` version.
91        /// Note that this struct is only present in `readwrite` if "tokio" Cargo feature is enabled.
92        pub struct ReadWriteTokio<R, W> {
93            #[pin]
94            r: R,
95            #[pin]
96            w: W,
97        }
98    }
99
100    impl<R: AsyncRead, W: AsyncWrite> From<(R, W)> for ReadWriteTokio<R, W> {
101        fn from((r, w): (R, W)) -> Self {
102            ReadWriteTokio { r, w }
103        }
104    }
105    impl<R: AsyncRead, W: AsyncWrite> ReadWriteTokio<R, W> {
106        /// Bundle separate async reader and writer into a combined pseudo-socket
107        pub fn new(r: R, w: W) -> Self {
108            ReadWriteTokio { r, w }
109        }
110        /// Borrow inner objects
111        pub fn borrow(&self) -> (&R, &W) {
112            (&self.r, &self.w)
113        }
114        /// Borrow the reader
115        pub fn borrow_read(&self) -> &R {
116            &self.r
117        }
118        /// Borrow the writer
119        pub fn borrow_write(&self) -> &W {
120            &self.w
121        }
122        /// Mutably borrow inner objects
123        pub fn borrow_mut(&mut self) -> (&mut R, &mut W) {
124            (&mut self.r, &mut self.w)
125        }
126        /// Mutably borrow the reader
127        pub fn borrow_mut_read(&mut self) -> &mut R {
128            &mut self.r
129        }
130        /// Mutably borrow the writer
131        pub fn borrow_mut_write(&mut self) -> &mut W {
132            &mut self.w
133        }
134        /// Convert ReadWrite back into individual reader and writer pair
135        pub fn into_inner(self) -> (R, W) {
136            (self.r, self.w)
137        }
138        /// Convert ReadWrite back into the reader, dropping the writer
139        pub fn into_reader(self) -> R {
140            self.r
141        }
142        /// Convert ReadWrite back into the writer, dropping the reader
143        pub fn into_writer(self) -> W {
144            self.w
145        }
146
147        /// Borrow pinned reader and writer
148        pub fn borrow_pin(self: Pin<&mut Self>) -> (Pin<&mut R>, Pin<&mut W>) {
149            let p = self.project();
150            (p.r, p.w)
151        }
152        /// Borrow pinned reader
153        pub fn borrow_pin_read(self: Pin<&mut Self>) -> Pin<&mut R> {
154            self.project().r
155        }
156        /// Borrow pinned writer
157        pub fn borrow_pin_write(self: Pin<&mut Self>) -> Pin<&mut W> {
158            self.project().w
159        }
160    }
161
162    impl<R: AsyncRead, W> AsyncRead for ReadWriteTokio<R, W> {
163        fn poll_read(
164            self: std::pin::Pin<&mut Self>,
165            cx: &mut std::task::Context<'_>,
166            buf: &mut tokio_dep::io::ReadBuf<'_>,
167        ) -> std::task::Poll<std::io::Result<()>> {
168            AsyncRead::poll_read(self.project().r, cx, buf)
169        }
170    }
171
172    impl<R, W: AsyncWrite> AsyncWrite for ReadWriteTokio<R, W> {
173        fn poll_write(
174            self: Pin<&mut Self>,
175            cx: &mut std::task::Context<'_>,
176            buf: &[u8],
177        ) -> std::task::Poll<Result<usize, std::io::Error>> {
178            self.project().w.poll_write(cx, buf)
179        }
180
181        fn poll_flush(
182            self: Pin<&mut Self>,
183            cx: &mut std::task::Context<'_>,
184        ) -> std::task::Poll<Result<(), std::io::Error>> {
185            self.project().w.poll_flush(cx)
186        }
187
188        fn poll_shutdown(
189            self: Pin<&mut Self>,
190            cx: &mut std::task::Context<'_>,
191        ) -> std::task::Poll<Result<(), std::io::Error>> {
192            self.project().w.poll_shutdown(cx)
193        }
194
195        fn poll_write_vectored(
196            self: Pin<&mut Self>,
197            cx: &mut std::task::Context<'_>,
198            bufs: &[std::io::IoSlice<'_>],
199        ) -> std::task::Poll<Result<usize, std::io::Error>> {
200            self.project().w.poll_write_vectored(cx, bufs)
201        }
202
203        fn is_write_vectored(&self) -> bool {
204            self.w.is_write_vectored()
205        }
206    }
207}
208#[cfg(all(feature = "tokio"))]
209pub use tokio::ReadWriteTokio;
210
211#[cfg(all(feature = "asyncstd"))]
212mod asyncstd {
213    use futures::io::{AsyncRead, AsyncWrite};
214
215    use std::pin::Pin;
216
217    pin_project_lite::pin_project! {
218        /// Combined async reader and writer, `futures 0.3` version.
219        /// Note that this struct is only present in `readwrite` if "asyncstd" Cargo feature is enabled.
220        pub struct ReadWriteAsyncstd<R, W> {
221            #[pin]
222            r: R,
223            #[pin]
224            w: W,
225        }
226    }
227
228    impl<R: AsyncRead, W: AsyncWrite> From<(R, W)> for ReadWriteAsyncstd<R, W> {
229        fn from((r, w): (R, W)) -> Self {
230            ReadWriteAsyncstd { r, w }
231        }
232    }
233    impl<R: AsyncRead, W: AsyncWrite> ReadWriteAsyncstd<R, W> {
234        /// Bundle separate async reader and writer into a combined pseudo-socket
235        pub fn new(r: R, w: W) -> Self {
236            ReadWriteAsyncstd { r, w }
237        }
238        /// Borrow inner objects
239        pub fn borrow(&self) -> (&R, &W) {
240            (&self.r, &self.w)
241        }
242        /// Borrow the reader
243        pub fn borrow_read(&self) -> &R {
244            &self.r
245        }
246        /// Borrow the writer
247        pub fn borrow_write(&self) -> &W {
248            &self.w
249        }
250        /// Mutably borrow inner objects
251        pub fn borrow_mut(&mut self) -> (&mut R, &mut W) {
252            (&mut self.r, &mut self.w)
253        }
254        /// Mutably borrow the reader
255        pub fn borrow_mut_read(&mut self) -> &mut R {
256            &mut self.r
257        }
258        /// Mutably borrow the writer
259        pub fn borrow_mut_write(&mut self) -> &mut W {
260            &mut self.w
261        }
262        /// Convert ReadWrite back into individual reader and writer pair
263        pub fn into_inner(self) -> (R, W) {
264            (self.r, self.w)
265        }
266        /// Convert ReadWrite back into the reader, dropping the writer
267        pub fn into_reader(self) -> R {
268            self.r
269        }
270        /// Convert ReadWrite back into the writer, dropping the reader
271        pub fn into_writer(self) -> W {
272            self.w
273        }
274
275        /// Borrow pinned reader and writer
276        pub fn borrow_pin(self: Pin<&mut Self>) -> (Pin<&mut R>, Pin<&mut W>) {
277            let p = self.project();
278            (p.r, p.w)
279        }
280        /// Borrow pinned reader
281        pub fn borrow_pin_read(self: Pin<&mut Self>) -> Pin<&mut R> {
282            self.project().r
283        }
284        /// Borrow pinned writer
285        pub fn borrow_pin_write(self: Pin<&mut Self>) -> Pin<&mut W> {
286            self.project().w
287        }
288    }
289
290    impl<R: AsyncRead, W> AsyncRead for ReadWriteAsyncstd<R, W> {
291        fn poll_read(
292            self: Pin<&mut Self>,
293            cx: &mut std::task::Context<'_>,
294            buf: &mut [u8],
295        ) -> std::task::Poll<std::io::Result<usize>> {
296            self.project().r.poll_read(cx, buf)
297        }
298
299        fn poll_read_vectored(
300            self: Pin<&mut Self>,
301            cx: &mut std::task::Context<'_>,
302            bufs: &mut [std::io::IoSliceMut<'_>],
303        ) -> std::task::Poll<std::io::Result<usize>> {
304            self.project().r.poll_read_vectored(cx, bufs)
305        }
306    }
307
308    impl<R, W: AsyncWrite> AsyncWrite for ReadWriteAsyncstd<R, W> {
309        fn poll_write(
310            self: Pin<&mut Self>,
311            cx: &mut std::task::Context<'_>,
312            buf: &[u8],
313        ) -> std::task::Poll<std::io::Result<usize>> {
314            self.project().w.poll_write(cx, buf)
315        }
316
317        fn poll_flush(
318            self: Pin<&mut Self>,
319            cx: &mut std::task::Context<'_>,
320        ) -> std::task::Poll<std::io::Result<()>> {
321            self.project().w.poll_flush(cx)
322        }
323
324        fn poll_close(
325            self: Pin<&mut Self>,
326            cx: &mut std::task::Context<'_>,
327        ) -> std::task::Poll<std::io::Result<()>> {
328            self.project().w.poll_close(cx)
329        }
330
331        fn poll_write_vectored(
332            self: Pin<&mut Self>,
333            cx: &mut std::task::Context<'_>,
334            bufs: &[std::io::IoSlice<'_>],
335        ) -> std::task::Poll<std::io::Result<usize>> {
336            self.project().w.poll_write_vectored(cx, bufs)
337        }
338    }
339}
340#[cfg(all(feature = "asyncstd"))]
341pub use asyncstd::ReadWriteAsyncstd;