Skip to content

Instantly share code, notes, and snippets.

@izderadicka
Created August 17, 2024 12:14
Show Gist options
  • Save izderadicka/296f2c07c984cf7d84335fbad2ca7095 to your computer and use it in GitHub Desktop.
Save izderadicka/296f2c07c984cf7d84335fbad2ca7095 to your computer and use it in GitHub Desktop.
Rust Map with COW key
use std::{borrow::Cow, collections::HashMap, hash::Hash};
pub struct CowMap<'a, T, K, V>
where
K: ToOwned<Owned = T> + ?Sized,
{
map: HashMap<Cow<'a, K>, V>,
}
impl<'a, T, K, V> CowMap<'a, T, K, V>
where
K: ToOwned<Owned = T> + ?Sized,
{
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}
}
impl<'a, T, K, V> CowMap<'a, T, K, V>
where
K: ToOwned<Owned = T> + Eq + Hash + ?Sized,
{
pub fn get(&self, key: &K) -> Option<&V> {
self.map.get(key)
}
fn insert_cow(&mut self, key: Cow<'a, K>, value: V) -> Option<V> {
self.map.insert(key, value)
}
pub fn insert(&mut self, key: T, value: V) -> Option<V> {
self.insert_cow(Cow::Owned(key), value)
}
pub fn insert_with_key_ref(&mut self, key: &'a K, value: V) -> Option<V> {
self.insert_cow(Cow::Borrowed(key), value)
}
pub fn delete(&mut self, key: &K) -> Option<V> {
self.map.remove(key)
}
pub fn len(&self) -> usize {
self.map.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_map() {
let string_key = "c".to_string();
let mut m = CowMap::new();
m.insert_with_key_ref("a", 1);
m.insert("b".to_string(), 2);
assert_eq!(Some(&1), m.get("a"));
assert_eq!(Some(&2), m.get("b"));
m.insert_with_key_ref(&string_key, 3);
assert_eq!(Some(&3), m.get(&string_key));
assert_eq!(Some(3), m.delete(&string_key));
assert_eq!(None, m.get(&string_key));
assert_eq!(2, m.len());
}
}
@izderadicka
Copy link
Author

Took me while to realize proper generics :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment