Expand description
Minimal traits for synchronous, fallible, pull-based item sources.
This module defines two related traits:
TryNext
— a context-free, fallible producer of items,TryNextWithContext
— a context-aware variant that allows the caller to supply mutable external state on each iteration step.
Both traits follow the same basic pattern: they represent a source that can attempt to produce the next item, which may succeed, fail, or signal the end of the sequence.
§Core idea
Each try_next*
method call returns a Result
with three possible outcomes:
Ok(Some(item))
— a successfully produced item,Ok(None)
— no more items are available (the source is exhausted),Err(error)
— an error occurred while trying to produce the next item.
These traits are synchronous — each call blocks until a result is ready.
They are suitable for ordinary blocking or CPU-bound producers such as parsers,
generators, or readers. For asynchronous, non-blocking sources, use
futures::TryStream
.
§TryNext
The simplest case: a self-contained, fallible producer that doesn’t depend on any external context.
use try_next::TryNext;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MyError { Broken }
struct Demo { state: u8 }
impl TryNext for Demo {
type Item = u8;
type Error = MyError;
fn try_next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
match self.state {
0..=2 => {
let v = self.state;
self.state += 1;
Ok(Some(v))
}
3 => {
self.state += 1;
Ok(None)
}
_ => Err(MyError::Broken),
}
}
}
let mut src = Demo { state: 0 };
assert_eq!(src.try_next(), Ok(Some(0)));
assert_eq!(src.try_next(), Ok(Some(1)));
assert_eq!(src.try_next(), Ok(Some(2)));
assert_eq!(src.try_next(), Ok(None));
assert_eq!(src.try_next(), Err(MyError::Broken));
§TryNextWithContext
A generalization of TryNext
that allows each call to [try_next_with_context
]
to receive a mutable reference to a caller-supplied context.
The context can hold shared mutable state, configuration data, or external resources such as file handles, buffers, or clients. This pattern is useful when the producer needs external help or coordination to produce the next item, while keeping the trait itself simple and generic.
use try_next::TryNextWithContext;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MyError { Fail }
struct Producer;
struct Ctx { next_val: u8 }
impl TryNextWithContext for Producer {
type Item = u8;
type Error = MyError;
type Context = Ctx;
fn try_next_with_context(
&mut self,
ctx: &mut Self::Context,
) -> Result<Option<Self::Item>, Self::Error> {
if ctx.next_val < 3 {
let v = ctx.next_val;
ctx.next_val += 1;
Ok(Some(v))
} else {
Ok(None)
}
}
}
let mut producer = Producer;
let mut ctx = Ctx { next_val: 0 };
assert_eq!(producer.try_next_with_context(&mut ctx), Ok(Some(0)));
assert_eq!(producer.try_next_with_context(&mut ctx), Ok(Some(1)));
assert_eq!(producer.try_next_with_context(&mut ctx), Ok(Some(2)));
assert_eq!(producer.try_next_with_context(&mut ctx), Ok(None));
§Design notes
- Both traits are deliberately minimal: they define no combinators or adapters. Their purpose is to provide a simple, low-level interface for fallible, stepwise data production.
TryNextWithContext
can often serve as a building block for adapters that integrate external state or resources.- These traits are a good fit for incremental or stateful producers such as parsers, lexers, tokenizers, and other components that advance in discrete steps while potentially failing mid-stream.
- For richer iterator-like abstractions, consider crates like
fallible-iterator
orfallible-streaming-iterator
.
§See also
std::io::Read
— The standard synchronous, fallible, pull-based trait for reading bytes. These traits generalize that idea to arbitrary item types.Iterator<Item = Result<T, E>>
— The idiomatic pattern for representing fallible iteration in the standard library.futures::TryStream
— The asynchronous equivalent of this pattern.
Traits§
- TryNext
- Context-free, fallible producer.
- TryNext
With Context - Context-aware, fallible producer.