| 
1 | 1 | //! Compatibility between the `tokio::io` and `futures-io` versions of the  | 
2 | 2 | //! `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 | +
  | 
3 | 108 | use pin_project_lite::pin_project;  | 
4 | 109 | use std::io;  | 
5 | 110 | use std::pin::Pin;  | 
 | 
0 commit comments