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