Skip to content

Commit a0af02a

Browse files
compat: add more documentation to tokio_util::compat (#7279)
1 parent 0ce3a11 commit a0af02a

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

tokio-util/src/compat.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,110 @@
11
//! Compatibility between the `tokio::io` and `futures-io` versions of the
22
//! `AsyncRead` and `AsyncWrite` traits.
3+
//!
4+
//! ## Bridging Tokio and Futures I/O with `compat()`
5+
//!
6+
//! The [`compat()`] function provides a compatibility layer that allows types implementing
7+
//! [`tokio::io::AsyncRead`] or [`tokio::io::AsyncWrite`] to be used as their
8+
//! [`futures::io::AsyncRead`] or [`futures::io::AsyncWrite`] counterparts — and vice versa.
9+
//!
10+
//! This is especially useful when working with libraries that expect I/O types from one ecosystem
11+
//! (usually `futures`) but you are using types from the other (usually `tokio`).
12+
//!
13+
//! ## Compatibility Overview
14+
//!
15+
//! | Inner Type Implements... | `Compat<T>` Implements... |
16+
//! |-----------------------------|-----------------------------|
17+
//! | [`tokio::io::AsyncRead`] | [`futures::io::AsyncRead`] |
18+
//! | [`futures::io::AsyncRead`] | [`tokio::io::AsyncRead`] |
19+
//! | [`tokio::io::AsyncWrite`] | [`futures::io::AsyncWrite`] |
20+
//! | [`futures::io::AsyncWrite`] | [`tokio::io::AsyncWrite`] |
21+
//!
22+
//! ## Feature Flag
23+
//!
24+
//! This functionality is available through the `compat` feature flag:
25+
//!
26+
//! ```toml
27+
//! tokio-util = { version = "...", features = ["compat"] }
28+
//! ```
29+
//!
30+
//! ## Example 1: Tokio -> Futures (`AsyncRead`)
31+
//!
32+
//! This example demonstrates sending data over a [`tokio::net::TcpStream`] and using
33+
//! [`futures::io::AsyncReadExt::read`] from the `futures` crate to read it after adapting the
34+
//! stream via [`compat()`].
35+
//!
36+
//! ```no_run
37+
//! use tokio::net::{TcpListener, TcpStream};
38+
//! use tokio::io::AsyncWriteExt;
39+
//! use tokio_util::compat::TokioAsyncReadCompatExt;
40+
//! use futures::io::AsyncReadExt;
41+
//!
42+
//! #[tokio::main]
43+
//! async fn main() -> std::io::Result<()> {
44+
//! let listener = TcpListener::bind("127.0.0.1:8081").await?;
45+
//!
46+
//! tokio::spawn(async {
47+
//! let mut client = TcpStream::connect("127.0.0.1:8081").await.unwrap();
48+
//! client.write_all(b"Hello World").await.unwrap();
49+
//! });
50+
//!
51+
//! let (stream, _) = listener.accept().await?;
52+
//!
53+
//! // Adapt `tokio::TcpStream` to be used with `futures::io::AsyncReadExt`
54+
//! let mut compat_stream = stream.compat();
55+
//! let mut buffer = [0; 20];
56+
//! let n = compat_stream.read(&mut buffer).await?;
57+
//! println!("Received: {}", String::from_utf8_lossy(&buffer[..n]));
58+
//!
59+
//! Ok(())
60+
//! }
61+
//! ```
62+
//!
63+
//! ## Example 2: Futures -> Tokio (`AsyncRead`)
64+
//!
65+
//! The reverse is also possible: you can take a [`futures::io::AsyncRead`] (e.g. a cursor) and
66+
//! adapt it to be used with [`tokio::io::AsyncReadExt::read_to_end`]
67+
//!
68+
//! ```
69+
//! use futures::io::Cursor;
70+
//! use tokio_util::compat::FuturesAsyncReadCompatExt;
71+
//! use tokio::io::AsyncReadExt;
72+
//!
73+
//! fn main() {
74+
//! let future = async {
75+
//! let reader = Cursor::new(b"Hello from futures");
76+
//! let mut compat_reader = reader.compat();
77+
//! let mut buf = Vec::new();
78+
//! compat_reader.read_to_end(&mut buf).await.unwrap();
79+
//! assert_eq!(&buf, b"Hello from futures");
80+
//! };
81+
//!
82+
//! // Run the future inside a Tokio runtime
83+
//! tokio::runtime::Runtime::new().unwrap().block_on(future);
84+
//! }
85+
//! ```
86+
//!
87+
//! ## Common Use Cases
88+
//!
89+
//! - Using `tokio` sockets with `async-tungstenite`, `async-compression`, or `futures-rs`-based
90+
//! libraries.
91+
//! - Bridging I/O interfaces between mixed-ecosystem libraries.
92+
//! - Avoiding rewrites or duplication of I/O code in async environments.
93+
//!
94+
//! ## See Also
95+
//!
96+
//! - [`Compat`] type
97+
//! - [`TokioAsyncReadCompatExt`]
98+
//! - [`FuturesAsyncReadCompatExt`]
99+
//! - [`tokio::io`]
100+
//! - [`futures::io`]
101+
//!
102+
//! [`futures::io`]: https://docs.rs/futures/latest/futures/io/
103+
//! [`futures::io::AsyncRead`]: https://docs.rs/futures/latest/futures/io/trait.AsyncRead.html
104+
//! [`futures::io::AsyncWrite`]: https://docs.rs/futures/latest/futures/io/trait.AsyncWrite.html
105+
//! [`futures::io::AsyncReadExt::read`]: https://docs.rs/futures/latest/futures/io/trait.AsyncReadExt.html#method.read
106+
//! [`compat()`]: TokioAsyncReadCompatExt::compat
107+
3108
use pin_project_lite::pin_project;
4109
use std::io;
5110
use std::pin::Pin;

tokio-util/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
//! This crate is not versioned in lockstep with the core
1717
//! [`tokio`] crate. However, `tokio-util` _will_ respect Rust's
1818
//! semantic versioning policy, especially with regard to breaking changes.
19-
//!
20-
//! [`tokio`]: https://docs.rs/tokio
2119
2220
#[macro_use]
2321
mod cfg;

0 commit comments

Comments
 (0)