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}