pawkit_input/
binding_map.rs

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