bisetmap/
lib.rs

1//! A fast and thread-safe two-way hash map of sets. It is best suited where you need to associate
2//! two collumns uniquely. Each key is associated to one or more other unique values.
3//!
4//! A `BisetMap<L, R>` is a Multi-Hash-Map between values of type `L`, called left values, and values
5//! of type `R`, called right values. This means every left value is associated with one or more
6//! right values and vice versa. Compare this to a [`HashMap`], where every key is associated with
7//! exactly one value.
8//!
9//! The structure is interior mutable and all operations are thread safe. Each clone provides access
10//! to the same underlying data. Serialize and Deserialize from serde are also implemented.
11//!
12//! Internally, a `BisetMap` is composed of two `HashMap`s, one for the left-to-right direction and
13//! one for right-to-left. As such, the big-O performance of the `get`, `remove`, `insert`, and
14//! `contains` methods are the same as those of a `HashMap`.
15//!
16//! As with `HashMap`, it is considered a logic error to modify a value's hash while it is in the
17//! `BisetMap` using a `Cell`, `RefCell`, etc.
18//!
19//! # Examples
20//!
21//! ```
22//! use bisetmap::BisetMap;
23//!
24//! let subscriptions = BisetMap::new();
25//!
26//! // insert client-ids and subscription topics
27//! subscriptions.insert("Bob", "Tech");
28//! subscriptions.insert("Bob", "Math");
29//! subscriptions.insert("Alice", "Tech");
30//! subscriptions.insert("Alice", "Romance");
31//!
32//! // retrieve topic by client-id (left to right)
33//! assert_eq!(subscriptions.get(&"Bob"), ["Math", "Tech"]);
34//! assert_eq!(subscriptions.get(&"Alice"), ["Romance", "Tech"]);
35//!
36//! // retrieve clients by topic (right to left)
37//! assert_eq!(subscriptions.rev_get(&"Tech"), ["Alice", "Bob"]);
38//! assert_eq!(subscriptions.rev_get(&"Math"), ["Bob"]);
39//!
40//! // check membership
41//! assert!(subscriptions.contains(&"Bob", &"Math"));
42//! assert!(!subscriptions.contains(&"Bob", &"Romance"));
43//!
44//! // check key/value existence
45//! assert!(subscriptions.key_exists(&"Alice"));
46//! assert!(subscriptions.value_exists(&"Tech"));
47//! ```
48//!
49//! ## Insertion and Uniqueness
50//!
51//! Consider the following example:
52//!
53//! ```
54//! use bisetmap::BisetMap;
55//!
56//! let bmap = BisetMap::new();
57//! bmap.insert('a', 1);
58//! bmap.insert('a', 1); // what to do here?
59//! ```
60//!
61//! Duplicate key-value pairs are ignored and inserted only once
62//!
63//! [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html
64
65extern crate serde;
66
67use std::collections::{HashMap, HashSet};
68use std::marker::PhantomData;
69use std::sync::{Mutex, Arc};
70use std::hash::Hash;
71use std::fmt;
72
73use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
74use serde::ser::{Serialize, Serializer, SerializeMap};
75
76
77/// A two-way map between keys (left) and values (right).
78///
79/// See the [module-level documentation] for more details and examples.
80///
81/// [module-level documentation]: index.html
82#[derive(Clone)]
83pub struct BisetMap<L:Eq+Hash+Clone, R:Eq+Hash+Clone> {
84	hh: Arc<Mutex<(HashMap<L, HashSet<R>>, HashMap<R, HashSet<L>>)>>
85}
86
87
88fn insert_item<L:Eq+Hash, R:Eq+Hash>(h: &mut HashMap<L, HashSet<R>>, k: L, v: R) {
89	let s = h.entry(k).or_insert_with(HashSet::new);
90	s.insert(v);
91}
92
93fn remove_item<L:Eq+Hash, R:Eq+Hash>(h: &mut HashMap<L, HashSet<R>>, k: L, v: &R) {
94	if let std::collections::hash_map::Entry::Occupied(mut e) = h.entry(k) {
95		e.get_mut().remove(v);
96		if e.get().is_empty() {
97			e.remove_entry();
98		}
99	}
100}
101
102fn get_item<L:Eq+Hash, R:Eq+Hash+Clone>(h: &HashMap<L, HashSet<R>>, k: &L) -> Vec<R> {
103	match h.get(k) {
104		Some(s) => s.iter().map(Clone::clone).collect(),
105		None => vec![]
106	}
107}
108
109fn 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> {
110	match h1.remove(k) {
111		Some(s) => {
112			let r = s.iter().map(Clone::clone).collect();
113			for v in s {
114				remove_item(h2, v, k)
115			}
116			r
117		},
118		None => vec![]
119	}
120}
121
122impl<L:Eq+Hash+Clone, R:Eq+Hash+Clone> BisetMap<L, R> {
123    /// Creates an empty `BisetMap`.
124    ///
125    /// # Examples
126    ///
127    /// ```
128    /// use bisetmap::BisetMap;
129    ///
130    /// let bmap: BisetMap<char, u32> = BisetMap::new();
131	/// ```
132	pub fn new() -> BisetMap<L, R> {
133		BisetMap::default()
134	}
135
136    /// Creates an empty `BisetMap` with the given capacity.
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use bisetmap::BisetMap;
142    ///
143    /// let bmap: BisetMap<char, u32> = BisetMap::with_capacity(5);
144	/// ```
145	pub fn with_capacity(capacity: usize) -> BisetMap<L, R> {
146		BisetMap {
147        	hh: Arc::new(Mutex::new( (HashMap::with_capacity(capacity), HashMap::with_capacity(capacity)) ))
148        }
149	}
150
151    /// Removes all key-value pairs from the `BisetMap`, but keeps the allocated memory for reuse.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// use bisetmap::BisetMap;
157    ///
158    /// let bmap = BisetMap::new();
159    /// bmap.insert('a', 1);
160    /// bmap.insert('b', 2);
161    /// bmap.insert('c', 3);
162    /// bmap.clear();
163    /// assert!(bmap.len() == 0);
164	/// ```
165	pub fn clear(&self) {
166		let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
167		h1.clear();
168		h2.clear();
169	}
170
171    /// Returns a new BisetMap where keys and values are swapped.
172    ///
173    /// # Examples
174    ///
175    /// ```
176    /// use bisetmap::BisetMap;
177    ///
178    /// let bmap = BisetMap::new();
179    /// bmap.insert('a', 1);
180    /// bmap.insert('b', 2);
181    /// bmap.insert('c', 3);
182    /// let rmap = bmap.rev();
183    /// assert_eq!(rmap.get(&1), ['a']);
184	/// ```
185	pub fn rev(&self) -> BisetMap<R, L> {
186		let (ref h1, ref h2) = *self.hh.lock().unwrap();
187		BisetMap {
188        	hh: Arc::new(Mutex::new( (h2.clone(), h1.clone()) ))
189        }
190	}
191
192    /// Returns a vector of (key,values) pairs, where values itself is a vector.
193    /// (Order of all pairs is unknown)
194    ///
195    /// # Examples
196    ///
197    /// ```
198    /// use bisetmap::BisetMap;
199    ///
200    /// let bmap = BisetMap::new();
201    /// bmap.insert('a', 1);
202    /// bmap.insert('a', 2);
203    /// bmap.insert('b', 3);
204    /// assert_eq!(bmap.collect(), vec![('a',vec![1,2]), ('b',vec![3])]);
205	/// ```
206	pub fn collect(&self) -> Vec<(L, Vec<R>)> {
207		self.hh.lock().unwrap().0
208			.iter()
209			.map(|(l, r)| (l.clone(), r.iter().map(Clone::clone).collect()))
210			.collect()
211	}
212
213    /// Returns a vector of (key,value) pairs.
214    /// (Order of pairs is unknown)
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use bisetmap::BisetMap;
220    ///
221    /// let bmap = BisetMap::new();
222    /// bmap.insert('a', 1);
223    /// bmap.insert('a', 2);
224    /// bmap.insert('b', 3);
225    /// assert_eq!(bmap.flat_collect(), [('a',1), ('a',2), ('b',3)]);
226	/// ```
227	pub fn flat_collect(&self) -> Vec<(L, R)> {
228		self.hh.lock().unwrap().0
229			.iter()
230			.flat_map(|(l, rs)| rs.iter().map(move |r| (l.clone(), r.clone())))
231			.collect()
232	}
233
234    /// Inserts the given key-value pair into the `BisetMap`.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// use bisetmap::BisetMap;
240    ///
241    /// let bmap = BisetMap::new();
242    /// bmap.insert('a', 1);
243    /// bmap.insert('a', 1);
244    /// bmap.insert('a', 2);
245    /// bmap.insert('b', 3);
246    /// assert_eq!(bmap.flat_collect(), [('a',1), ('a',2), ('b',3)]);
247	/// ```
248	pub fn insert(&self, k: L, v: R) {
249		let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
250		insert_item(h1, k.clone(), v.clone());
251		insert_item(h2, v, k);
252	}
253
254    /// Removes the specified key-value pair from the `BisetMap`.
255    ///
256    /// # Examples
257    ///
258    /// ```
259    /// use bisetmap::BisetMap;
260    ///
261    /// let bmap = BisetMap::new();
262    /// bmap.insert('a', 1);
263    /// bmap.insert('a', 1);
264    /// bmap.insert('a', 2);
265    /// bmap.insert('c', 3);
266    /// assert_eq!(bmap.len(), 2);
267    /// assert_eq!(bmap.rev_len(), 3);
268    /// bmap.remove(&'a', &2);
269    /// assert_eq!(bmap.len(), 2);
270    /// assert_eq!(bmap.rev_len(), 2);
271	/// ```
272	pub fn remove(&self, k: &L, v: &R) {
273		let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
274		remove_item(h1, k.clone(), &v.clone());
275		remove_item(h2, v.clone(), &k.clone());
276	}
277
278    /// Returns `true` if the map contains the given key-value pair and `false` otherwise.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use bisetmap::BisetMap;
284    ///
285    /// let bmap = BisetMap::new();
286    /// bmap.insert('a', 1);
287    /// assert!(bmap.contains(&'a', &1));
288    /// assert!(!bmap.contains(&'b', &1));
289    /// assert!(!bmap.contains(&'a', &2));
290	/// ```
291	pub fn contains(&self, k: &L, v: &R) -> bool {
292		match self.hh.lock().unwrap().0.get(k) {
293			Some(s) => s.contains(v),
294			None => false
295		}
296	}
297
298    /// Returns `true` if the map contains the given key (left) value and `false` otherwise.
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// use bisetmap::BisetMap;
304    ///
305    /// let bmap = BisetMap::new();
306    /// bmap.insert('a', 1);
307    /// assert!(bmap.key_exists(&'a'));
308    /// assert!(!bmap.key_exists(&'b'));
309	/// ```
310	pub fn key_exists(&self, k: &L) -> bool {
311		self.hh.lock().unwrap().0.contains_key(k)
312	}
313
314    /// Returns `true` if the map contains the given value (right) and `false` otherwise.
315    ///
316    /// # Examples
317    ///
318    /// ```
319    /// use bisetmap::BisetMap;
320    ///
321    /// let bmap = BisetMap::new();
322    /// bmap.insert('a', 1);
323    /// assert!(bmap.value_exists(&1));
324    /// assert!(!bmap.value_exists(&2));
325	/// ```
326	pub fn value_exists(&self, v: &R) -> bool {
327		self.hh.lock().unwrap().1.contains_key(v)
328	}
329
330    /// Returns a vector of values (right) corresponding to the given key (left).
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// use bisetmap::BisetMap;
336    ///
337    /// let bmap = BisetMap::new();
338    /// bmap.insert('a', 1);
339    /// assert_eq!(bmap.get(&'a'), [1]);
340    /// assert_eq!(bmap.get(&'z'), []);
341	/// ```
342	pub fn get(&self, k: &L) -> Vec<R> {
343		get_item(&self.hh.lock().unwrap().0, &k)
344	}
345
346    /// Returns a vector of keys (left) corresponding to the given value (right).
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// use bisetmap::BisetMap;
352    ///
353    /// let bmap = BisetMap::new();
354    /// bmap.insert('a', 1);
355    /// assert_eq!(bmap.rev_get(&1), ['a']);
356    /// assert_eq!(bmap.rev_get(&2), []);
357	/// ```
358	pub fn rev_get(&self, v: &R) -> Vec<L> {
359		get_item(&self.hh.lock().unwrap().1, &v)
360	}
361
362    /// Removes the specified key and all values associated with it.
363    ///
364    /// Returns a vector of previous values associated with given key.
365    ///
366    /// # Examples
367    ///
368    /// ```
369    /// use bisetmap::BisetMap;
370    ///
371    /// let bmap = BisetMap::new();
372    /// bmap.insert('a', 1);
373    /// bmap.insert('a', 2);
374    /// bmap.insert('c', 3);
375    /// assert_eq!(bmap.delete(&'a'), [1, 2]);
376    /// assert_eq!(bmap.len(), 1);
377	/// ```
378	pub fn delete(&self, k: &L) -> Vec<R> {
379		let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
380		remove_items(h1, h2, &k)
381	}
382
383    /// Removes the specified value and all keys associated with it.
384    ///
385    /// Returns a vector of previous keys associated with given value.
386    ///
387    /// # Examples
388    ///
389    /// ```
390    /// use bisetmap::BisetMap;
391    ///
392    /// let bmap = BisetMap::new();
393    /// bmap.insert('a', 1);
394    /// bmap.insert('b', 1);
395    /// bmap.insert('c', 2);
396    /// assert_eq!(bmap.rev_delete(&1), ['a', 'b']);
397    /// assert_eq!(bmap.len(), 1);
398	/// ```
399	pub fn rev_delete(&self, v: &R) -> Vec<L> {
400		let (ref mut h1, ref mut h2) = *self.hh.lock().unwrap();
401		remove_items(h2, h1, &v)
402	}
403
404    /// Returns the number of unique keys (left).
405    ///
406    /// # Examples
407    ///
408    /// ```
409    /// use bisetmap::BisetMap;
410    ///
411    /// let bmap = BisetMap::new();
412    /// bmap.insert('a', 1);
413    /// bmap.insert('b', 2);
414    /// bmap.insert('c', 3);
415    /// bmap.insert('c', 4);
416    /// assert_eq!(bmap.len(), 3);
417	/// ```
418	pub fn len(&self) -> usize {
419		self.hh.lock().unwrap().0.len()
420	}
421
422    /// Returns the number of unique values (right).
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// use bisetmap::BisetMap;
428    ///
429    /// let bmap = BisetMap::new();
430    /// bmap.insert('a', 1);
431    /// bmap.insert('b', 2);
432    /// bmap.insert('c', 3);
433    /// bmap.insert('d', 3);
434    /// assert_eq!(bmap.rev_len(), 3);
435	/// ```
436	pub fn rev_len(&self) -> usize {
437		self.hh.lock().unwrap().1.len()
438	}
439
440    /// Returns `true` if the map contains no key-value pairs, and `false` otherwise.
441    ///
442    /// # Examples
443    ///
444    /// ```
445    /// use bisetmap::BisetMap;
446    ///
447    /// let bmap = BisetMap::new();
448    /// assert!(bmap.is_empty());
449    /// bmap.insert('a', 1);
450    /// assert!(!bmap.is_empty());
451    /// bmap.rev_delete(&1);
452    /// assert!(bmap.is_empty());
453	/// ```
454	pub fn is_empty(&self) -> bool {
455		self.hh.lock().unwrap().0.is_empty()
456	}
457}
458
459
460impl<L: Eq+Hash+Clone, R: Eq+Hash+Clone> Default for BisetMap<L,R> {
461    fn default() -> BisetMap<L, R> {
462        BisetMap {
463        	hh: Arc::new(Mutex::new( (HashMap::default(), HashMap::default()) ))
464        }
465    }
466}
467
468impl<L: Eq+Hash+Clone+fmt::Debug, R: Eq+Hash+Clone+fmt::Debug> fmt::Debug for BisetMap<L, R> {
469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470        write!(f, "{{")?;
471        for (i, (left, right)) in self.hh.lock().unwrap().0.iter().enumerate() {
472            let comma = if i == 0 { "" } else { ", " };
473            write!(f, "{}{:?} => {:?}", comma, left, right)?;
474        }
475        write!(f, "}}")?;
476        Ok(())
477    }
478}
479
480
481
482
483
484impl<L:Eq+Hash+Clone+Serialize, R:Eq+Hash+Clone+Serialize> Serialize for BisetMap<L, R> {
485    fn serialize<S:Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
486    	let data = self.collect();
487        let mut map = serializer.serialize_map(Some(data.len()))?;
488        for (k, v) in data {
489            map.serialize_entry(&k, &v)?;
490        }
491        map.end()
492    }
493}
494
495
496struct BisetMapVisitor<L:Eq+Hash+Clone, R:Eq+Hash+Clone> {
497    marker: PhantomData<fn() -> BisetMap<L, R>>
498}
499
500impl<L:Eq+Hash+Clone, R:Eq+Hash+Clone> BisetMapVisitor<L, R> {
501    fn new() -> Self {
502        BisetMapVisitor {
503            marker: PhantomData
504        }
505    }
506}
507
508impl<'de, L:Eq+Hash+Clone+Deserialize<'de>, R:Eq+Hash+Clone+Deserialize<'de>> Visitor<'de> for BisetMapVisitor<L, R> {
509    type Value = BisetMap<L, R>;
510
511    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
512        formatter.write_str("a biset map")
513    }
514
515    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
516        let bmap = BisetMap::with_capacity(access.size_hint().unwrap_or(0));
517        while let Some((key, values)) = access.next_entry::<L, Vec<R>>()? {
518        	for value in values {
519            	bmap.insert(key.clone(), value);
520            }
521        }
522        Ok(bmap)
523    }
524}
525
526impl<'de, L:Eq+Hash+Clone+Deserialize<'de>, R:Eq+Hash+Clone+Deserialize<'de>> Deserialize<'de> for BisetMap<L, R> {
527    fn deserialize<D:Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
528        deserializer.deserialize_map(BisetMapVisitor::new())
529    }
530}
531
532
533
534
535
536
537#[cfg(test)]
538mod tests {
539	use BisetMap;
540
541	#[test]
542	fn test1() {
543		let h = BisetMap::new();
544		h.insert("sdf", "sdfsd");
545		h.insert("sdf", "sdfsd");
546    	h.insert("a", "1");
547    	h.insert("b", "1");
548    	h.insert("c", "2");
549    	h.insert("c", "3");
550    	h.insert("c", "4");
551
552    	println!("{:?}", h);
553    	println!("{:?}", h.rev());
554    	println!("{:?}", h.collect());
555	}
556
557    #[test]
558    fn clone_works_with_same_internal_memory() {
559    	let h1 = BisetMap::new();
560    	let h2 = h1.clone();
561    	h1.insert("hello", "world");
562        assert_eq!(h2.get(&"hello"), ["world"]);
563    }
564
565    #[test]
566    fn test_len_function() {
567    	let h = BisetMap::new();
568    	assert_eq!(h.len(), 0);
569    	assert_eq!(h.rev_len(),0);
570
571    	h.insert("a", "1");
572    	h.insert("b", "1");
573    	h.insert("c", "2");
574    	assert_eq!(h.len(), 3);
575    	assert_eq!(h.rev_len(),2);
576
577    	h.rev_delete(&"1");
578    	assert_eq!(h.len(), 1);
579    	assert_eq!(h.rev_len(),1);
580    }
581
582    #[test]
583    fn is_empty_after_removal() {
584    	let h = BisetMap::new();
585        assert!(h.is_empty());
586
587    	h.insert("a", "1");
588    	h.insert("b", "1");
589    	h.insert("c", "2");
590        assert!(!h.is_empty());
591
592        h.rev_delete(&"1");
593        h.delete(&"c");
594        assert!(h.is_empty());
595    }
596}