Skip to main content
A collection of convenient macros for working with collections, regular expressions, and other common patterns in Rust.

Features

  • Collection Macros: Easy creation of HashMap, HashSet, BTreeMap, BTreeSet, and VecDeque
  • Type Conversion: _into variants that automatically convert values to target types
  • Regular Expressions: Static regex compilation for efficient pattern matching
  • Utility Macros: Helper macros for counting and other operations

Installation

Add bomboni_macros to your Cargo.toml:
[dependencies]
bomboni_macros = "*"
regex = "*"  # Required for the regex! macro

HashMap Creation

Create HashMap instances with a convenient syntax:
use bomboni_macros::hash_map;
use std::collections::HashMap;

// Create an empty map
let map: HashMap<i32, &str> = hash_map!();

// Create with initial capacity
let map: HashMap<i32, String> = hash_map!(100);

// Create with key-value pairs
let map = hash_map! {
    1 => "first",
    2 => "second",
    3 => "third",
};
assert_eq!(map.get(&1), Some(&"first"));
assert_eq!(map.get(&2), Some(&"second"));
assert_eq!(map.len(), 3);

HashMap with Type Conversion

Use hash_map_into! to automatically convert keys and values:
use bomboni_macros::hash_map_into;
use std::collections::HashMap;

// Automatically converts &str to String
let map: HashMap<i32, String> = hash_map_into! {
    1 => "first",
    2 => "second",
};
assert_eq!(map.get(&1), Some(&"first".to_string()));

// Works with any type that implements Into
let map: HashMap<String, i64> = hash_map_into! {
    "one" => 1i32,
    "two" => 2i32,
};

HashSet Creation

Create HashSet instances with ease:
use bomboni_macros::hash_set;
use std::collections::HashSet;

// Create an empty set
let set: HashSet<i32> = hash_set!();

// Create with values
let set = hash_set![1, 2, 3, 4, 5];
assert!(set.contains(&1));
assert!(set.contains(&3));
assert_eq!(set.len(), 5);

// Trailing commas are allowed
let set = hash_set!["a", "b", "c",];

HashSet with Type Conversion

use bomboni_macros::hash_set_into;
use std::collections::HashSet;

let set: HashSet<String> = hash_set_into!["one", "two", "three"];
assert!(set.contains(&"one".to_string()));

BTreeMap Creation

Create sorted BTreeMap instances:
use bomboni_macros::btree_map;
use std::collections::BTreeMap;

// Create with key-value pairs
let map = btree_map! {
    "c" => 3,
    "a" => 1,
    "b" => 2,
};

// Keys are automatically sorted
let keys: Vec<_> = map.keys().collect();
assert_eq!(keys, vec![&"a", &"b", &"c"]);

BTreeMap with Type Conversion

use bomboni_macros::btree_map_into;
use std::collections::BTreeMap;

let map: BTreeMap<i32, String> = btree_map_into! {
    1 => "first",
    2 => "second",
};
assert_eq!(map.get(&1), Some(&"first".to_string()));

BTreeSet Creation

Create sorted BTreeSet instances:
use bomboni_macros::btree_set;
use std::collections::BTreeSet;

let set = btree_set![3, 1, 4, 1, 5, 9, 2, 6];

// Values are automatically sorted and deduplicated
let values: Vec<_> = set.iter().copied().collect();
assert_eq!(values, vec![1, 2, 3, 4, 5, 6, 9]);

BTreeSet with Type Conversion

use bomboni_macros::btree_set_into;
use std::collections::BTreeSet;

let set: BTreeSet<String> = btree_set_into!["cherry", "apple", "banana"];
let values: Vec<_> = set.iter().map(|s| s.as_str()).collect();
assert_eq!(values, vec!["apple", "banana", "cherry"]);

VecDeque Creation

Create double-ended queue instances:
use bomboni_macros::vec_deque;
use std::collections::VecDeque;

// Create empty deque
let deque: VecDeque<i32> = vec_deque!();

// Create with values
let deque = vec_deque![1, 2, 3, 4, 5];
assert_eq!(deque.front(), Some(&1));
assert_eq!(deque.back(), Some(&5));

// Create with repeated element
let deque = vec_deque![0; 5];
assert_eq!(deque.len(), 5);

VecDeque with Type Conversion

use bomboni_macros::vec_deque_into;
use std::collections::VecDeque;

let deque: VecDeque<String> = vec_deque_into!["first", "second", "third"];
assert_eq!(deque[0], "first".to_string());

Regular Expression Macro

Create static, lazily-compiled regular expressions:
use bomboni_macros::regex;

// Create a static regex that's compiled once
let re = regex!(r"\d{4}-\d{2}-\d{2}");
assert!(re.is_match("2021-08-012"));

// The regex is stored in a static OnceLock
// Subsequent calls return the same compiled instance
let re2 = regex!(r"\d{4}-\d{2}-\d{2}");
assert!(std::ptr::eq(re, re2));
The regex! macro will panic at runtime if the regex pattern is invalid. Make sure to test your patterns.

Common Regex Patterns

use bomboni_macros::regex;

