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.

Library
Cargo
v0.3.0
63stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity8
Maintenance20
Community44
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture78
Code Quality68
Innovation55
Learning Curve45

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 FallibleIterator trait with fallible equivalents of nearly every std::iter::Iterator method (map, filter, fold, try_fold, collect, count, zip, and more)
  • DoubleEndedFallibleIterator for reverse iteration (next_back, rfold, try_rfold) and IntoFallibleIterator for 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() and IteratorExt to bridge standard Result-yielding iterators into and out of the fallible world, plus Iterator::unwrap to go the other direction
  • no_std compatibility by default, with optional alloc and std feature flags that add Box, Vec, BTreeMap/BTreeSet, and (with std) HashMap/HashSet implementations

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 in libstd
  • Replacing manual for item in iter { let item = item?; ... } unwrap loops with fallible combinator chains like map/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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search