matchmaker/
selection.rs

1use crate::{Identifier, Selection};
2use indexmap::IndexMap;
3use rustc_hash::FxBuildHasher;
4use std::sync::Mutex;
5use std::{borrow::Borrow, hash::Hash, sync::Arc};
6
7pub type SelectionValidator<S> = fn(&S) -> bool;
8#[derive(Debug)]
9pub struct Selector<T, S> {
10    selections: SelectorImpl<u32, S>,
11    pub identifier: Identifier<T, S>,
12    pub validator: SelectionValidator<S>,
13}
14
15pub fn truthy_validator<S>(_: &S) -> bool {
16    true
17}
18
19impl<T, S: Selection> Selector<T, S> {
20    pub fn new(identifier: Identifier<T, S>) -> Self {
21        Self::new_with_validator(identifier, truthy_validator)
22    }
23
24    pub fn new_with_validator(
25        identifier: Identifier<T, S>,
26        validator: SelectionValidator<S>,
27    ) -> Self {
28        Self {
29            selections: SelectorImpl::new(),
30            identifier,
31            validator,
32        }
33    }
34
35    pub fn sel(&mut self, item: &T) -> bool {
36        let (k, v) = (self.identifier)(item);
37        self.selections.insert(k, v)
38    }
39
40    pub fn desel(&mut self, item: &T) -> bool {
41        let (k, _v) = (self.identifier)(item);
42        self.selections.remove(&k)
43    }
44
45    pub fn contains(&self, item: &T) -> bool {
46        let (k, _v) = (self.identifier)(item);
47        self.selections.contains(&k)
48    }
49
50    pub fn toggle(&mut self, item: &T) {
51        let (k, v) = (self.identifier)(item);
52        if self.selections.contains(&k) {
53            self.selections.remove(&k);
54        } else {
55            self.selections.insert(k, v);
56        }
57    }
58
59    pub fn clear(&mut self) {
60        self.selections.clear();
61    }
62
63    pub fn len(&self) -> usize {
64        self.selections.len()
65    }
66
67    pub fn is_empty(&self) -> bool {
68        self.selections.is_empty()
69    }
70
71    pub fn output(&mut self) -> impl Iterator<Item = S>
72// indexmap::map::IntoValues<u32, S>
73    {
74        let mut set = self.selections.set.lock().unwrap();
75
76        std::mem::take(&mut *set).into_values()
77    }
78
79    pub fn identify_to_vec<I>(&self, items: I) -> Vec<S>
80    where
81        I: IntoIterator,
82        I::Item: std::borrow::Borrow<T> + Send,
83    {
84        // let items_vec: Vec<I::Item> = items.into_iter().collect();
85
86        items
87            .into_iter()
88            // .into_par_iter()
89            .map(|item| (self.identifier)(item.borrow()).1)
90            .collect()
91    }
92
93    pub fn map_to_vec<U, F>(&self, f: F) -> Vec<U>
94    where
95        F: FnMut(&S) -> U,
96    {
97        // let items_vec: Vec<I::Item> = items.into_iter().collect();
98        self.selections.map_to_vec(f)
99    }
100
101    pub fn revalidate(&mut self) {
102        let mut set = self.selections.set.lock().unwrap();
103        let validator = &self.validator;
104
105        set.retain(|_, v| validator(v));
106    }
107
108    pub fn cycle_all_bg<I>(&self, items: I)
109    where
110        I: IntoIterator,
111        I::Item: std::borrow::Borrow<T> + Send,
112    {
113        let results: Vec<_> = items
114            .into_iter()
115            .map(|item| (self.identifier)(item.borrow()))
116            .collect();
117
118        let selections = self.selections.clone();
119
120        #[cfg(feature = "parallelism")]
121        tokio::task::spawn_blocking(move || {
122            let mut all = true;
123            let mut set_guard = selections.set.lock().unwrap();
124
125            let mut seen = 0;
126            for (i, (k, _v)) in results.iter().enumerate() {
127                if !set_guard.contains_key(k) {
128                    all = false;
129                    seen = i;
130                    break;
131                }
132            }
133
134            if all {
135                for (k, _v) in results {
136                    set_guard.swap_remove(&k); // swap instead of shift for speed
137                }
138            } else {
139                for (k, v) in results.into_iter().skip(seen) {
140                    set_guard.insert(k, v);
141                }
142            }
143        });
144        #[cfg(not(feature = "parallelism"))]
145        {
146            let mut all = true;
147            let mut set_guard = selections.set.lock().unwrap();
148
149            let mut seen = 0;
150            for (i, (k, _v)) in results.iter().enumerate() {
151                if !set_guard.contains_key(k) {
152                    all = false;
153                    seen = i;
154                    break;
155                }
156            }
157
158            if all {
159                for (k, _v) in results {
160                    set_guard.swap_remove(&k); // swap instead of shift for speed
161                }
162            } else {
163                for (k, v) in results.into_iter().skip(seen) {
164                    set_guard.insert(k, v);
165                }
166            };
167        };
168    }
169}
170
171// ---------- Selection Set ---------------
172#[derive(Debug, Clone)]
173struct SelectorImpl<K: Eq + Hash, S> {
174    pub set: Arc<Mutex<IndexMap<K, S, FxBuildHasher>>>,
175}
176
177impl<K: Eq + Hash, S> SelectorImpl<K, S>
178where
179    S: Selection,
180{
181    pub fn new() -> Self {
182        Self {
183            set: Arc::new(Mutex::new(IndexMap::with_hasher(FxBuildHasher))),
184        }
185    }
186
187    pub fn insert(&self, key: K, value: S) -> bool {
188        let mut set = self.set.lock().unwrap();
189        set.insert(key, value).is_none()
190    }
191
192    pub fn remove(&self, key: &K) -> bool {
193        let mut set = self.set.lock().unwrap();
194        set.shift_remove(key).is_some()
195    }
196
197    pub fn contains(&self, key: &K) -> bool {
198        let set = self.set.lock().unwrap();
199        set.contains_key(key)
200    }
201
202    pub fn clear(&self) {
203        let mut set = self.set.lock().unwrap();
204        set.clear();
205    }
206
207    pub fn clone(&self) -> Self {
208        Self {
209            set: Arc::clone(&self.set),
210        }
211    }
212
213    pub fn len(&self) -> usize {
214        let set = self.set.lock().unwrap();
215        set.len()
216    }
217
218    pub fn is_empty(&self) -> bool {
219        let set = self.set.lock().unwrap();
220        set.is_empty()
221    }
222
223    pub fn map_to_vec<U, F>(&self, f: F) -> Vec<U>
224    where
225        F: FnMut(&S) -> U,
226    {
227        let set = self.set.lock().unwrap();
228        set.values().map(f).collect()
229    }
230}