use hashbrown::HashMap;
use std::borrow::{Borrow, Cow, ToOwned};
use std::hash::Hash;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Form {
Borrowed,
Owned,
}
pub struct CowHashMap<'a, K, V>
where K: Hash + ?Sized + PartialEq + Eq + ToOwned,
V: ToOwned + ?Sized,
{
inner: HashMap<Cow<'a, K>, Cow<'a, V>>
}
impl<'a, K, V> CowHashMap<'a, K, V>
where K: Hash + ?Sized + PartialEq + Eq + ToOwned,
V: ToOwned + ?Sized,
{
#[inline]
pub fn new() -> Self {
CowHashMap {
inner: HashMap::new()
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
CowHashMap {
inner: HashMap::with_capacity(capacity)
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit();
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear();
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn insert_owned(&mut self, key: <K as ToOwned>::Owned, value: <V as ToOwned>::Owned) -> Option<<V as ToOwned>::Owned> {
self.inner.insert(Cow::Owned(key), Cow::Owned(value)).map(|x| x.into_owned())
}
#[inline]
pub fn insert_owned_borrowed_key(&mut self, key: &'a K, value: <V as ToOwned>::Owned) -> Option<<V as ToOwned>::Owned> {
self.inner.insert(Cow::Borrowed(key), Cow::Owned(value)).map(|x| x.into_owned())
}
#[inline]
pub fn insert_borrowed(&mut self, key: &'a K, value: &'a V) -> Option<<V as ToOwned>::Owned> {
self.inner.insert(Cow::Borrowed(key), Cow::Borrowed(value)).map(|x| x.into_owned())
}
#[inline]
pub fn insert_borrowed_owned_key(&mut self, key: <K as ToOwned>::Owned, value: &'a V) -> Option<<V as ToOwned>::Owned> {
self.inner.insert(Cow::Owned(key), Cow::Borrowed(value)).map(|x| x.into_owned())
}
#[inline]
pub fn get(&self, key: &K) -> Option<&V> {
self.inner.get(key).map(|v| v.as_ref())
}
#[inline]
pub fn get_mut(&mut self, key: &K) -> Option<&mut <V as ToOwned>::Owned> {
self.inner.get_mut(key).map(|v| v.to_mut())
}
#[inline]
#[inline]
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.inner.keys().map(|k| k.borrow())
}
#[inline]
pub fn make_owned(&mut self, key: &K) -> Option<&V> {
let val = self.inner.get_mut(key)?;
match val {
Cow::Borrowed(v) => {
*val = Cow::Owned(v.to_owned());
self.inner.get(key).map(|v| v.as_ref())
}
Cow::Owned(_) => {
self.inner.get(key).map(|v| v.as_ref())
}
}
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn entry_form(&self, key: &K) -> Option<Form> {
let val = self.inner.get(key)?;
match val {
Cow::Borrowed(_) => Some(Form::Borrowed),
Cow::Owned(_) => Some(Form::Owned),
}
}
#[inline]
pub fn borrow_fields(&'a self) -> Self {
let collection: HashMap<Cow<'a, K>, Cow<'a, V>> = self.inner
.iter()
.map(|(k, v)| {
match (k, v) {
(Cow::Owned(key), Cow::Owned(val)) => {
(Cow::Borrowed((*key).borrow()), Cow::Borrowed((*val).borrow()))
}
(Cow::Borrowed(key), Cow::Owned(val)) => {
(Cow::Borrowed(*key), Cow::Borrowed((*val).borrow()))
}
(Cow::Owned(key), Cow::Borrowed(val)) => {
(Cow::Borrowed((*key).borrow()), Cow::Borrowed(*val))
}
(Cow::Borrowed(key), Cow::Borrowed(val)) => {
(Cow::Borrowed(*key), Cow::Borrowed(*val))
}
}
})
.collect();
CowHashMap { inner: collection }
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.inner.iter().map(|(k, v)| (k.borrow(), v.borrow()))
}
pub fn remove(&mut self, key: &K) -> Option<<V as ToOwned>::Owned> {
let val = self.inner.remove(key)?;
match val {
Cow::Borrowed(val) => Some(val.to_owned()),
Cow::Owned(val) => Some(val),
}
}
}
#[macro_use]
mod macros;
#[cfg(test)]
mod tests {
use super::*;
}