fallible-iterator
Iterator traits for Rust that let iteration itself return a Result, so map, filter, and fold propagate errors instead of forcing unwraps in every loop.
Repository Health
Technical Analysis
fallible-iterator provides a FallibleIterator trait that mirrors Rust’s standard Iterator trait almost method-for-method, except every operation returns Result<Option<Self::Item>, Self::Error> instead of a plain Option<T>. That means iteration itself, not just individual item access, can fail — errors surface through ? at each step rather than requiring callers to unwrap or panic inside a loop.
The crate ships a full adaptor suite (Map, Filter, FlatMap, Scan, Peekable, Zip, Rev, Cycle, and more) plus a DoubleEndedFallibleIterator trait for reverse iteration, convert() to wrap an existing Iterator<Item = Result<T, E>>, and IteratorExt/unwrap() to bridge back to the standard library. It is no_std by default with optional alloc and std feature flags, making it a natural fit for parsers, database drivers, and embedded code that need chainable iterator ergonomics without giving up explicit, typed error handling.
What You Get
- The
FallibleIteratortrait with fallible equivalents of nearly everystd::iter::Iteratormethod (map,filter,fold,try_fold,collect,count,zip, and more) DoubleEndedFallibleIteratorfor reverse iteration (next_back,rfold,try_rfold) andIntoFallibleIteratorfor converting owned types into the trait- Adaptor structs (
Map,Filter,FlatMap,Flatten,Peekable,Scan,Cycle,StepBy,Rev,Enumerate,Chain,Fuse, and others) implementing the fallible protocol convert()andIteratorExtto bridge standardResult-yielding iterators into and out of the fallible world, plusIterator::unwrapto go the other directionno_stdcompatibility by default, with optionalallocandstdfeature flags that addBox,Vec,BTreeMap/BTreeSet, and (withstd)HashMap/HashSetimplementations
Common Use Cases
- Iterating over I/O-bound sources (readers, sockets, cursors) where each
next()call can itself fail - Building database drivers or parsers that expose row or token iteration as a stream of
Results - Writing
no_std/embedded code that still wants ergonomic, chainable iterator adaptors without pulling inlibstd - Replacing manual
for item in iter { let item = item?; ... }unwrap loops with fallible combinator chains likemap/filter/collect
Under The Hood
Architecture
The crate centers on a single core trait, FallibleIterator (src/lib.rs:113), whose next() returns Result<Option<Self::Item>, Self::Error>; nearly every combinator method (map, filter, fold, try_fold, and dozens more) is a default method that wraps self in a small adaptor struct (Map, Filter, FlatMap, Scan, Peekable, and so on) holding the inner iterator plus adaptor state such as closures or PhantomData markers, and each adaptor re-implements FallibleIterator recursively over its inner type. A companion DoubleEndedFallibleIterator trait (src/lib.rs:1055) adds reverse iteration, and IntoFallibleIterator (src/lib.rs:1110) together with the free function convert() (src/lib.rs:1411, backed by a Convert struct) and IteratorExt/Iterator::unwrap bridge to and from std::iter::Iterator. There is no runtime state machine or I/O anywhere in the crate — it is entirely generic, zero-cost composition of single-purpose adaptor structs, so any change to the core trait’s next signature would ripple through every adaptor simultaneously since they all delegate to the same Result-returning contract.
Tech Stack
The crate targets Rust edition 2018, is dual-licensed MIT/Apache-2.0, and declares zero external dependencies — it builds directly on core and an optional alloc crate, with #![no_std] set at the crate root. Cargo features are minimal and additive: alloc (enabled by default) and a legacy std flag retained for backwards compatibility. CI (.github/workflows/rust.yml) uses cargo-hack to build and test every feature combination across stable, beta, nightly, and a pinned 1.36.0 MSRV toolchain, reflecting the crate’s role as a low-level, dependency-free foundation rather than an application.
Code Quality
A dedicated src/test.rs module contains 43 #[test] functions covering the core adaptors (map, filter, scan, fold, zip, peekable, and more), executed via cargo hack test --feature-powerset --all-targets across the full CI toolchain matrix, giving reasonable confidence that behavior holds under every feature-flag combination. Error handling is the crate’s entire purpose — every method threads a generic Self::Error type explicitly rather than swallowing failures, and an internal FoldStop<T, E> enum (src/lib.rs:83) cleanly separates an early break from a propagated error inside fold-based implementations. Naming closely mirrors std::iter::Iterator for immediate familiarity to Rust developers. There is no visible Clippy or rustfmt CI step, and testing is limited to the in-crate unit suite with no fuzzing or property-based tests.
What Makes It Unique
The crate is not a novel algorithm so much as a disciplined, complete application of Rust’s trait system to a well-known ergonomics gap: the standard Iterator trait has no first-class way to represent an iteration step that can fail. Rather than trying to retrofit Result handling onto Iterator itself, fallible-iterator defines a parallel trait that reimplements nearly the entire std::iter::Iterator surface as default methods, preserving full API familiarity while remaining no_std-compatible from the start. That combination of near-total API parity plus zero mandatory dependencies is the crate’s distinguishing design choice, even though the general “fallible iterator” pattern itself is a known category rather than something original to this project.