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 items
82 .into_iter()
83 .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 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); }
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#[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}