lexigram_lib/
macros.rs

1// Copyright (c) 2025 Redglyph (@gmail.com). All Rights Reserved.
2
3// Rust lacks the HashMap and HashSet equivalents of vec!
4
5/// Generates the code to initialize a [HashMap](std::collections::HashMap).
6///
7/// The macro can be followed by parentheses or square brackets.
8///
9/// # Example
10/// ```
11/// # #[macro_use] fn main() {
12/// # use lexigram_lib::hashmap;
13/// let days = hashmap![0 => "Monday", 1 => "Tuesday", 2 => "Wednesday"];
14/// // => HashMap::from([(0, "Monday"), (1, "Tuesday"), (2, "Wednesday"), ])
15/// assert_eq!(days, std::collections::HashMap::from([(0, "Monday"), (1, "Tuesday"), (2, "Wednesday")]));
16/// # }
17/// ```
18#[macro_export]
19macro_rules! hashmap {
20    () => { std::collections::HashMap::new() };
21    ($($key:expr => $value:expr,)+) => { hashmap!($($key => $value),+) };
22    ($($key:expr => $value:expr),*) => {
23        std::collections::HashMap::from([ $(($key, $value),)* ])
24    };
25}
26
27/// Generates the code to initialize a [BTreeMap](std::collections::BTreeMap).
28///
29/// The macro can be followed by parentheses or square brackets.
30///
31/// # Example
32/// ```
33/// # #[macro_use] fn main() {
34/// # use std::collections::BTreeMap;
35/// # use lexigram_lib::btreemap;
36/// let days = btreemap![0 => "Monday", 1 => "Tuesday", 2 => "Wednesday"];
37/// // => BTreeMap::from([(0, "Monday"), (1, "Tuesday"), (2, "Wednesday"), ])
38/// assert_eq!(days, BTreeMap::from([(0, "Monday"), (1, "Tuesday"), (2, "Wednesday")]));
39/// # }
40/// ```
41#[macro_export]
42macro_rules! btreemap {
43    () => { std::collections::BTreeMap::new() };
44    ($($key:expr => $value:expr,)+) => { btreemap!($($key => $value),+) };
45    ($($key:expr => $value:expr),*) => {
46        std::collections::BTreeMap::from([ $(($key, $value),)* ])
47    };
48}
49
50/// Generates the code to initialize a [HashSet](std::collections::HashSet).
51///
52/// The macro can be followed by parentheses or square brackets.
53///
54/// # Example
55/// ```
56/// # #[macro_use] fn main() {
57/// # use std::collections::HashSet;
58/// # use lexigram_lib::hashset;
59/// let days = hashset!["Monday", "Tuesday", "Wednesday"];
60/// // => HashSet::from(["Monday", "Tuesday", "Wednesday", ])
61/// assert_eq!(days, HashSet::from(["Monday", "Tuesday", "Wednesday"]));
62/// # }
63/// ```
64#[macro_export]
65macro_rules! hashset {
66    () => { std::collections::HashSet::new() };
67    ($($key:expr,)+) => { hashset!($($key),+) };
68    ($($key:expr),*) => { std::collections::HashSet::from([ $($key,)* ]) };
69}
70
71/// Generates the code to initialize a [BTreeSet](std::collections::BTreeSet).
72///
73/// The macro can be followed by parentheses or square brackets.
74///
75/// # Example
76/// ```
77/// # #[macro_use] fn main() {
78/// # use std::collections::BTreeSet;
79/// # use lexigram_lib::btreeset;
80/// let days = btreeset!["Monday", "Tuesday", "Wednesday"];
81/// // => BTreeSet::from(["Monday", "Tuesday", "Wednesday", ])
82/// assert_eq!(days, BTreeSet::from(["Monday", "Tuesday", "Wednesday"]));
83/// # }
84/// ```
85#[macro_export]
86macro_rules! btreeset {
87    () => { std::collections::BTreeSet::new() };
88    ($($key:expr,)+) => { btreeset!($($key),+) };
89    ($($key:expr),*) => { std::collections::BTreeSet::from([ $($key,)* ]) };
90}
91
92#[cfg(test)]
93#[macro_export]
94macro_rules! time {
95    ($verbose:expr, $p:block) => {
96        let macro_timer = std::time::Instant::now();
97        $p
98        let elapsed = macro_timer.elapsed().as_secs_f64();
99        if ($verbose) { std::println!("elapsed time: {elapsed:.3} s"); }
100    }
101}
102
103/// Makes the string argument a String, by using `String::from()` (see [String] for details).
104///
105/// # Example
106/// ```
107/// # #[macro_use] fn main() {
108/// # use lexigram_lib::s;
109/// let text: String = s!("Hello");
110/// # }
111/// ```
112#[macro_export]
113macro_rules! s {
114    ($arg:expr) => {{ String::from($arg) }}
115}
116
117#[cfg(test)]
118mod tests {
119    use std::collections::{HashMap, BTreeMap, HashSet, BTreeSet};
120
121    #[test]
122    fn hashmap() {
123        let h = hashmap!(
124            'a' => hashmap!(
125                '1' => 'a',
126                '2' => 'A'
127            ),
128            'b' => hashmap!['1' => 'b', '2' => 'B',],
129            'c' => hashmap!()
130        );
131        assert_eq!(h, HashMap::from([('a', HashMap::from([('1', 'a'), ('2', 'A')])), ('b', HashMap::from([('1', 'b'), ('2', 'B')])), ('c', HashMap::new())]))
132    }
133
134    #[test]
135    fn btreemap() {
136        let h = btreemap!(
137            'a' => btreemap!(
138                '1' => 'a',
139                '2' => 'A'
140            ),
141            'b' => btreemap!['1' => 'b', '2' => 'B',],
142            'c' => btreemap!()
143        );
144        assert_eq!(h, BTreeMap::from([('a', BTreeMap::from([('1', 'a'), ('2', 'A')])), ('b', BTreeMap::from([('1', 'b'), ('2', 'B')])), ('c', BTreeMap::new())]))
145    }
146
147    #[test]
148    fn hashset() {
149        let h1 = hashset![1, 3, 5, 7];
150        let h2 = hashset!();
151        assert_eq!(h1, HashSet::from([1, 3, 5, 7]));
152        assert_eq!(h2, HashSet::<i32>::from([]));
153    }
154
155    #[test]
156    fn btreeset() {
157        let h1 = btreeset![1, 3, 5, 7];
158        let h2 = btreeset!();
159        assert_eq!(h1, BTreeSet::from([1, 3, 5, 7]));
160        assert_eq!(h2, BTreeSet::<i32>::from([]));
161    }
162}