{"id":35858083,"url":"https://github.com/maxmahem/collect_failable","last_synced_at":"2026-02-03T01:13:35.607Z","repository":{"id":321187492,"uuid":"1084842872","full_name":"MaxMahem/collect_failable","owner":"MaxMahem","description":"A trait that allows iterables to be failably gathered into a collection. Useful for types (such as a Map) which may have an invariant to uphold during construction.","archived":false,"fork":false,"pushed_at":"2026-01-14T06:46:03.000Z","size":491,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-14T10:27:26.839Z","etag":null,"topics":["collections","failable","hashmap","iterables","rust"],"latest_commit_sha":null,"homepage":"https://maxmahem.github.io/collect_failable/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaxMahem.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-28T08:36:24.000Z","updated_at":"2026-01-14T06:40:08.000Z","dependencies_parsed_at":"2025-10-28T10:22:34.518Z","dependency_job_id":"0cacaf7b-b69d-42ec-956c-e1835a9cd19b","html_url":"https://github.com/MaxMahem/collect_failable","commit_stats":null,"previous_names":["maxmahem/collect_failable"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/MaxMahem/collect_failable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxMahem%2Fcollect_failable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxMahem%2Fcollect_failable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxMahem%2Fcollect_failable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxMahem%2Fcollect_failable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxMahem","download_url":"https://codeload.github.com/MaxMahem/collect_failable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxMahem%2Fcollect_failable/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28754807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T13:59:49.818Z","status":"ssl_error","status_checked_at":"2026-01-25T13:59:33.728Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["collections","failable","hashmap","iterables","rust"],"created_at":"2026-01-08T10:11:42.377Z","updated_at":"2026-02-03T01:13:35.600Z","avatar_url":"https://github.com/MaxMahem.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `collect_failable`\n\n[![Build](https://github.com/MaxMahem/collect_failable/actions/workflows/build.yml/badge.svg)](https://github.com/MaxMahem/collect_failable/actions/workflows/build.yml)\n[![Docs](https://github.com/MaxMahem/collect_failable/actions/workflows/docs.yml/badge.svg)](https://maxmahem.github.io/collect_failable/collect_failable/index.html)\n[![Crates.io](https://img.shields.io/crates/v/collect_failable)](https://crates.io/crates/collect_failable)\n[![dependency status](https://deps.rs/repo/github/maxmahem/collect_failable/status.svg)](https://deps.rs/repo/github/maxmahem/collect_failable)\n[![codecov](https://codecov.io/github/MaxMahem/collect_failable/graph/badge.svg?token=6JJF59BIO3)](https://codecov.io/github/MaxMahem/collect_failable)\n![GitHub License](https://img.shields.io/github/license/maxmahem/collect_failable)\n\nA 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`.\n\n## Installation\n\nIt's on [crates.io](https://crates.io/crates/collect_failable).\n\n## Traits\n\nThis crate provides several complementary traits for failable collection:\n\n- [`TryFromIterator`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryFromIterator.html) and [`TryCollectEx`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryCollectEx.html) – failably build a container from an `IntoIterator`.\n- [`TryExtend`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtend.html), [`TryExtendSafe`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtendSafe.html) and [`TryExtendOne`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtendOne.html) – failably extend a container with an `IntoIterator`, with different error guarantees.\n- [`TryUnzip`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryUnzip.html) – failably unzip an `IntoIterator` of pairs into two containers (requires feature `tuples`, enabled by default).\n\nAdditionally, several implementations are provided for common and popular containers. See the [implementations](#implementations) section for more details.\n\n## Error Recovery\n\nImplementations from this crate make a special emphasis on being able to recover all data in the case of collection or extension failure. The [`CollectError`](https://docs.rs/collect_failable/latest/collect_failable/errors/struct.CollectError.html) 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.\n\n## Features\n\nThis crate provides the following optional features:\n\n| Feature | Description | Dependencies |\n| :--- | :--- | :--- |\n| **Default** | Default features of the crate | `alloc`, `std`, `unsafe`, `tuples` |\n| `alloc` | Enables support for allocation-dependent types (`BTreeMap`, `BTreeSet`) and built-in error types. | - |\n| `std` | Enables standard library support, including `HashMap` and `HashSet` implementations. When disabled, the crate is `no_std` compatible. | `alloc` |\n| `unsafe` | Enables `TryFromIterator` implementations for arrays using unsafe code. | - |\n| `tuples` | Enables tuple extension ([`TryExtend`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtend.html) for tuples) and [`TryUnzip`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryUnzip.html) trait. | [`either`](https://crates.io/crates/either) |\n| `arrayvec` | Enables `TryFromIterator` and `TryExtend` implementations for [`ArrayVec`](https://docs.rs/arrayvec/latest/arrayvec/struct.ArrayVec.html). | [`arrayvec`](https://crates.io/crates/arrayvec) |\n| `hashbrown` | Enables `TryFromIterator` and `TryExtend` implementations for [`hashbrown::HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html) and [`hashbrown::HashSet`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html). | `alloc`, [`hashbrown`](https://crates.io/crates/hashbrown) |\n| `indexmap` | Enables `TryFromIterator` and `TryExtend` implementations for [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/) and [`IndexSet`](https://docs.rs/indexmap/latest/indexmap/). | `alloc`, [`indexmap`](https://crates.io/crates/indexmap) |\n\n### `no_std` Support\n\nThis 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.\n\n## Usage\n\n### [`TryFromIterator`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryFromIterator.html) and [`TryCollectEx`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryCollectEx.html)\n\nConstruct a container from an iterator, with errors for invalid input. This behaves like [`FromIterator`](https://doc.rust-lang.org/std/iter/trait.FromIterator.html) but returns `Result\u003cSelf, E\u003e` instead of panicking or ignoring failures.\n\n```rust\nuse std::collections::BTreeMap;\nuse collect_failable::TryFromIterator;\n\n// try_from_iter is the core method - works on any TryFromIterator implementor\nlet map = BTreeMap::try_from_iter([(1, \"a\"), (2, \"b\")]).expect(\"no duplicates\");\nassert_eq!(map, BTreeMap::from([(1, \"a\"), (2, \"b\")]), \"should contain all values\");\n\n// duplicate keys produce an error containing the colliding item\nlet err = BTreeMap::try_from_iter([(1, \"a\"), (2, \"b\"), (1, \"c\")]).expect_err(\"duplicate key\");\nassert_eq!(err.error.item, (1, \"c\"), \"should contain the colliding item\");\n\n// errors contain all data needed to reconstruct the consumed iterator\n// order is: rejected item, then collected items, then remaining iterator\nlet recovered: Vec\u003c_\u003e = err.into_iter().collect();\nassert_eq!(recovered, [(1, \"c\"), (1, \"a\"), (2, \"b\")]);\n```\n\n[`TryCollectEx`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryCollectEx.html) provides a more convenient alternative, similar to [`collect`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect):\n\n```rust\nuse std::collections::HashMap;\nuse collect_failable::TryCollectEx;\n\nlet map: HashMap\u003c_, _\u003e = [(1, \"a\"), (2, \"b\")].into_iter().try_collect_ex().unwrap();\nassert_eq!(map, HashMap::from([(1, \"a\"), (2, \"b\")]));\n```\n\n### [`TryExtend`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtend.html) and [`TryExtendSafe`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtendSafe.html)\n\nExtend an existing container with items that may violate its invariants. Two different trait exposes two styles of error behavior:\n\n- [`TryExtendSafe`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtendSafe.html) – **strong guarantee** On an error, the container must remain unchanged.\n- [`TryExtend`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtend.html) – **basic guarantee** The container may have partially ingested items, but must remain valid.\n\nUse `TryExtendSafe` if you must avoid mutation on failure; otherwise, prefer the faster `TryExtend`.\n\n```rust\nuse std::collections::HashMap;\nuse collect_failable::TryExtendSafe;\n\nlet mut map = HashMap::new();\nmap.try_extend_safe([(1, 2), (2, 3)]).expect(\"should be Ok\");\nassert_eq!(map, HashMap::from([(1, 2), (2, 3)]));\n\n// on a failure, the container is not modified\nmap.try_extend_safe([(1, 3)]).expect_err(\"should be Err\");\nassert_eq!(map, HashMap::from([(1, 2), (2, 3)]));\n```\n\n### [`TryExtendOne`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtendOne.html)\n\nExtend 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.\n\n### [`TryUnzip`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryUnzip.html)\n\nFallible equivalent of [`Iterator::unzip`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.unzip). Given an iterator of `(A, B)` items, produce two collections that implement `Default + TryExtend`, stopping on the first failure.\n\n```rust\nuse std::collections::{BTreeSet, HashSet};\nuse collect_failable::TryUnzip;\n\n// Unzip into two different container types\nlet data = vec![(1, 'a'), (2, 'b'), (3, 'c')];\nlet (nums, chars): (BTreeSet\u003ci32\u003e, HashSet\u003cchar\u003e) = data.into_iter().try_unzip().expect(\"should be ok\");\n\nassert_eq!(nums, BTreeSet::from([1, 2, 3]));\nassert_eq!(chars, HashSet::from(['a', 'b', 'c']));\n```\n\n## Implementations\n\nImplementations for various containers are provided.\n\n- [HashMap](https://doc.rust-lang.org/std/collections/struct.HashMap.html), [HashSet](https://doc.rust-lang.org/std/collections/struct.HashSet.html) (feature `std`, enabled by default)\n- [BTreeMap](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html), [BTreeSet](https://doc.rust-lang.org/std/collections/struct.BTreeSet.html) (feature `alloc`, enabled by default)\n- [ArrayVec](https://docs.rs/arrayvec/latest/arrayvec/struct.ArrayVec.html) (feature `arrayvec`)\n- [hashbrown::HashMap](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html), [hashbrown::HashSet](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) (feature `hashbrown`)\n- [indexmap::IndexMap](https://docs.rs/indexmap/latest/indexmap/), [indexmap::IndexSet](https://docs.rs/indexmap/latest/indexmap/) (feature `indexmap`)\n\n### Tuples\n\nTuples of arity 2 implement [`TryExtend`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryExtend.html) when their inner types do (requires feature `tuples`, enabled by default). For constructing tuple collections from `IntoIterator` [`TryUnzip`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryUnzip.html) is available.\n\n### Arrays\n\nArrays implement [`TryFromIterator`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryFromIterator.html) for `IntoIterator` that yield exactly the right number of elements. This uses `unsafe` internally and is gated behind the `unsafe` feature (enabled by default).\n\n### Result\n\n[`TryFromIterator`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryFromIterator.html) is implemented for `Result\u003cC, E\u003e`, where `C` implements [`TryFromIterator\u003cT\u003e`](https://docs.rs/collect_failable/latest/collect_failable/trait.TryFromIterator.html), similar to the [`FromIterator`](https://doc.rust-lang.org/std/result/enum.Result.html#impl-FromIterator%3CResult%3CA,+E%3E%3E-for-Result%3CV,+E%3E) implementation for `Result`. This allows short-circuiting collection of failable values into a container whose construction is also failable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmahem%2Fcollect_failable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxmahem%2Fcollect_failable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmahem%2Fcollect_failable/lists"}