Skip to content

Commit 542d4e2

Browse files
committed
Add multimap! macro
1 parent d3edd93 commit 542d4e2

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

src/lib.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@
1818
//! and memory penalty. Notably, indexing by `K2` requires two HashMap lookups.
1919
//!
2020
//! ```
21-
//! # extern crate multi_map;
21+
//! extern crate multi_map;
2222
//! use multi_map::MultiMap;
23+
//!
2324
//! # fn main() {
2425
//! #[derive(Hash,Clone,PartialEq,Eq)]
2526
//! enum ThingIndex {
2627
//! IndexOne,
2728
//! IndexTwo,
2829
//! IndexThree,
2930
//! };
31+
//!
3032
//! let mut map = MultiMap::new();
3133
//! map.insert("One", ThingIndex::IndexOne, 1);
3234
//! map.insert("Two", ThingIndex::IndexTwo, 2);
35+
//!
3336
//! assert!(*map.get_alt(&ThingIndex::IndexOne).unwrap() == 1);
3437
//! assert!(*map.get(&"Two").unwrap() == 2);
3538
//! assert!(map.remove_alt(&ThingIndex::IndexTwo).unwrap() == 2);
@@ -64,6 +67,16 @@ impl<K1: Eq + Hash + Clone, K2: Eq + Hash + Clone, V> MultiMap<K1, K2, V> {
6467
}
6568
}
6669

70+
/// Creates an empty MultiMap with the specified capacity.
71+
///
72+
/// The multi map will be able to hold at least `capacity` elements without reallocating. If `capacity` is 0, the multi map will not allocate.
73+
pub fn with_capacity(capacity: usize) -> MultiMap<K1, K2, V> {
74+
MultiMap {
75+
value_map: HashMap::with_capacity(capacity),
76+
key_map: HashMap::with_capacity(capacity),
77+
}
78+
}
79+
6780
/// Insert an item into the MultiMap. You must supply both keys to insert
6881
/// an item. The keys cannot be modified at a later date, so if you only
6982
/// have one key at this time, use a placeholder value for the second key
@@ -157,6 +170,50 @@ impl<K1: Eq + Hash + Clone, K2: Eq + Hash + Clone, V> MultiMap<K1, K2, V> {
157170
}
158171
}
159172

173+
#[macro_export]
174+
/// Create a MultiMap from a list of key-value tuples
175+
///
176+
/// ## Example
177+
///
178+
/// ```
179+
/// #[macro_use]
180+
/// extern crate multi_map;
181+
/// use multi_map::MultiMap;
182+
///
183+
/// # fn main() {
184+
/// #[derive(Hash,Clone,PartialEq,Eq)]
185+
/// enum ThingIndex {
186+
/// IndexOne,
187+
/// IndexTwo,
188+
/// IndexThree,
189+
/// };
190+
///
191+
/// let map = multimap!{
192+
/// "One", ThingIndex::IndexOne => 1,
193+
/// "Two", ThingIndex::IndexTwo => 2,
194+
/// };
195+
///
196+
/// assert!(*map.get_alt(&ThingIndex::IndexOne).unwrap() == 1);
197+
/// assert!(*map.get(&"Two").unwrap() == 2);
198+
/// # }
199+
/// ```
200+
macro_rules! multimap {
201+
(@single $($x:tt)*) => (());
202+
(@count $($rest:expr),*) => (<[()]>::len(&[$(multimap!(@single $rest)),*]));
203+
204+
($($key1:expr, $key2:expr => $value:expr,)+) => { multimap!($($key1, $key2 => $value),+) };
205+
($($key1:expr, $key2:expr => $value:expr),*) => {
206+
{
207+
let _cap = multimap!(@count $($key1),*);
208+
let mut _map = MultiMap::with_capacity(_cap);
209+
$(
210+
_map.insert($key1, $key2, $value);
211+
)*
212+
_map
213+
}
214+
};
215+
}
216+
160217
mod test {
161218

162219
#[test]
@@ -195,6 +252,32 @@ mod test {
195252
assert!(*map.get(&2).unwrap() == String::from("Zwei!"));
196253
assert!(map.get_alt(&"Three") == None);
197254
assert!(map.get(&3) == None);
255+
}
256+
257+
#[test]
258+
fn macro_test() {
259+
use ::MultiMap;
260+
261+
let _: MultiMap<i32, &str, String> = multimap!{};
262+
263+
multimap!{
264+
1, "One" => String::from("Eins"),
265+
};
266+
267+
multimap!{
268+
1, "One" => String::from("Eins")
269+
};
270+
271+
multimap!{
272+
1, "One" => String::from("Eins"),
273+
2, "Two" => String::from("Zwei"),
274+
3, "Three" => String::from("Drei"),
275+
};
198276

277+
multimap!{
278+
1, "One" => String::from("Eins"),
279+
2, "Two" => String::from("Zwei"),
280+
3, "Three" => String::from("Drei")
281+
};
199282
}
200283
}

0 commit comments

Comments
 (0)