Rust Streams and StreamExt
The Stream trait
- Lives in
futures-core(not in std, not stabilized as of Rust 1.85) - Async equivalent of
Iterator— yields items viapoll_next() - You almost never call
poll_nextdirectly; you use combinator extensions
Two competing StreamExt traits
futures_util::StreamExt
- Full combinator set:
map,filter,take,next,collect,split,forward,zip, etc. split()works on types that implement bothStreamandSink(e.g. a WebSocket). It consumes the value and returns two independent halves: aSplitStream(read side) and aSplitSink(write side). This lets you move each half into a separate concurrent task — you can’t do&mut socketin two places, but you can ownsenderin one task andreceiverin another. See Axum WebSocket patterns for the concrete use case.SinkExtprovides.send()on the write half after splitting- Heavier dependency — pulls in all of
futures-util
tokio_stream::StreamExt
- Lighter subset from the tokio ecosystem
- Has
next,map,filter,take,collect,timeout— but nosplit() - Exists because tokio wanted a lighter dep than all of
futures-util
Rule of thumb
If you already need futures-util (e.g., for split() or SinkExt on WebSocket split halves), just use futures_util::StreamExt everywhere. Mixing both causes ambiguity errors.
tokio_stream::wrappers
Adapters that wrap tokio types into Stream:
IntervalStream— wrapstokio::time::IntervalBroadcastStream— wrapsbroadcast::Receiver(used in Axum WebSocket patterns)ReceiverStream— wrapsmpsc::ReceiverUnboundedReceiverStream— wrapsmpsc::UnboundedReceiver
futures_util::stream::unfold
State machine stream builder. Takes an initial state and an async closure:
use futures_util::stream::unfold;
let stream = unfold(0u32, |state| async move {
if state < 5 {
Some((state * 2, state + 1)) // (item_to_yield, next_state)
} else {
None // stream ends
}
});- Returns
Some((item, next_state))to yield an item and continue - Returns
Noneto end the stream - Useful for paginated API calls, file chunking, or any stateful iteration
See also
- Async — Rust async/await fundamentals
- Axum WebSocket patterns — practical use of streams with WebSockets
- Tokio Runtime — the runtime powering tokio_stream