Skip to main content

Crate collect_failable

Crate collect_failable 

Source
Expand description

§collect_failable

Build Docs Crates.io dependency status codecov GitHub License

A set of traits for collecting values into containers that must uphold invariants during construction or extension. These traits let you propagate structured errors instead of panicking or silently discarding data. Examples include preventing duplicate keys in a HashMap or respecting capacity limits in types like ArrayVec.

§Installation

It’s on crates.io.

§Traits

This crate provides several complementary traits for failable collection:

Additionally, several implementations are provided for common and popular containers. See the implementations section for more details.

§Error Recovery

Implementations from this crate make a special emphasis on being able to recover all data in the case of collection or extension failure. The CollectError type will contain both the (potentially partially iterated) iterator, the items collected up to the point of failure, and the item that caused the failure, and can be converted back into an iterator if desired.

§Features

This crate provides the following optional features:

FeatureDescriptionDependencies
DefaultDefault features of the cratealloc, std, unsafe, tuples
allocEnables support for allocation-dependent types (BTreeMap, BTreeSet) and built-in error types.-
stdEnables standard library support, including HashMap and HashSet implementations. When disabled, the crate is no_std compatible.alloc
unsafeEnables TryFromIterator implementations for arrays using unsafe code.-
tuplesEnables tuple extension (TryExtend for tuples) and TryUnzip trait.either
arrayvecEnables TryFromIterator and TryExtend implementations for ArrayVec.arrayvec
hashbrownEnables TryFromIterator and TryExtend implementations for hashbrown::HashMap and hashbrown::HashSet.alloc, hashbrown
indexmapEnables TryFromIterator and TryExtend implementations for IndexMap and IndexSet.alloc, indexmap

§no_std Support

This crate supports no_std environments when the std feature is disabled. The alloc feature provides allocation-dependent functionality (BTreeMap, BTreeSet, etc.) without requiring the full standard library. The traits and error types are available without any features enabled.

§Usage

§TryFromIterator and TryCollectEx

Construct a container from an iterator, with errors for invalid input. This behaves like FromIterator but returns Result<Self, E> instead of panicking or ignoring failures.

use std::collections::BTreeMap;
use collect_failable::TryFromIterator;

// try_from_iter is the core method - works on any TryFromIterator implementor
let map = BTreeMap::try_from_iter([(1, "a"), (2, "b")]).expect("no duplicates");
assert_eq!(map, BTreeMap::from([(1, "a"), (2, "b")]), "should contain all values");

// duplicate keys produce an error containing the colliding item
let err = BTreeMap::try_from_iter([(1, "a"), (2, "b"), (1, "c")]).expect_err("duplicate key");
assert_eq!(err.error.item, (1, "c"), "should contain the colliding item");

// errors contain all data needed to reconstruct the consumed iterator
// order is: rejected item, then collected items, then remaining iterator
let recovered: Vec<_> = err.into_iter().collect();
assert_eq!(recovered, [(1, "c"), (1, "a"), (2, "b")]);

TryCollectEx provides a more convenient alternative, similar to collect:

use std::collections::HashMap;
use collect_failable::TryCollectEx;

let map: HashMap<_, _> = [(1, "a"), (2, "b")].into_iter().try_collect_ex().unwrap();
assert_eq!(map, HashMap::from([(1, "a"), (2, "b")]));

§TryExtend and TryExtendSafe

Extend an existing container with items that may violate its invariants. Two different trait exposes two styles of error behavior:

  • TryExtendSafestrong guarantee On an error, the container must remain unchanged.
  • TryExtendbasic guarantee The container may have partially ingested items, but must remain valid.

Use TryExtendSafe if you must avoid mutation on failure; otherwise, prefer the faster TryExtend.

use std::collections::HashMap;
use collect_failable::TryExtendSafe;

let mut map = HashMap::new();
map.try_extend_safe([(1, 2), (2, 3)]).expect("should be Ok");
assert_eq!(map, HashMap::from([(1, 2), (2, 3)]));

// on a failure, the container is not modified
map.try_extend_safe([(1, 3)]).expect_err("should be Err");
assert_eq!(map, HashMap::from([(1, 2), (2, 3)]));

§TryExtendOne

Extend a collection with a single item. This trait always provides a strong guarantee. On failure, the collection remains unchanged. Implemented as a seperate trait with no default implementation due to limitations imposed by the trait definition.

§TryUnzip

Fallible equivalent of Iterator::unzip. Given an iterator of (A, B) items, produce two collections that implement Default + TryExtend, stopping on the first failure.

use std::collections::{BTreeSet, HashSet};
use collect_failable::TryUnzip;

// Unzip into two different container types
let data = vec![(1, 'a'), (2, 'b'), (3, 'c')];
let (nums, chars): (BTreeSet<i32>, HashSet<char>) = data.into_iter().try_unzip().expect("should be ok");

assert_eq!(nums, BTreeSet::from([1, 2, 3]));
assert_eq!(chars, HashSet::from(['a', 'b', 'c']));

§Implementations

Implementations for various containers are provided.

§Tuples

Tuples of arity 2 implement TryExtend when their inner types do (requires feature tuples, enabled by default). For constructing tuple collections from IntoIterator TryUnzip is available.

§Arrays

Arrays implement TryFromIterator for IntoIterator that yield exactly the right number of elements. This uses unsafe internally and is gated behind the unsafe feature (enabled by default).

§Result

TryFromIterator is implemented for Result<C, E>, where C implements TryFromIterator<T>, similar to the FromIterator implementation for Result. This allows short-circuiting collection of failable values into a container whose construction is also failable.

Modules§

errors
Error types returned by failable collection operations.

Traits§

TryCollectEx
Extends Iterator with a failable collect method.
TryExtend
Trait for extending an existing collection from an iterator with fallible operations.
TryExtendOne
Extension trait providing convenience method for extending a collection with a single item.
TryExtendSafe
Trait for extending a collection with a strong error guarantee.
TryFromIterator
Tries to convert a IntoIterator into a container that may fail to be constructed.
TryUnzip
Extends Iterator with a failable unzip method.