pawkit_input/
binding_map.rs1use std::{
2 collections::HashMap,
3 sync::{Arc, RwLock},
4};
5
6use pawkit_holy_array::HolyArray;
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9
10use crate::bindings::{
11 AnalogBinding, DefaultBinding, DefaultBindingType, DigitalBinding, VectorBinding,
12};
13
14#[repr(u8)]
15#[derive(Error, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16pub enum BindingMapError {
17 #[error("The requested key already exists")]
18 KeyAlreadyExists,
19 #[error("Bindings updated while locked")]
20 BindingUpdateWhileLocked,
21 #[error("Binding map instantiated while unlocked")]
22 InstantiationWhileUnlocked,
23 #[error("Locking failed")]
24 LockIssue,
25}
26
27#[derive(Debug, Serialize, Deserialize)]
28#[serde(tag = "type", content = "bindings")]
29pub enum BindingList {
30 Digital(RwLock<Vec<DigitalBinding>>),
31 Analog(RwLock<Vec<AnalogBinding>>),
32 Vector(RwLock<Vec<VectorBinding>>),
33}
34
35impl Clone for BindingList {
36 fn clone(&self) -> Self {
37 match self {
38 Self::Digital(bindings) => Self::Digital(RwLock::new(bindings.read().unwrap().clone())),
39 Self::Analog(bindings) => Self::Analog(RwLock::new(bindings.read().unwrap().clone())),
40 Self::Vector(bindings) => Self::Vector(RwLock::new(bindings.read().unwrap().clone())),
41 }
42 }
43}
44
45pub struct DefaultBindingMap {
46 pub(crate) index: HashMap<String, usize>,
47 pub(crate) values: Vec<BindingList>,
48
49 pub(crate) locked: bool,
56
57 pub(crate) instances: RwLock<HolyArray<Arc<BindingMap>>>,
58}
59
60#[derive(Serialize, Deserialize)]
61pub struct BindingMapSerializer {
62 #[serde(flatten)]
63 values: HashMap<String, BindingList>,
64}
65
66impl DefaultBindingMap {
67 pub fn new() -> Self {
68 return Self {
69 index: HashMap::new(),
70 values: Vec::new(),
71 locked: false,
72 instances: RwLock::new(HolyArray::new()),
73 };
74 }
75
76 pub fn lock(&mut self) {
77 self.locked = true;
78 }
79
80 pub fn new_instance(&self) -> Result<usize, BindingMapError> {
81 if !self.locked {
82 return Err(BindingMapError::InstantiationWhileUnlocked);
83 }
84
85 let Ok(mut instances) = self.instances.write() else {
86 return Err(BindingMapError::LockIssue);
87 };
88
89 let index = instances.acquire(Arc::new(BindingMap {
90 values: self.values.clone().into_boxed_slice(),
91 }));
92
93 return Ok(index);
94 }
95
96 pub fn delete_instance(&self, id: usize) -> Result<(), BindingMapError> {
97 if !self.locked {
98 return Err(BindingMapError::InstantiationWhileUnlocked);
99 }
100
101 let Ok(mut instances) = self.instances.write() else {
102 return Err(BindingMapError::LockIssue);
103 };
104
105 instances.release(id);
106
107 return Ok(());
108 }
109
110 pub fn get_map(&self, index: usize) -> Option<Arc<BindingMap>> {
111 let instances = self.instances.read().ok()?;
112
113 return Some(instances.get(index)?.clone());
114 }
115
116 pub fn register_raw<'a>(
117 &mut self,
118 name: &str,
119 bindings: DefaultBindingType<'a>,
120 ) -> Result<(), BindingMapError> {
121 if self.locked {
122 return Err(BindingMapError::BindingUpdateWhileLocked);
123 }
124
125 if self.index.contains_key(name) {
126 return Err(BindingMapError::KeyAlreadyExists);
127 }
128
129 let binding_list = match bindings {
130 DefaultBindingType::Analog(analog) => BindingList::Analog(RwLock::new(analog.to_vec())),
131 DefaultBindingType::Digital(digital) => {
132 BindingList::Digital(RwLock::new(digital.to_vec()))
133 }
134 DefaultBindingType::Vector(vector) => BindingList::Vector(RwLock::new(vector.to_vec())),
135 };
136
137 let index = self.values.len();
138
139 self.index.insert(name.into(), index);
140
141 self.values.push(binding_list);
142
143 return Ok(());
144 }
145
146 pub fn register_digital(
147 &mut self,
148 name: &str,
149 bindings: &[DigitalBinding],
150 ) -> Result<(), BindingMapError> {
151 return self.register_raw(name, DefaultBindingType::Digital(bindings));
152 }
153
154 pub fn register_analog(
155 &mut self,
156 name: &str,
157 bindings: &[AnalogBinding],
158 ) -> Result<(), BindingMapError> {
159 return self.register_raw(name, DefaultBindingType::Analog(bindings));
160 }
161
162 pub fn register_vector(
163 &mut self,
164 name: &str,
165 bindings: &[VectorBinding],
166 ) -> Result<(), BindingMapError> {
167 return self.register_raw(name, DefaultBindingType::Vector(bindings));
168 }
169
170 pub fn register(&mut self, bindings: DefaultBinding) -> Result<(), BindingMapError> {
171 return self.register_raw(bindings.name, bindings.bindings);
172 }
173}
174
175pub struct BindingMap {
176 pub(crate) values: Box<[BindingList]>,
178}
179
180impl BindingMap {
181 pub fn deserialize(&mut self, index: &HashMap<String, usize>, serial: BindingMapSerializer) {
182 for (name, bindings) in serial.values {
183 if let Some(slot) = self.get_binding(index, &name) {
184 match slot {
185 BindingList::Analog(slot) => {
186 let BindingList::Analog(bindings) = bindings else {
187 return;
188 };
189
190 let Ok(mut slot) = slot.write() else {
191 return;
192 };
193
194 let Ok(bindings) = bindings.read() else {
195 return;
196 };
197
198 *slot = bindings.clone();
199 }
200
201 BindingList::Digital(slot) => {
202 let BindingList::Digital(bindings) = bindings else {
203 return;
204 };
205
206 let Ok(mut slot) = slot.write() else {
207 return;
208 };
209
210 let Ok(bindings) = bindings.read() else {
211 return;
212 };
213
214 *slot = bindings.clone();
215 }
216
217 BindingList::Vector(slot) => {
218 let BindingList::Vector(bindings) = bindings else {
219 return;
220 };
221
222 let Ok(mut slot) = slot.write() else {
223 return;
224 };
225
226 let Ok(bindings) = bindings.read() else {
227 return;
228 };
229
230 *slot = bindings.clone();
231 }
232 }
233 }
234 }
235 }
236
237 pub fn serialize(&self, index: &HashMap<String, usize>) -> BindingMapSerializer {
238 let mut serial = BindingMapSerializer {
239 values: HashMap::new(),
240 };
241
242 for (name, index) in index {
243 serial
244 .values
245 .insert(name.clone(), self.values[*index].clone());
246 }
247
248 return serial;
249 }
250
251 pub fn get_binding(&self, index: &HashMap<String, usize>, name: &str) -> Option<&BindingList> {
252 let index = *index.get(name)?;
253
254 return Some(&self.values[index]);
255 }
256}