Skip to content

Commit

Permalink
Add documentation for SyncIoBridge with examples and alternatives
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathy-bajo committed Sep 3, 2024
1 parent 11f66f4 commit 3008e7b
Showing 1 changed file with 75 additions and 0 deletions.
75 changes: 75 additions & 0 deletions tokio-util/src/io/sync_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,81 @@ use tokio::io::{

/// Use a [`tokio::io::AsyncRead`] synchronously as a [`std::io::Read`] or
/// a [`tokio::io::AsyncWrite`] as a [`std::io::Write`].
///
/// # Alternatives
///
/// In many cases, there are better alternatives to using `SyncIoBridge`, especially if you
/// want to avoid blocking the async runtime. Consider the following scenarios:
///
/// ## Example 1: Hashing Data
///
/// When hashing data, using `SyncIoBridge` can lead to suboptimal performance and might not fully leverage the async capabilities of the system.
/// Instead, consider reading the data into memory and then hashing it, or processing the data in chunks.
///
/// ```rust
/// let mut data = Vec::new();
/// reader.read_to_end(&mut data).await?;
/// let hash = blake3::hash(&data);
/// ```
///
/// Or, for more complex cases:
///
/// ```rust
/// let mut data = vec![0; 64 * 1024];
/// loop {
/// let len = reader.read(&mut data).await?;
/// if len == 0 { break; }
/// hasher.update(&data[..len]);
/// }
/// let hash = hasher.finalize();
/// ```
///
/// ## Example 2: Compressing Data
///
/// When compressing data, avoid using `SyncIoBridge`` with non-async compression libraries, as it may lead to inefficient and blocking code.
/// Instead, use `async-compression`, which is designed to work with asynchronous data streams.
///
/// ```rust
/// use async_compression::tokio::write::GzipEncoder;
///
/// let mut encoder = GzipEncoder::new(writer);
/// tokio::io::copy(&mut reader, &mut encoder).await?;
/// ```
///
/// ## Example 3: Parsing JSON
///
/// When parsing `JSON` data, avoid using `SyncIoBridge` with `serde_json::from_reader` as it may cause blocking operations.
/// Instead, read the data into a `Vec<u8>` and parse it using `serde_json::from_slice`.
///
/// ```rust
/// let mut data = Vec::new();
/// reader.read_to_end(&mut data).await?;
/// let value: MyStruct = serde_json::from_slice(&data)?;
/// ```
///
/// ## Correct Usage of `SyncIoBridge` inside `spawn_blocking`
///
/// `SyncIoBridge` is mainly useful when you need to interface with synchronous libraries from an asynchronous context.
/// Here is how you can do it correctly:
///
/// ```rust
/// use tokio::task::spawn_blocking;
/// use tokio::io::AsyncReadExt;
/// use tokio_util::io::SyncIoBridge;
/// use std::fs::File;
/// use std::io::Read;
///
/// let reader = tokio::fs::File::open("data.txt").await?;
/// let sync_reader = SyncIoBridge::new(reader);
///
/// let result = spawn_blocking(move || {
/// let mut file = File::open("output.txt")?;
/// std::io::copy(&mut sync_reader, &mut file)?;
/// Ok::<_, std::io::Error>(())
/// })
/// .await??;
/// ```
///
#[derive(Debug)]
pub struct SyncIoBridge<T> {
src: T,
Expand Down

0 comments on commit 3008e7b

Please sign in to comment.