Skip to content

Commit ff3f2a8

Browse files
authored
io: add SimplexStream (#6589)
1 parent 5b9a290 commit ff3f2a8

File tree

3 files changed

+72
-17
lines changed

3 files changed

+72
-17
lines changed

tokio/src/io/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ cfg_io_util! {
271271
pub(crate) mod seek;
272272
pub(crate) mod util;
273273
pub use util::{
274-
copy, copy_bidirectional, copy_bidirectional_with_sizes, copy_buf, duplex, empty, repeat, sink, AsyncBufReadExt, AsyncReadExt, AsyncSeekExt, AsyncWriteExt,
275-
BufReader, BufStream, BufWriter, DuplexStream, Empty, Lines, Repeat, Sink, Split, Take,
274+
copy, copy_bidirectional, copy_bidirectional_with_sizes, copy_buf, duplex, empty, repeat, sink, simplex, AsyncBufReadExt, AsyncReadExt, AsyncSeekExt, AsyncWriteExt,
275+
BufReader, BufStream, BufWriter, DuplexStream, Empty, Lines, Repeat, Sink, Split, Take, SimplexStream,
276276
};
277277
}
278278

tokio/src/io/util/mem.rs

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! In-process memory IO types.
22
3-
use crate::io::{AsyncRead, AsyncWrite, ReadBuf};
3+
use crate::io::{split, AsyncRead, AsyncWrite, ReadBuf, ReadHalf, WriteHalf};
44
use crate::loom::sync::Mutex;
55

66
use bytes::{Buf, BytesMut};
@@ -47,15 +47,34 @@ use std::{
4747
#[derive(Debug)]
4848
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
4949
pub struct DuplexStream {
50-
read: Arc<Mutex<Pipe>>,
51-
write: Arc<Mutex<Pipe>>,
50+
read: Arc<Mutex<SimplexStream>>,
51+
write: Arc<Mutex<SimplexStream>>,
5252
}
5353

54-
/// A unidirectional IO over a piece of memory.
54+
/// A unidirectional pipe to read and write bytes in memory.
5555
///
56-
/// Data can be written to the pipe, and reading will return that data.
56+
/// It can be constructed by [`simplex`] function which will create a pair of
57+
/// reader and writer or by calling [`SimplexStream::new_unsplit`] that will
58+
/// create a handle for both reading and writing.
59+
///
60+
/// # Example
61+
///
62+
/// ```
63+
/// # async fn ex() -> std::io::Result<()> {
64+
/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
65+
/// let (mut receiver, mut sender) = tokio::io::simplex(64);
66+
///
67+
/// sender.write_all(b"ping").await?;
68+
///
69+
/// let mut buf = [0u8; 4];
70+
/// receiver.read_exact(&mut buf).await?;
71+
/// assert_eq!(&buf, b"ping");
72+
/// # Ok(())
73+
/// # }
74+
/// ```
5775
#[derive(Debug)]
58-
struct Pipe {
76+
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
77+
pub struct SimplexStream {
5978
/// The buffer storing the bytes written, also read from.
6079
///
6180
/// Using a `BytesMut` because it has efficient `Buf` and `BufMut`
@@ -83,8 +102,8 @@ struct Pipe {
83102
/// written to a side before the write returns `Poll::Pending`.
84103
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
85104
pub fn duplex(max_buf_size: usize) -> (DuplexStream, DuplexStream) {
86-
let one = Arc::new(Mutex::new(Pipe::new(max_buf_size)));
87-
let two = Arc::new(Mutex::new(Pipe::new(max_buf_size)));
105+
let one = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
106+
let two = Arc::new(Mutex::new(SimplexStream::new_unsplit(max_buf_size)));
88107

89108
(
90109
DuplexStream {
@@ -161,11 +180,47 @@ impl Drop for DuplexStream {
161180
}
162181
}
163182

164-
// ===== impl Pipe =====
183+
// ===== impl SimplexStream =====
184+
185+
/// Creates unidirectional buffer that acts like in memory pipe.
186+
///
187+
/// The `max_buf_size` argument is the maximum amount of bytes that can be
188+
/// written to a buffer before the it returns `Poll::Pending`.
189+
///
190+
/// # Unify reader and writer
191+
///
192+
/// The reader and writer half can be unified into a single structure
193+
/// of `SimplexStream` that supports both reading and writing or
194+
/// the `SimplexStream` can be already created as unified structure
195+
/// using [`SimplexStream::new_unsplit()`].
196+
///
197+
/// ```
198+
/// # async fn ex() -> std::io::Result<()> {
199+
/// # use tokio::io::{AsyncReadExt, AsyncWriteExt};
200+
/// let (writer, reader) = tokio::io::simplex(64);
201+
/// let mut simplex_stream = writer.unsplit(reader);
202+
/// simplex_stream.write_all(b"hello").await?;
203+
///
204+
/// let mut buf = [0u8; 5];
205+
/// simplex_stream.read_exact(&mut buf).await?;
206+
/// assert_eq!(&buf, b"hello");
207+
/// # Ok(())
208+
/// # }
209+
/// ```
210+
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
211+
pub fn simplex(max_buf_size: usize) -> (ReadHalf<SimplexStream>, WriteHalf<SimplexStream>) {
212+
split(SimplexStream::new_unsplit(max_buf_size))
213+
}
165214

166-
impl Pipe {
167-
fn new(max_buf_size: usize) -> Self {
168-
Pipe {
215+
impl SimplexStream {
216+
/// Creates unidirectional buffer that acts like in memory pipe. To create split
217+
/// version with separate reader and writer you can use [`simplex`] function.
218+
///
219+
/// The `max_buf_size` argument is the maximum amount of bytes that can be
220+
/// written to a buffer before the it returns `Poll::Pending`.
221+
#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
222+
pub fn new_unsplit(max_buf_size: usize) -> SimplexStream {
223+
SimplexStream {
169224
buffer: BytesMut::new(),
170225
is_closed: false,
171226
max_buf_size,
@@ -269,7 +324,7 @@ impl Pipe {
269324
}
270325
}
271326

272-
impl AsyncRead for Pipe {
327+
impl AsyncRead for SimplexStream {
273328
cfg_coop! {
274329
fn poll_read(
275330
self: Pin<&mut Self>,
@@ -299,7 +354,7 @@ impl AsyncRead for Pipe {
299354
}
300355
}
301356

302-
impl AsyncWrite for Pipe {
357+
impl AsyncWrite for SimplexStream {
303358
cfg_coop! {
304359
fn poll_write(
305360
self: Pin<&mut Self>,

tokio/src/io/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ cfg_io_util! {
4242
pub use lines::Lines;
4343

4444
mod mem;
45-
pub use mem::{duplex, DuplexStream};
45+
pub use mem::{duplex, simplex, DuplexStream, SimplexStream};
4646

4747
mod read;
4848
mod read_buf;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy