1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::PoisonError;
impl<K: Clone + Eq + Hash, V: Clone + PartialEq> HashMapComparer<K, V> {
pub fn new() -> Self {
Self {
last_map: Arc::new(Mutex::new(HashMap::new())),
}
}
/// Clones last hashmap
pub fn clone_last(&self) -> HashMap<K, V> {
self.last_map.lock().unwrap().clone()
}
/// Checks if last hashmap is the same as new one
pub fn is_same(&self, comparable: &HashMap<K, V>) -> bool {
self.last_map.lock().unwrap().iter().eq(comparable)
}
/// Updates last hashmap to a new value
pub fn update(&self, new_map: &HashMap<K, V>) {
self.last_map.lock().unwrap().clone_from(new_map);
}
/// Checks if last hashmap is the same as new one and updates it to be that new value
pub fn is_same_update(&self, new_map: &HashMap<K, V>) -> bool {
let is_same = self.is_same(new_map);
self.update(new_map);
is_same
}
/// Updates last hashmap, compares new one to the last one and returns changed values.
/// If you want to compare hashmap without updating last hashmap use``` compare()```.
/// If you want to update hashmap without comparing it use ```update()``` and if you want to return bool instead of changed values use ```is_same()``` or ```is_same_update()```.
///
/// # Examples
/// ```
/// use std::collections::HashMap;
/// use comparer::HashMapComparer;
/// let comparer = HashMapComparer::<u8, &str>::new();
/// let mut my_hashmap = HashMap::<u8, &str>::new();
/// my_hashmap.insert(1, "foo");
/// my_hashmap.insert(2, "bar");
/// my_hashmap.insert(4, "foo");
/// let mut results: Vec<HashMap<u8, &str>> = vec![];
/// for i in 0..5 {
/// my_hashmap.insert(i, "foo");
/// results.push(comparer.update_and_compare(&my_hashmap).unwrap());
/// }
/// assert_eq!(
/// vec![
/// // In a first comparison comparer always returns whole hashmap because all values in it is new
/// HashMap::<u8, &str>::from_iter(vec![(0, "foo"), (4, "foo"), (2, "bar"), (1, "foo")]),
/// // Returns empty hashmap because value 1: "foo" didn't change
/// HashMap::<u8, &str>::new(),
/// // Returns hashmap with 2: "foo" because it was changed from 2: "bar"
/// HashMap::<u8, &str>::from_iter(vec![(2, "foo")]),
/// // Returns hashmap with 3: "foo" because it's a new value
/// HashMap::<u8, &str>::from_iter(vec![(3, "foo")]),
/// //Returns empty hashmap because value 4: "foo" didn't change
/// HashMap::<u8, &str>::new(),
/// ],
/// results
/// );
/// ```
pub fn update_and_compare(
&self,
new_map: &HashMap<K, V>,
) -> Result<HashMap<K, V>, PoisonError<K>> {
let mut last_map = self.last_map.lock().unwrap();
let mut changed_values: HashMap<K, V> = HashMap::new();
if !last_map.is_empty() {
for (key, value) in new_map.iter() {
if last_map.contains_key(key) {
if value != last_map.get(key).unwrap() {
changed_values.insert(key.clone(), value.clone());
}
} else {
changed_values.insert(key.clone(), value.clone());
}
}
last_map.clone_from(new_map);
return Ok(changed_values);
}
last_map.clone_from(new_map);
Ok(new_map.clone())
}
/// Compares new hashmap to the last one and returns changed values
pub fn compare(&self, new_map: &HashMap<K, V>) -> Result<HashMap<K, V>, PoisonError<K>> {
let last_map = self.last_map.lock().unwrap();
let mut changed_values: HashMap<K, V> = HashMap::new();
if !last_map.is_empty() {
for (key, value) in new_map.iter() {
if last_map.contains_key(key) {
if value != last_map.get(key).unwrap() {
changed_values.insert(key.clone(), value.clone());
}
} else {
changed_values.insert(key.clone(), value.clone());
}
}
return Ok(changed_values);
}
Ok(new_map.clone())
}
}
/// HashMapC
#[derive(Debug, Clone)]
pub struct HashMapComparer<K: Clone + Eq + Hash, V: Clone + PartialEq> {
last_map: Arc<Mutex<HashMap<K, V>>>,
}
impl<K: Clone + Eq + Hash, V: Clone + PartialEq> Default for HashMapComparer<K, V> {
fn default() -> Self {
HashMapComparer::new()
}
}