Skip to main content

bidirectional_map/
lib.rs

1//! A two-way map data structure for cloneable keys and values.
2//!
3//! Most functions come in `_fwd` and `_rev` variants, where the `_fwd` variant acts on the second
4//! entry given the first, and `_rev` is the opposite.
5//!
6//! This crate is best for values that are cheap to clone, since internally it stores two copies
7//! of each element. To use it with large values, consider wrapping them in `Rc` to make them cheap
8//! to clone.
9
10use std::borrow::Borrow;
11use std::collections::hash_map::*;
12use std::default::Default;
13use std::hash::{BuildHasher, Hash};
14use std::iter::{FromIterator, IntoIterator};
15
16#[derive(Clone, Debug)]
17pub struct Bimap<K, V, S = RandomState> {
18    fwd: HashMap<K, V, S>,
19    rev: HashMap<V, K, S>,
20}
21
22impl<K, V> Bimap<K, V, RandomState>
23where
24    K: Eq + Hash + Clone,
25    V: Eq + Hash + Clone,
26{
27    /// Creates an empty `Bimap`.
28    pub fn new() -> Self {
29        Self { fwd: HashMap::new(), rev: HashMap::new() }
30    }
31}
32
33impl<K, V, S> Bimap<K, V, S>
34where
35    K: Eq + Hash + Clone,
36    V: Eq + Hash + Clone,
37    S: BuildHasher + Clone + Default,
38{
39    /// Creates a `Bimap` with the given hasher.
40    pub fn with_hasher(hash_builder: S) -> Self {
41        Self {
42            fwd: HashMap::with_hasher(hash_builder.clone()),
43            rev: HashMap::with_hasher(hash_builder),
44        }
45    }
46
47    /// Creates a bimap from a `HashMap`.
48    pub fn from_hash_map(fwd: HashMap<K, V, S>) -> Self {
49        let rev = fwd.iter().map(|(k, v)| (v.clone(), k.clone())).collect();
50        Self { fwd, rev }
51    }
52
53    /// Returns the number of elements in the bimap.
54    pub fn len(&self) -> usize {
55        self.fwd.len()
56    }
57
58    /// Returns whether the bimap is empty.
59    pub fn is_empty(&self) -> bool {
60        self.fwd.is_empty()
61    }
62
63    /// Removes all elements from the bimap.
64    pub fn clear(&mut self) {
65        self.fwd.clear();
66        self.rev.clear();
67    }
68
69    /// Inserts a (key, value) pair into the bimap. Panics if either the key or value is already
70    /// present in the bimap; to change a key or value, call either `remove_fwd` or
71    /// `remove_rev` before inserting the new (key, value) pair.
72    pub fn insert(&mut self, k: K, v: V) {
73        match self.fwd.entry(k.clone()) {
74            Entry::Vacant(entry) => {
75                entry.insert(v.clone());
76            }
77            Entry::Occupied(_) => panic!("Element already in bimap"),
78        }
79        match self.rev.entry(v) {
80            Entry::Vacant(entry) => {
81                entry.insert(k);
82            }
83            Entry::Occupied(_) => panic!("Element already in bimap"),
84        }
85    }
86
87    /// Gets the forward `HashMap`.
88    pub fn fwd(&self) -> &HashMap<K, V, S> {
89        &self.fwd
90    }
91
92    /// Gets the reverse `HashMap`.
93    pub fn rev(&self) -> &HashMap<V, K, S> {
94        &self.rev
95    }
96
97    /// Gets the value corresponding to a key.
98    pub fn get_fwd<KeyBorrow: ?Sized>(&self, k: &KeyBorrow) -> Option<&V>
99    where
100        K: Borrow<KeyBorrow>,
101        KeyBorrow: Hash + Eq,
102    {
103        self.fwd.get(k)
104    }
105
106    /// Gets the key corresponding to a value.
107    pub fn get_rev<ValBorrow: ?Sized>(&self, v: &ValBorrow) -> Option<&K>
108    where
109        V: Borrow<ValBorrow>,
110        ValBorrow: Hash + Eq,
111    {
112        self.rev.get(v)
113    }
114
115    /// Removes the (key, value) pair with the given key; returns the corresponding value.
116    pub fn remove_fwd<KeyBorrow: ?Sized>(&mut self, k: &KeyBorrow) -> V
117    where
118        K: Borrow<KeyBorrow>,
119        KeyBorrow: Hash + Eq,
120    {
121        let v = self.fwd.remove(k).unwrap();
122        self.rev.remove(&v).unwrap();
123        v
124    }
125
126    /// Removes the (key, value) pair with the given value; returns the corresponding key.
127    pub fn remove_rev<ValBorrow: ?Sized>(&mut self, v: &ValBorrow) -> K
128    where
129        V: Borrow<ValBorrow>,
130        ValBorrow: Hash + Eq,
131    {
132        let k = self.rev.remove(v).unwrap();
133        self.fwd.remove(&k).unwrap();
134        k
135    }
136
137    /// Returns whether the bimap contains a (key, value) pair with the given key.
138    pub fn contains_fwd<KeyBorrow: ?Sized>(&self, k: &KeyBorrow) -> bool
139    where
140        K: Borrow<KeyBorrow>,
141        KeyBorrow: Hash + Eq,
142    {
143        self.fwd.contains_key(k)
144    }
145
146    /// Returns whether the bimap contains a (key, value) pair with the given value.
147    pub fn contains_rev<ValBorrow: ?Sized>(&self, v: &ValBorrow) -> bool
148    where
149        V: Borrow<ValBorrow>,
150        ValBorrow: Hash + Eq,
151    {
152        self.rev.contains_key(v)
153    }
154
155    /// Iterates over all (key, value) pairs in the bimap.
156    pub fn iter(&self) -> Iter<K, V> {
157        self.fwd.iter()
158    }
159}
160
161impl<K, V, S> FromIterator<(K, V)> for Bimap<K, V, S>
162where
163    K: Eq + Hash + Clone,
164    V: Eq + Hash + Clone,
165    S: BuildHasher + Clone + Default,
166{
167    fn from_iter<T>(iter: T) -> Self
168    where
169        T: IntoIterator<Item = (K, V)>,
170    {
171        Bimap::from_hash_map(iter.into_iter().collect())
172    }
173}
174
175impl<K, V, S> IntoIterator for Bimap<K, V, S>
176where
177    K: Eq + Hash + Clone,
178    V: Eq + Hash + Clone,
179    S: BuildHasher + Clone + Default,
180{
181    type Item = (K, V);
182    type IntoIter = IntoIter<K, V>;
183
184    fn into_iter(self) -> Self::IntoIter {
185        self.fwd.into_iter()
186    }
187}
188
189impl<K, V, S> Default for Bimap<K, V, S>
190where
191    K: Eq + Hash + Clone,
192    V: Eq + Hash + Clone,
193    S: BuildHasher + Clone + Default,
194{
195    fn default() -> Self {
196        Bimap::with_hasher(Default::default())
197    }
198}