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