matchmaker/
selection.rs

1use crate::Selection;
2use indexmap::IndexMap;
3use rustc_hash::FxBuildHasher;
4use std::sync::Mutex;
5use std::{borrow::Borrow, hash::Hash, sync::Arc};
6
7#[derive(Debug)]
8pub struct SelectionSet<T, S> {
9    selections: SelectionSetImpl<u32, S>,
10    pub identifier: fn(&T) -> (u32, S),
11}
12
13impl<T, S: Selection> SelectionSet<T, S> {
14    pub fn new(identifier: fn(&T) -> (u32, S)) -> Self {
15        Self {
16            selections: SelectionSetImpl::new(),
17            identifier,
18        }
19    }
20
21    pub fn sel(&mut self, item: &T) -> bool {
22        let (k, v) = (self.identifier)(item);
23        self.selections.insert(k, v)
24    }
25
26    pub fn desel(&mut self, item: &T) -> bool {
27        let (k, _v) = (self.identifier)(item);
28        self.selections.remove(&k)
29    }
30
31    pub fn contains(&self, item: &T) -> bool {
32        let (k, _v) = (self.identifier)(item);
33        self.selections.contains(&k)
34    }
35
36    pub fn toggle(&mut self, item: &T) {
37        let (k, v) = (self.identifier)(item);
38        if self.selections.contains(&k) {
39            self.selections.remove(&k);
40        } else {
41            self.selections.insert(k, v);
42        }
43    }
44
45    pub fn clear(&mut self) {
46        self.selections.clear();
47    }
48
49    pub fn len(&self) -> usize {
50        self.selections.len()
51    }
52
53    pub fn is_empty(&self) -> bool {
54        self.selections.is_empty()
55    }
56
57    pub fn output(&mut self) -> impl Iterator<Item = S> {
58        let mut set = self.selections.set.lock().unwrap();
59
60        std::mem::take(&mut *set).into_values()
61    }
62
63    pub fn map_to_vec<I>(&self, items: I) -> Vec<S>
64    where
65    I: IntoIterator,
66    I::Item: std::borrow::Borrow<T> + Send,
67    {
68        // let items_vec: Vec<I::Item> = items.into_iter().collect();
69
70        items
71        .into_iter()
72        // .into_par_iter()
73        .map(|item| (self.identifier)(item.borrow()).1)
74        .collect()
75    }
76
77    pub fn cycle_all_bg<I>(&self, items: I)
78    where
79    I: IntoIterator,
80    I::Item: std::borrow::Borrow<T> + Send,
81    {
82        let results: Vec<_> = items
83        .into_iter()
84        .map(|item| (self.identifier)(item.borrow()))
85        .collect();
86
87        let selections = self.selections.clone();
88
89        tokio::task::spawn_blocking(move || {
90            let mut all = true;
91            let mut set_guard = selections.set.lock().unwrap();
92
93            let mut seen = 0;
94            for (i, (k, _v)) in results.iter().enumerate() {
95                if !set_guard.contains_key(k) {
96                    all = false;
97                    seen = i;
98                    break;
99                }
100            }
101
102            if all {
103                for (k, _v) in results {
104                    set_guard.swap_remove(&k); // swap instead of shift for speed
105                }
106            } else {
107                for (k, v) in results.into_iter().skip(seen) {
108                    set_guard.insert(k, v);
109                }
110            }
111        });
112    }
113}
114
115// ---------- Selection Set ---------------
116#[derive(Debug, Clone)]
117struct SelectionSetImpl<K: Eq + Hash, S> {
118    pub set: Arc<Mutex<IndexMap<K, S, FxBuildHasher>>>,
119}
120
121impl<K: Eq + Hash, S> SelectionSetImpl<K, S>
122where
123S: Selection,
124{
125    pub fn new() -> Self {
126        Self {
127            set: Arc::new(Mutex::new(IndexMap::with_hasher(FxBuildHasher))),
128        }
129    }
130
131    pub fn insert(&self, key: K, value: S) -> bool {
132        let mut set = self.set.lock().unwrap();
133        set.insert(key, value).is_none()
134    }
135
136    pub fn remove(&self, key: &K) -> bool {
137        let mut set = self.set.lock().unwrap();
138        set.shift_remove(key).is_some()
139    }
140
141    pub fn contains(&self, key: &K) -> bool {
142        let set = self.set.lock().unwrap();
143        set.contains_key(key)
144    }
145
146    pub fn clear(&self) {
147        let mut set = self.set.lock().unwrap();
148        set.clear();
149    }
150
151    pub fn clone(&self) -> Self {
152        Self {
153            set: Arc::clone(&self.set),
154        }
155    }
156
157    pub fn len(&self) -> usize {
158        let set = self.set.lock().unwrap();
159        set.len()
160    }
161
162    pub fn is_empty(&self) -> bool {
163        let set = self.set.lock().unwrap();
164        set.is_empty()
165    }
166}