1use crate::nucleo::Indexed;
2use crate::{Identifier, Selection};
3use indexmap::IndexMap;
4use rustc_hash::FxBuildHasher;
5use std::sync::Mutex;
6use std::{borrow::Borrow, hash::Hash, sync::Arc};
7
8pub type SelectionValidator<S> = fn(&S) -> bool;
9
10#[derive(Debug)]
11pub struct Selector<T, S> {
12 selections: Option<SelectorImpl<u32, S>>,
13 pub identifier: Identifier<T, S>,
14 pub validator: SelectionValidator<S>,
15}
16
17pub fn truthy_validator<S>(_: &S) -> bool {
18 true
19}
20
21impl<T> Selector<Indexed<T>, ()> {
22 pub fn new_disabled() -> Self {
24 Self {
25 selections: None,
26 identifier: Indexed::dummy_identifier,
27 validator: truthy_validator,
28 }
29 }
30}
31
32impl<T, S: Selection> Selector<T, S> {
33 pub fn new(identifier: Identifier<T, S>) -> Self {
34 Self {
35 selections: Some(SelectorImpl::new()),
36 identifier,
37 validator: truthy_validator,
38 }
39 }
40
41 pub fn with_validator(mut self, validator: SelectionValidator<S>) -> Self {
42 self.validator = validator;
43 self
44 }
45
46 pub fn disabled(mut self) -> Self {
47 self.selections = None;
48 self
49 }
50
51 pub fn is_disabled(&self) -> bool {
52 self.selections.is_none()
53 }
54
55 pub fn id(&self, item: &T) -> u32 {
56 (self.identifier)(item).0
57 }
58 pub fn eval(&self, item: &T) -> S {
59 (self.identifier)(item).1
60 }
61
62 pub fn sel(&mut self, item: &T) -> bool {
65 let Some(selections) = &mut self.selections else {
66 return false;
67 };
68
69 let (k, v) = (self.identifier)(item);
70 selections.insert(k, v)
71 }
72
73 pub fn desel(&mut self, item: &T) -> bool {
74 let Some(selections) = &mut self.selections else {
75 return false;
76 };
77
78 let (k, _v) = (self.identifier)(item);
79 selections.remove(&k)
80 }
81
82 pub fn contains(&self, item: &T) -> bool {
83 let Some(selections) = &self.selections else {
84 return false;
85 };
86
87 let (k, _v) = (self.identifier)(item);
88 selections.contains(&k)
89 }
90
91 pub fn toggle(&mut self, item: &T) {
92 let Some(selections) = &mut self.selections else {
93 return;
94 };
95
96 let (k, v) = (self.identifier)(item);
97 if selections.contains(&k) {
98 selections.remove(&k);
99 } else {
100 selections.insert(k, v);
101 }
102 }
103
104 pub fn clear(&mut self) {
105 if let Some(selections) = &mut self.selections {
106 selections.clear();
107 }
108 }
109
110 pub fn len(&self) -> usize {
111 self.selections.as_ref().map_or(0, |s| s.len())
112 }
113
114 pub fn is_empty(&self) -> bool {
117 self.selections.as_ref().is_none_or(|s| s.is_empty())
118 }
119
120 pub fn output(&mut self) -> impl Iterator<Item = S> {
121 if let Some(selections) = &mut self.selections {
122 let mut set = selections.set.lock().unwrap();
123 std::mem::take(&mut *set).into_values()
124 } else {
125 IndexMap::with_capacity(0).into_values()
126 }
127 }
128
129 pub fn identify_to_vec<I>(&self, items: I) -> Vec<S>
130 where
131 I: IntoIterator,
132 I::Item: std::borrow::Borrow<T> + Send,
133 {
134 items
135 .into_iter()
136 .map(|item| (self.identifier)(item.borrow()).1)
137 .collect()
138 }
139
140 pub fn map_to_vec<U, F>(&self, f: F) -> Vec<U>
141 where
142 F: FnMut(&S) -> U,
143 {
144 self.selections
145 .as_ref()
146 .map_or_else(Vec::new, |s| s.map_to_vec(f))
147 }
148
149 pub fn map_last<U, F>(&self, f: F) -> Option<U>
150 where
151 F: FnOnce(&S) -> U,
152 {
153 self.selections
154 .as_ref()
155 .and_then(|s| s.map_last(|(_, s)| f(s)))
156 }
157
158 pub fn revalidate(&mut self) {
159 let Some(selections) = &mut self.selections else {
160 return;
161 };
162
163 let mut set = selections.set.lock().unwrap();
164 let validator = &self.validator;
165
166 set.retain(|_, v| validator(v));
167 }
168
169 pub fn cycle_all_bg<I>(&self, items: I)
170 where
171 I: IntoIterator,
172 I::Item: std::borrow::Borrow<T> + Send,
173 {
174 let Some(selections) = &self.selections else {
175 return;
176 };
177
178 let results: Vec<_> = items
179 .into_iter()
180 .map(|item| (self.identifier)(item.borrow()))
181 .collect();
182
183 let selections = selections.clone();
184
185 #[cfg(feature = "parallelism")]
186 tokio::task::spawn_blocking(move || {
187 let mut set_guard = selections.set.lock().unwrap();
188
189 let mut all = true;
190 let mut seen = 0;
191 for (i, (k, _)) in results.iter().enumerate() {
192 if !set_guard.contains_key(k) {
193 all = false;
194 seen = i;
195 break;
196 }
197 }
198
199 if all {
200 for (k, _) in results {
201 set_guard.swap_remove(&k);
202 }
203 } else {
204 for (k, v) in results.into_iter().skip(seen) {
205 set_guard.insert(k, v);
206 }
207 }
208 });
209
210 #[cfg(not(feature = "parallelism"))]
211 {
212 let mut set_guard = selections.set.lock().unwrap();
213
214 let mut all = true;
215 let mut seen = 0;
216 for (i, (k, _)) in results.iter().enumerate() {
217 if !set_guard.contains_key(k) {
218 all = false;
219 seen = i;
220 break;
221 }
222 }
223
224 if all {
225 for (k, _) in results {
226 set_guard.swap_remove(&k);
227 }
228 } else {
229 for (k, v) in results.into_iter().skip(seen) {
230 set_guard.insert(k, v);
231 }
232 }
233 }
234 }
235
236 }
245
246#[derive(Debug, Clone)]
248struct SelectorImpl<K: Eq + Hash, S> {
249 pub set: Arc<Mutex<IndexMap<K, S, FxBuildHasher>>>,
250}
251
252impl<K: Eq + Hash, S> SelectorImpl<K, S>
253where
254 S: Selection,
255{
256 pub fn new() -> Self {
257 Self {
258 set: Arc::new(Mutex::new(IndexMap::with_hasher(FxBuildHasher))),
259 }
260 }
261
262 pub fn insert(&self, key: K, value: S) -> bool {
263 let mut set = self.set.lock().unwrap();
264 set.insert(key, value).is_none()
265 }
266
267 pub fn remove(&self, key: &K) -> bool {
268 let mut set = self.set.lock().unwrap();
269 set.shift_remove(key).is_some()
270 }
271
272 pub fn contains(&self, key: &K) -> bool {
273 let set = self.set.lock().unwrap();
274 set.contains_key(key)
275 }
276
277 pub fn clear(&self) {
278 let mut set = self.set.lock().unwrap();
279 set.clear();
280 }
281
282 pub fn clone(&self) -> Self {
283 Self {
284 set: Arc::clone(&self.set),
285 }
286 }
287
288 pub fn len(&self) -> usize {
289 let set = self.set.lock().unwrap();
290 set.len()
291 }
292
293 pub fn is_empty(&self) -> bool {
294 let set = self.set.lock().unwrap();
295 set.is_empty()
296 }
297
298 pub fn map_to_vec<U, F>(&self, f: F) -> Vec<U>
299 where
300 F: FnMut(&S) -> U,
301 {
302 let set = self.set.lock().unwrap();
303 set.values().map(f).collect()
304 }
305
306 pub fn map_last<U>(&self, f: impl FnOnce((&K, &S)) -> U) -> Option<U> {
307 let set = self.set.lock().unwrap();
308 set.last().map(f)
309 }
310}