1use std::collections::{HashMap, HashSet};
6use std::sync::atomic::{AtomicU32, Ordering};
7
8pub(crate) fn atomic_update_max(v: &AtomicU32, new: u32) {
14 let mut cur = v.load(Ordering::SeqCst);
19 while cur < new {
20 match v.compare_exchange_weak(cur, new, Ordering::SeqCst, Ordering::SeqCst) {
23 Ok(_) => {
24 break;
26 }
27 Err(new_cur) => {
28 cur = new_cur
30 }
31 }
32 }
33}
34
35pub(crate) fn set_union(a: &HashSet<String>, b: &HashSet<String>) -> HashSet<String> {
37 a.union(b).cloned().collect()
38}
39
40pub(crate) fn set_difference(a: &HashSet<String>, b: &HashSet<String>) -> HashSet<String> {
41 a.difference(b).cloned().collect()
42}
43
44pub(crate) fn set_intersection(a: &HashSet<String>, b: &HashSet<String>) -> HashSet<String> {
45 a.intersection(b).cloned().collect()
46}
47
48pub(crate) fn partition_by_value(v: &HashMap<String, bool>) -> (HashSet<String>, HashSet<String>) {
49 let mut true_: HashSet<String> = HashSet::new();
50 let mut false_: HashSet<String> = HashSet::new();
51 for (s, val) in v {
52 if *val {
53 true_.insert(s.clone());
54 } else {
55 false_.insert(s.clone());
56 }
57 }
58 (true_, false_)
59}
60
61#[cfg(test)]
62mod test {
63 use super::*;
64
65 #[test]
66 fn test_set_ops() {
67 fn hash_set(s: &[&str]) -> HashSet<String> {
68 s.iter()
69 .copied()
70 .map(ToOwned::to_owned)
71 .collect::<HashSet<_>>()
72 }
73
74 assert_eq!(
75 set_union(&hash_set(&["a", "b", "c"]), &hash_set(&["b", "d"])),
76 hash_set(&["a", "b", "c", "d"]),
77 );
78
79 assert_eq!(
80 set_difference(&hash_set(&["a", "b", "c"]), &hash_set(&["b", "d"])),
81 hash_set(&["a", "c"]),
82 );
83 assert_eq!(
84 set_intersection(&hash_set(&["a", "b", "c"]), &hash_set(&["b", "d"])),
85 hash_set(&["b"]),
86 );
87 let m: HashMap<String, bool> = [
88 ("foo", true),
89 ("bar", true),
90 ("baz", false),
91 ("quux", false),
92 ]
93 .iter()
94 .copied()
95 .map(|(a, b)| (a.to_owned(), b))
96 .collect();
97 assert_eq!(
98 partition_by_value(&m),
99 (hash_set(&["foo", "bar"]), hash_set(&["baz", "quux"])),
100 );
101 }
102}