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