1
2023-08-03 20:07:13 -04:00

122 lines
3.3 KiB
Rust

use std::hash::Hash;
use rustc_hash::FxHashMap;
/// A bi-directional hash map
#[derive(Debug, Clone)]
pub struct BiHashMap<Left, Right> {
/// Mapping from a left value to a right value
left_to_right: FxHashMap<Left, Right>,
/// Mapping from a right value to a left value
right_to_left: FxHashMap<Right, Left>,
}
impl<Left, Right> BiHashMap<Left, Right>
where
Left: Eq + Hash + Clone,
Right: Eq + Hash + Clone,
{
/// Construct a new empty `BiHashMap`
pub fn new() -> Self {
Self::default()
}
/// Insert a new mapping into the `BiHashMap`
pub fn insert(&mut self, left: Left, right: Right) {
self.left_to_right.insert(left.clone(), right.clone());
self.right_to_left.insert(right, left);
}
/// Get the right value for a given left value
pub fn get_right(&self, left: &Left) -> Option<&Right> {
self.left_to_right.get(left)
}
/// Get the left value for a given right value
pub fn get_left(&self, right: &Right) -> Option<&Left> {
self.right_to_left.get(right)
}
/// Remove a mapping from the `BiHashMap`
pub fn remove(&mut self, left: &Left, right: &Right) {
self.left_to_right.remove(left);
self.right_to_left.remove(right);
}
/// Remove a mapping from the `BiHashMap` by left value
#[allow(dead_code)]
pub fn remove_left(&mut self, left: &Left) {
if let Some(right) = self.left_to_right.remove(left) {
self.right_to_left.remove(&right);
}
}
/// Remove a mapping from the `BiHashMap` by right value
#[allow(dead_code)]
pub fn remove_right(&mut self, right: &Right) {
if let Some(left) = self.right_to_left.remove(right) {
self.left_to_right.remove(&left);
}
}
/// Get the total number of mappings in the `BiHashMap`
pub fn len(&self) -> usize {
self.left_to_right.len()
}
/// Check if the `BiHashMap` is empty
pub fn is_empty(&self) -> bool {
self.left_to_right.is_empty()
}
}
impl<Left, Right> Default for BiHashMap<Left, Right> {
fn default() -> Self {
Self {
left_to_right: FxHashMap::default(),
right_to_left: FxHashMap::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insert() {
let mut bimap = BiHashMap::new();
bimap.insert(1, "one");
bimap.insert(2, "two");
bimap.insert(3, "three");
assert_eq!(bimap.get_right(&1), Some(&"one"));
assert_eq!(bimap.get_right(&2), Some(&"two"));
assert_eq!(bimap.get_right(&3), Some(&"three"));
assert_eq!(bimap.get_left(&"one"), Some(&1));
assert_eq!(bimap.get_left(&"two"), Some(&2));
assert_eq!(bimap.get_left(&"three"), Some(&3));
}
#[test]
fn test_remove() {
let mut bimap = BiHashMap::new();
bimap.insert(1, "one");
bimap.insert(2, "two");
bimap.insert(3, "three");
bimap.remove(&1, &"one");
assert_eq!(bimap.get_right(&1), None);
assert_eq!(bimap.get_left(&"one"), None);
bimap.remove_left(&2);
assert_eq!(bimap.get_right(&2), None);
assert_eq!(bimap.get_left(&"two"), None);
bimap.remove_right(&"three");
assert_eq!(bimap.get_right(&3), None);
assert_eq!(bimap.get_left(&"three"), None);
}
}