// Email validation (simple)
let email_re = regex!(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
assert!(email_re.is_match("[email protected]"));

// URL matching
let url_re = regex!(r"https?://[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+");
assert!(url_re.is_match("https://example.com/path"));

// IPv4 address
let ip_re = regex!(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$");
assert!(ip_re.is_match("192.168.1.1"));

Counting Macro

Count the number of repeated elements:
use bomboni_macros::count_repeating;

// Count items in a repetition
let count = count_repeating!(1, 2, 3, 4, 5);
assert_eq!(count, 5);

let count = count_repeating!("a", "b", "c");
assert_eq!(count, 3);

// Useful in macro implementations
let capacity = count_repeating!("key1", "key2", "key3");
let vec = Vec::with_capacity(capacity);
The count_repeating! macro is primarily used internally by other collection macros to pre-allocate capacity, but it’s available for general use.

Macro Comparison

Regular vs Into Variants

use bomboni_macros::{hash_map, hash_map_into};
use std::collections::HashMap;

// Regular variant: no conversion
let map1 = hash_map! {
    1 => "value".to_string(),  // Must explicitly convert
};

// Into variant: automatic conversion
let map2: HashMap<i32, String> = hash_map_into! {
    1 => "value",  // Automatically converted to String
};

assert_eq!(map1, map2);

Performance Considerations

use bomboni_macros::{hash_map, hash_set};

// The hash_map! macro pre-calculates capacity
let map = hash_map! {
    1 => "a",
    2 => "b",
    3 => "c",
};
// Equivalent to:
let mut map_manual = HashMap::with_capacity(3);
map_manual.insert(1, "a");
map_manual.insert(2, "b");
map_manual.insert(3, "c");

Practical Examples

Configuration Map

use bomboni_macros::hash_map;

let config = hash_map! {
    "database_url" => "postgres://localhost/mydb",
    "api_key" => "secret123",
    "max_connections" => "10",
};

if let Some(url) = config.get("database_url") {
    println!("Connecting to: {}", url);
}

Static Lookup Tables

use bomboni_macros::btree_map;
use std::collections::BTreeMap;

fn get_http_status_text(code: u16) -> &'static str {
    static STATUS_CODES: std::sync::OnceLock<BTreeMap<u16, &str>> = 
        std::sync::OnceLock::new();
    
    let codes = STATUS_CODES.get_or_init(|| btree_map! {
        200 => "OK",
        201 => "Created",
        400 => "Bad Request",
        404 => "Not Found",
        500 => "Internal Server Error",
    });
    
    codes.get(&code).unwrap_or(&"Unknown")
}

assert_eq!(get_http_status_text(200), "OK");

Validation Sets

use bomboni_macros::hash_set;

let valid_extensions = hash_set!["rs", "toml", "md", "txt"];

fn is_valid_file(filename: &str) -> bool {
    filename
        .rsplit('.')
        .next()
        .map(|ext| valid_extensions.contains(ext))
        .unwrap_or(false)
}

assert!(is_valid_file("main.rs"));
assert!(!is_valid_file("image.png"));

API Reference

Collection Macros

hash_map!
macro
Creates a HashMap with optional capacity or key-value pairs.Syntax:
  • hash_map!() - Empty map
  • hash_map!(capacity) - Map with pre-allocated capacity
  • hash_map!{ k1 => v1, k2 => v2, ... } - Map with initial values
hash_map_into!
macro
Creates a HashMap with automatic type conversion using Into.Syntax: hash_map_into!{ k1 => v1, k2 => v2, ... }
hash_set!
macro
Creates a HashSet with optional values.Syntax:
  • hash_set!() - Empty set
  • hash_set![v1, v2, v3, ...] - Set with initial values
hash_set_into!
macro
Creates a HashSet with automatic type conversion.Syntax: hash_set_into![v1, v2, v3, ...]
btree_map!
macro
Creates a sorted BTreeMap with key-value pairs.Syntax:
  • btree_map!() - Empty map
  • btree_map!{ k1 => v1, k2 => v2, ... } - Map with initial values
btree_map_into!
macro
Creates a BTreeMap with automatic type conversion.Syntax: btree_map_into!{ k1 => v1, k2 => v2, ... }
btree_set!
macro
Creates a sorted BTreeSet with values.Syntax:
  • btree_set!() - Empty set
  • btree_set![v1, v2, v3, ...] - Set with initial values
btree_set_into!
macro
Creates a BTreeSet with automatic type conversion.Syntax: btree_set_into![v1, v2, v3, ...]
vec_deque!
macro
Creates a VecDeque with values.Syntax:
  • vec_deque!() - Empty deque
  • vec_deque![v; n] - Deque with n copies of v
  • vec_deque![v1, v2, v3, ...] - Deque with initial values
vec_deque_into!
macro
Creates a VecDeque with automatic type conversion.Syntax: vec_deque_into![v1, v2, v3, ...]

Utility Macros

regex!
macro
Creates a static, lazily-compiled Regex instance.Syntax: regex!(pattern)Returns: &'static RegexPanics: If the regex pattern is invalid
count_repeating!
macro
Counts the number of repeated elements in a macro invocation.Syntax: count_repeating!(expr1, expr2, ...)Returns: usize - The count of elements

bomboni_common

Common utilities and types

bomboni_core

Core utilities and abstractions

Build docs developers (and LLMs) love