stream_transfer_limit/lib.rs
1//! Byte-count transfer limits for fallible futures streams.
2//!
3//! This crate is intentionally small: it wraps a `Stream<Item = Result<T, E>>`,
4//! counts the bytes yielded by successful chunks, and returns a typed error as
5//! soon as the configured transfer limit is exceeded. This is useful when the
6//! limit is known only after request routing, authentication, or tenant lookup.
7//! The default counter type is `usize`; use `TransferLimit::<u64>::from_limit`
8//! or `TransferLimit::<u128>::from_limit` for streams that may exceed
9//! pointer-sized byte counts.
10//!
11//! ```
12//! use futures::{StreamExt, stream};
13//! use stream_transfer_limit::{TransferLimit, TransferLimitError};
14//!
15//! # futures::executor::block_on(async {
16//! let chunks = stream::iter([
17//! Ok::<_, std::io::Error>(vec![1, 2]),
18//! Ok(vec![3, 4, 5]),
19//! ]);
20//! let mut chunks = TransferLimit::new(4).wrap(chunks);
21//!
22//! assert_eq!(chunks.next().await.unwrap().unwrap(), vec![1, 2]);
23//! assert!(matches!(
24//! chunks.next().await.unwrap(),
25//! Err(TransferLimitError::LimitExceeded { limit: 4, actual: 5 })
26//! ));
27//! assert!(chunks.next().await.is_none());
28//! # });
29//! ```
30
31mod chunk;
32mod counter;
33mod error;
34mod transfer_limit;
35
36pub use chunk::ChunkLength;
37pub use counter::TransferCounter;
38pub use error::TransferLimitError;
39pub use transfer_limit::{NoopProgress, TransferLimit};
40
41#[cfg(test)]
42mod tests;