maplit
Rust macros that let you write HashMap, HashSet, BTreeMap, and BTreeSet literals inline, without the boilerplate of manual insert calls.
Repository Health
Technical Analysis
maplit is a small, dependency-free Rust crate that adds container literal syntax the language itself doesn’t provide. Where vec![1, 2, 3] builds a Vec in one expression, maplit’s hashmap!{ "a" => 1, "b" => 2 } does the same for HashMap, and matching macros (hashset!, btreemap!, btreeset!) cover the other standard-library collection types.
Each macro expands at compile time to a sequence of insert calls, pre-sized using a @count arm so the resulting map or set doesn’t reallocate as it fills. A separate convert_args! macro wraps any of the four (or compatible third-party macros) to apply an Into-based or custom conversion function to keys and/or values, so a literal built from &str can populate a HashMap<String, String> without manual .to_string() calls at every pair.
What You Get
- hashmap! and hashset! macros for building std::collections::HashMap and HashSet in one expression
- btreemap! and btreeset! macros for the ordered BTreeMap and BTreeSet equivalents
- convert_args! to apply a key/value conversion function (default: Into::into) while building any of the above
- Capacity pre-allocation computed from the literal’s element count, avoiding reallocation during insertion
- Optional trailing commas on every macro, matching Rust’s own array and vec! literal conventions
Common Use Cases
- Building expected HashMap/HashSet values inline in unit tests for assert_eq! comparisons
- Writing small static-like lookup tables (error codes to messages, flags to labels) as a single expression
- Keeping doctest and example code short when a function needs a map or set argument
- Constructing a HashMap<String, String> or similar owned-type container directly from &str literals via convert_args!
Under The Hood
Architecture
The entire crate is a single src/lib.rs (roughly 160 lines) exporting four sibling macro_rules! macros — hashmap!, hashset!, btreemap!, btreeset! — plus convert_args! and a hidden __id identity function used as the default no-op conversion. There are no modules, no runtime state, and no dependency injection to speak of: each container macro recurses through internal @single/@count arms to compute an element count before allocating, then emits a block of insert calls. convert_args! follows a similar recursive-expansion pattern, filling in default keys=/values= conversion functions (defaulting to std::convert::Into::into) before re-invoking the wrapped macro with converted arguments. Because everything resolves at compile time via #[macro_export(local_inner_macros)], the public surface has no runtime behavior of its own beyond what the expanded insert calls do, which keeps the blast radius of any internal change very small.
Tech Stack
maplit has zero external dependencies — its Cargo.toml declares none — and touches only std::collections::{HashMap, HashSet, BTreeMap, BTreeSet} directly. There’s no async runtime, ORM, or CLI layer; the crate’s only “deployment target” is being pulled in as a [dependencies] entry from crates.io. CI (.travis.yml) runs cargo build, cargo test, and cargo doc across a matrix from Rust 1.14.0 through nightly, and additionally builds two auxiliary crates (rust2015user/, rust2018user/) whose sole purpose is verifying the macros still resolve correctly under both the 2015 and 2018 editions’ macro-import rules.
Code Quality
Tests exist in two places: inline #[test] functions at the bottom of src/lib.rs covering nesting, empty containers, and convert_args! interaction, and a separate tests/tests.rs exercising parsing edge cases such as trailing commas, expression keys, and a 200-plus-element hashset! invocation guarding against macro recursion limits. Because the macros can’t fail at runtime beyond ordinary insert semantics, there’s no error-handling surface to speak of, and naming is consistent (each macro mirrors its std container’s name). CI runs build/test/doc across Rust versions and editions but has no clippy or rustfmt step, and there’s no coverage tooling.
What Makes It Unique
The crate’s small technical edge is precomputing element count in a @count macro arm so the resulting collection is pre-sized before insertion, avoiding the reallocation a naive sequence of .insert() calls (or a .collect() from an iterator) would incur. convert_args! is the more distinctive piece: it generically wraps any of the four container macros — or any third-party macro with a matching signature — to inject a per-key and per-value conversion function at macro-expansion time. Neither idea is unique to maplit; several Rust crates offer comparable container-literal macros, so this is a well-executed instance of an established pattern rather than something novel to the ecosystem.
Used by 3 apps in this directory
Meilisearch
Search
Lightning-fast hybrid search engine with AI-powered semantic and full-text retrieval for modern applications.
Stalwart
Collaboration
All-in-one secure mail and collaboration server covering IMAP, JMAP, SMTP, CalDAV, CardDAV, and WebDAV in a single memory-safe Rust binary.
Svix
Developer Tools · Automation
Open source, self-hostable webhook infrastructure that handles delivery, retries, HMAC signing, and multi-tenant event management so you never have to build a webhooks system from scratch.