extern crate serde;
use std::collections::{HashMap, HashSet};
use std::marker::PhantomData;
use std::sync::{Mutex, Arc};
use std::hash::Hash;
use std::fmt;
use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
use serde::ser::{Serialize, Serializer, SerializeMap};
#[derive(Clone)]
pub struct BisetMap<L:Eq+Hash+Clone, R:Eq+Hash+Clone> {
hh: Arc<Mutex<(HashMap<L, HashSet<R>>, HashMap<R, HashSet<L>>)>>
}
fn insert_item<L:Eq+Hash, R:Eq+Hash>(h: &mut HashMap<L, HashSet<R>>, k: L, v: R) {
let s = h.entry(k).or_insert_with(HashSet::new);
s.insert(v);
}
fn remove_item<L:Eq+Hash, R:Eq+Hash>(h: &mut HashMap<L, HashSet<R>>, k: L, v: &R) {
if let std::collections::hash_map::Entry::Occupied(mut e) = h.entry(k) {
e.get_mut().remove(v);
if e.get().is_empty() {
e.remove_entry();
}
}
}
fn get_item<L:Eq+Hash, R:Eq+Hash+Clone>(h: &HashMap<L, HashSet<R>>, k: &L) -> Vec<R> {
match h.get(k) {
Some(s) => s.iter().map(Clone::clone).collect(),
None => vec![]
}
}
fn remove_items<L:Eq+Hash, R:Eq+Hash+Clone>(h1: &mut HashMap<L, HashSet<R>>, h2: &mut HashMap<R, HashSet<L>>, k: &L) -> Vec<R> {
match h1.remove(k) {
Some(s) => {
let r = s.iter().map(Clone::clone).collect();
for v in s {
remove_item(h2, v, k)
}
r
},
None => vec![]
}
}
impl<L:Eq+Hash+Clone, R:Eq+Hash+Clone> BisetMap<L, R> {
pub fn new() -> BisetMap<L, R> {
BisetMap::default()
}
pub fn with_capacity(capacity: usize) -> BisetMap<L, R> {
BisetMap {
hh: Arc::new(Mutex::new( (HashMap::with_capacity(capacity), HashMap::with_capacity(capacity)) ))
}
}
pub fn clear(&self) {
let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
h1.clear();
h2.clear();
}
pub fn rev(&self) -> BisetMap<R, L> {
let (ref h1, ref h2) = *self.hh.lock().unwrap();
BisetMap {
hh: Arc::new(Mutex::new( (h2.clone(), h1.clone()) ))
}
}
pub fn collect(&self) -> Vec<(L, Vec<R>)> {
self.hh.lock().unwrap().0
.iter()
.map(|(l, r)| (l.clone(), r.iter().map(Clone::clone).collect()))
.collect()
}
pub fn flat_collect(&self) -> Vec<(L, R)> {
self.hh.lock().unwrap().0
.iter()
.flat_map(|(l, rs)| rs.iter().map(move |r| (l.clone(), r.clone())))
.collect()
}
pub fn insert(&self, k: L, v: R) {
let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
insert_item(h1, k.clone(), v.clone());
insert_item(h2, v, k);
}
pub fn remove(&self, k: &L, v: &R) {
let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
remove_item(h1, k.clone(), &v.clone());
remove_item(h2, v.clone(), &k.clone());
}
pub fn contains(&self, k: &L, v: &R) -> bool {
match self.hh.lock().unwrap().0.get(k) {
Some(s) => s.contains(v),
None => false
}
}
pub fn key_exists(&self, k: &L) -> bool {
self.hh.lock().unwrap().0.contains_key(k)
}
pub fn value_exists(&self, v: &R) -> bool {
self.hh.lock().unwrap().1.contains_key(v)
}
pub fn get(&self, k: &L) -> Vec<R> {
get_item(&self.hh.lock().unwrap().0, &k)
}
pub fn rev_get(&self, v: &R) -> Vec<L> {
get_item(&self.hh.lock().unwrap().1, &v)
}
pub fn delete(&self, k: &L) -> Vec<R> {
let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
remove_items(h1, h2, &k)
}
pub fn rev_delete(&self, v: &R) -> Vec<L> {
let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
remove_items(h2, h1, &v)
}
pub fn len(&self) -> usize {
self.hh.lock().unwrap().0.len()
}
pub fn rev_len(&self) -> usize {
self.hh.lock().unwrap().1.len()
}
pub fn is_empty(&self) -> bool {
self.hh.lock().unwrap().0.is_empty()
}
}
impl<L: Eq+Hash+Clone, R: Eq+Hash+Clone> Default for BisetMap<L,R> {
fn default() -> BisetMap<L, R> {
BisetMap {
hh: Arc::new(Mutex::new( (HashMap::default(), HashMap::default()) ))
}
}
}
impl<L: Eq+Hash+Clone+fmt::Debug, R: Eq+Hash+Clone+fmt::Debug> fmt::Debug for BisetMap<L, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{")?;
for (i, (left, right)) in self.hh.lock().unwrap().0.iter().enumerate() {
let comma = if i == 0 { "" } else { ", " };
write!(f, "{}{:?} => {:?}", comma, left, right)?;
}
write!(f, "}}")?;
Ok(())
}
}
impl<L:Eq+Hash+Clone+Serialize, R:Eq+Hash+Clone+Serialize> Serialize for BisetMap<L, R> {
fn serialize<S:Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let data = self.collect();
let mut map = serializer.serialize_map(Some(data.len()))?;
for (k, v) in data {
map.serialize_entry(&k, &v)?;
}
map.end()
}
}
struct BisetMapVisitor<L:Eq+Hash+Clone, R:Eq+Hash+Clone> {
marker: PhantomData<fn() -> BisetMap<L, R>>
}
impl<L:Eq+Hash+Clone, R:Eq+Hash+Clone> BisetMapVisitor<L, R> {
fn new() -> Self {
BisetMapVisitor {
marker: PhantomData
}
}
}
impl<'de, L:Eq+Hash+Clone+Deserialize<'de>, R:Eq+Hash+Clone+Deserialize<'de>> Visitor<'de> for BisetMapVisitor<L, R> {
type Value = BisetMap<L, R>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a biset map")
}
fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
let bmap = BisetMap::with_capacity(access.size_hint().unwrap_or(0));
while let Some((key, values)) = access.next_entry::<L, Vec<R>>()? {
for value in values {
bmap.insert(key.clone(), value);
}
}
Ok(bmap)
}
}
impl<'de, L:Eq+Hash+Clone+Deserialize<'de>, R:Eq+Hash+Clone+Deserialize<'de>> Deserialize<'de> for BisetMap<L, R> {
fn deserialize<D:Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_map(BisetMapVisitor::new())
}
}
#[cfg(test)]
mod tests {
use BisetMap;
#[test]
fn test1() {
let h = BisetMap::new();
h.insert("sdf", "sdfsd");
h.insert("sdf", "sdfsd");
h.insert("a", "1");
h.insert("b", "1");
h.insert("c", "2");
h.insert("c", "3");
h.insert("c", "4");
println!("{:?}", h);
println!("{:?}", h.rev());
println!("{:?}", h.collect());
}
#[test]
fn clone_works_with_same_internal_memory() {
let h1 = BisetMap::new();
let h2 = h1.clone();
h1.insert("hello", "world");
assert_eq!(h2.get(&"hello"), ["world"]);
}
#[test]
fn test_len_function() {
let h = BisetMap::new();
assert_eq!(h.len(), 0);
assert_eq!(h.rev_len(),0);
h.insert("a", "1");
h.insert("b", "1");
h.insert("c", "2");
assert_eq!(h.len(), 3);
assert_eq!(h.rev_len(),2);
h.rev_delete(&"1");
assert_eq!(h.len(), 1);
assert_eq!(h.rev_len(),1);
}
#[test]
fn is_empty_after_removal() {
let h = BisetMap::new();
assert!(h.is_empty());
h.insert("a", "1");
h.insert("b", "1");
h.insert("c", "2");
assert!(!h.is_empty());
h.rev_delete(&"1");
h.delete(&"c");
assert!(h.is_empty());
}
}