use std::borrow::Borrow;
use std::collections::hash_map;
use std::collections::HashMap;
use std::fmt::{self, Debug};
use std::hash::Hash;
#[derive(Eq)]
pub struct MultiMap<K1: Eq + Hash, K2: Eq + Hash, V> {
value_map: HashMap<K1, (K2, V)>,
key_map: HashMap<K2, K1>,
}
impl<K1: Eq + Hash + Clone, K2: Eq + Hash + Clone, V> MultiMap<K1, K2, V> {
pub fn new() -> MultiMap<K1, K2, V> {
MultiMap {
value_map: HashMap::new(),
key_map: HashMap::new(),
}
}
pub fn with_capacity(capacity: usize) -> MultiMap<K1, K2, V> {
MultiMap {
value_map: HashMap::with_capacity(capacity),
key_map: HashMap::with_capacity(capacity),
}
}
pub fn insert(&mut self, key_one: K1, key_two: K2, value: V) {
self.key_map.insert(key_two.clone(), key_one.clone());
self.value_map.insert(key_one, (key_two, value));
}
pub fn get(&self, key: &K1) -> Option<&V> {
let mut result = None;
if let Some(pair) = self.value_map.get(key) {
result = Some(&pair.1)
}
result
}
pub fn get_mut(&mut self, key: &K1) -> Option<&mut V> {
let mut result = None;
if let Some(pair) = self.value_map.get_mut(key) {
result = Some(&mut pair.1)
}
result
}
pub fn get_alt(&self, key: &K2) -> Option<&V> {
let mut result = None;
if let Some(key_a) = self.key_map.get(key) {
if let Some(pair) = self.value_map.get(key_a) {
result = Some(&pair.1)
}
}
result
}
pub fn get_mut_alt(&mut self, key: &K2) -> Option<&mut V> {
let mut result = None;
if let Some(key_a) = self.key_map.get(key) {
if let Some(pair) = self.value_map.get_mut(key_a) {
result = Some(&mut pair.1)
}
}
result
}
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K1: Borrow<Q>,
Q: Hash + Eq,
{
let mut result = None;
if let Some(pair) = self.value_map.remove(key) {
self.key_map.remove(&pair.0);
result = Some(pair.1)
}
result
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K1: Borrow<Q>,
Q: Hash + Eq,
{
self.value_map.contains_key(key)
}
pub fn contains_key_alt<Q: ?Sized>(&self, key: &Q) -> bool
where
K2: Borrow<Q>,
Q: Hash + Eq,
{
self.key_map.contains_key(key)
}
pub fn remove_alt<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K2: Borrow<Q>,
Q: Hash + Eq,
{
let mut result = None;
if let Some(key_a) = self.key_map.remove(key) {
if let Some(pair) = self.value_map.remove(&key_a) {
result = Some(pair.1)
}
}
result
}
pub fn iter(&self) -> Iter<'_, K1, K2, V> {
Iter {
base: self.value_map.iter(),
}
}
}
impl<K1: Eq + Hash, K2: Eq + Hash, V: Eq> PartialEq for MultiMap<K1, K2, V> {
fn eq(&self, other: &MultiMap<K1, K2, V>) -> bool {
self.value_map.eq(&other.value_map)
}
}
impl<K1: Eq + Hash + Debug, K2: Eq + Hash + Debug, V: Debug> fmt::Debug for MultiMap<K1, K2, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map()
.entries(
self.value_map
.iter()
.map(|(key_one, &(ref key_two, ref value))| ((key_one, key_two), value)),
)
.finish()
}
}
impl<K1, K2, V> Default for MultiMap<K1, K2, V>
where
K1: Eq + Hash + Clone,
K2: Eq + Hash + Clone,
{
#[inline]
fn default() -> MultiMap<K1, K2, V> {
MultiMap::new()
}
}
#[derive(Clone, Debug)]
pub struct Iter<'a, K1: 'a, K2: 'a, V: 'a> {
base: hash_map::Iter<'a, K1, (K2, V)>,
}
pub struct IntoIter<K1, K2, V> {
base: hash_map::IntoIter<K1, (K2, V)>,
}
impl<K1, K2, V> IntoIterator for MultiMap<K1, K2, V>
where
K1: Eq + Hash + Debug,
K2: Eq + Hash + Debug,
V: Debug,
{
type Item = (K1, (K2, V));
type IntoIter = IntoIter<K1, K2, V>;
fn into_iter(self) -> IntoIter<K1, K2, V> {
IntoIter {
base: self.value_map.into_iter(),
}
}
}
impl<'a, K1, K2, V> IntoIterator for &'a MultiMap<K1, K2, V>
where
K1: Eq + Hash + Debug + Clone,
K2: Eq + Hash + Debug + Clone,
V: Debug,
{
type Item = (&'a K1, &'a (K2, V));
type IntoIter = Iter<'a, K1, K2, V>;
fn into_iter(self) -> Iter<'a, K1, K2, V> {
self.iter()
}
}
impl<'a, K1, K2, V> Iterator for Iter<'a, K1, K2, V> {
type Item = (&'a K1, &'a (K2, V));
fn next(&mut self) -> Option<(&'a K1, &'a (K2, V))> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
}
impl<K1, K2, V> Iterator for IntoIter<K1, K2, V> {
type Item = (K1, (K2, V));
#[inline]
fn next(&mut self) -> Option<(K1, (K2, V))> {
self.base.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
}
#[macro_export]
macro_rules! multimap {
(@single $($x:tt)*) => (());
(@count $($rest:expr),*) => (<[()]>::len(&[$(multimap!(@single $rest)),*]));
($($key1:expr, $key2:expr => $value:expr,)+) => { multimap!($($key1, $key2 => $value),+) };
($($key1:expr, $key2:expr => $value:expr),*) => {
{
let _cap = multimap!(@count $($key1),*);
let mut _map = MultiMap::with_capacity(_cap);
$(
_map.insert($key1, $key2, $value);
)*
_map
}
};
}
mod test {
#[test]
fn big_test() {
use MultiMap;
let mut map = MultiMap::new();
map.insert(1, "One", String::from("Ein"));
map.insert(2, "Two", String::from("Zwei"));
map.insert(3, "Three", String::from("Drei"));
assert!(*map.get(&1).unwrap() == String::from("Ein"));
assert!(*map.get(&2).unwrap() == String::from("Zwei"));
assert!(*map.get(&3).unwrap() == String::from("Drei"));
assert!(map.contains_key(&1));
assert!(!map.contains_key(&4));
assert!(map.contains_key_alt(&"One"));
assert!(!map.contains_key_alt(&"Four"));
map.get_mut_alt(&"One").unwrap().push_str("s");
assert!(*map.get_alt(&"One").unwrap() == String::from("Eins"));
assert!(*map.get_alt(&"Two").unwrap() == String::from("Zwei"));
assert!(*map.get_alt(&"Three").unwrap() == String::from("Drei"));
map.remove(&3);
assert!(*map.get_alt(&"One").unwrap() == String::from("Eins"));
assert!(*map.get_alt(&"Two").unwrap() == String::from("Zwei"));
assert!(map.get_alt(&"Three") == None);
assert!(map.get(&3) == None);
assert!(map.remove_alt(&"Three") == None);
assert!(*map.remove_alt(&"One").unwrap() == String::from("Eins"));
map.get_mut(&2).unwrap().push_str("!");
assert!(map.get(&1) == None);
assert!(*map.get(&2).unwrap() == String::from("Zwei!"));
assert!(map.get_alt(&"Three") == None);
assert!(map.get(&3) == None);
}
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
struct MultiCount<'a>(i32, &'a str, &'a str);
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
struct MultiCountOwned(i32, String, String);
#[test]
fn into_iter_test() {
use MultiMap;
let mut map = MultiMap::new();
map.insert(1, "One", String::from("Eins"));
map.insert(2, "Two", String::from("Zwei"));
map.insert(3, "Three", String::from("Drei"));
let mut vec_borrow = Vec::new();
for (k1, (k2, v)) in &map {
vec_borrow.push(MultiCount(*k1, *k2, v));
}
vec_borrow.sort();
assert_eq!(
vec_borrow,
vec!(
MultiCount(1, "One", "Eins"),
MultiCount(2, "Two", "Zwei"),
MultiCount(3, "Three", "Drei")
)
);
let mut vec_owned = Vec::new();
for (k1, (k2, v)) in map {
vec_owned.push(MultiCountOwned(k1, String::from(k2), v));
}
vec_owned.sort();
assert_eq!(
vec_owned,
vec!(
MultiCountOwned(1, String::from("One"), String::from("Eins")),
MultiCountOwned(2, String::from("Two"), String::from("Zwei")),
MultiCountOwned(3, String::from("Three"), String::from("Drei"))
)
)
}
#[test]
fn macro_test() {
use MultiMap;
let map: MultiMap<i32, &str, String> = MultiMap::new();
assert_eq!(map, multimap! {});
let mut map = MultiMap::new();
map.insert(1, "One", String::from("Eins"));
assert_eq!(
map,
multimap! {
1, "One" => String::from("Eins"),
}
);
assert_eq!(
map,
multimap! {
1, "One" => String::from("Eins")
}
);
let mut map = MultiMap::new();
map.insert(1, "One", String::from("Eins"));
map.insert(2, "Two", String::from("Zwei"));
map.insert(3, "Three", String::from("Drei"));
assert_eq!(
map,
multimap! {
1, "One" => String::from("Eins"),
2, "Two" => String::from("Zwei"),
3, "Three" => String::from("Drei"),
}
);
assert_eq!(
map,
multimap! {
1, "One" => String::from("Eins"),
2, "Two" => String::from("Zwei"),
3, "Three" => String::from("Drei")
}
);
}
}