pawkit_input/binding/
map.rs1use std::collections::HashMap;
2
3use pawkit_interner::InternString;
4use serde::{Deserialize, Serialize};
5
6use crate::binding::{AnalogBinding, BindingKind, BindingList, DigitalBinding, VectorBinding};
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub struct BindingMap {
10 #[serde(flatten)]
11 map: HashMap<InternString, BindingList>,
12}
13
14pub enum BindingMapModificaitonError {
15 NotFound,
16 TypeMismatch,
17 BindingAlreadyExists,
18 BindingNotExists,
19}
20
21impl BindingMap {
22 pub fn new() -> Self {
23 return Self {
24 map: HashMap::new(),
25 };
26 }
27
28 pub fn load(s: &str) -> serde_json::Result<Self> {
29 return serde_json::from_str(s);
30 }
31
32 pub fn save(&self) -> String {
33 return serde_json::to_string(self).unwrap();
34 }
35
36 pub fn ensure_prototype(&mut self, prototype: &BindingMap) {
37 self.map.retain(|key, _| prototype.map.contains_key(key));
38
39 for (key, value) in &prototype.map {
40 if self.map.contains_key(key) {
41 continue;
42 }
43
44 self.map.insert(key.clone(), value.clone());
45 }
46 }
47
48 pub fn register_binding(&mut self, name: InternString, mut values: BindingList) {
49 match &mut values {
50 BindingList::Digital(list) => list.dedup(),
51 BindingList::Analog(list) => list.dedup(),
52 BindingList::Vector(list) => list.dedup(),
53 }
54
55 self.map.insert(name, values);
56 }
57
58 pub(crate) fn add_digital_binding(
59 &mut self,
60 name: InternString,
61 value: DigitalBinding,
62 ) -> Result<(), BindingMapModificaitonError> {
63 let Some(list) = self.map.get_mut(&name) else {
64 return Err(BindingMapModificaitonError::NotFound);
65 };
66
67 let BindingList::Digital(bindings) = list else {
68 return Err(BindingMapModificaitonError::TypeMismatch);
69 };
70
71 if bindings.contains(&value) {
72 return Err(BindingMapModificaitonError::BindingAlreadyExists);
73 }
74
75 bindings.push(value);
76
77 return Ok(());
78 }
79
80 pub(crate) fn remove_digital_binding(
81 &mut self,
82 name: InternString,
83 value: DigitalBinding,
84 ) -> Result<(), BindingMapModificaitonError> {
85 let Some(list) = self.map.get_mut(&name) else {
86 return Err(BindingMapModificaitonError::NotFound);
87 };
88
89 let BindingList::Digital(bindings) = list else {
90 return Err(BindingMapModificaitonError::TypeMismatch);
91 };
92
93 if !bindings.contains(&value) {
94 return Err(BindingMapModificaitonError::BindingNotExists);
95 }
96
97 bindings.retain(|it| *it != value);
98
99 return Ok(());
100 }
101
102 pub(crate) fn add_analog_binding(
103 &mut self,
104 name: InternString,
105 value: AnalogBinding,
106 ) -> Result<(), BindingMapModificaitonError> {
107 let Some(list) = self.map.get_mut(&name) else {
108 return Err(BindingMapModificaitonError::NotFound);
109 };
110
111 let BindingList::Analog(bindings) = list else {
112 return Err(BindingMapModificaitonError::TypeMismatch);
113 };
114
115 if bindings.contains(&value) {
116 return Err(BindingMapModificaitonError::BindingAlreadyExists);
117 }
118
119 bindings.push(value);
120
121 return Ok(());
122 }
123
124 pub(crate) fn remove_analog_binding(
125 &mut self,
126 name: InternString,
127 value: AnalogBinding,
128 ) -> Result<(), BindingMapModificaitonError> {
129 let Some(list) = self.map.get_mut(&name) else {
130 return Err(BindingMapModificaitonError::NotFound);
131 };
132
133 let BindingList::Analog(bindings) = list else {
134 return Err(BindingMapModificaitonError::TypeMismatch);
135 };
136
137 if !bindings.contains(&value) {
138 return Err(BindingMapModificaitonError::BindingNotExists);
139 }
140
141 bindings.retain(|it| *it != value);
142
143 return Ok(());
144 }
145
146 pub(crate) fn add_vector_binding(
147 &mut self,
148 name: InternString,
149 value: VectorBinding,
150 ) -> Result<(), BindingMapModificaitonError> {
151 let Some(list) = self.map.get_mut(&name) else {
152 return Err(BindingMapModificaitonError::NotFound);
153 };
154
155 let BindingList::Vector(bindings) = list else {
156 return Err(BindingMapModificaitonError::TypeMismatch);
157 };
158
159 if bindings.contains(&value) {
160 return Err(BindingMapModificaitonError::BindingAlreadyExists);
161 }
162
163 bindings.push(value);
164
165 return Ok(());
166 }
167
168 pub(crate) fn remove_vector_binding(
169 &mut self,
170 name: InternString,
171 value: VectorBinding,
172 ) -> Result<(), BindingMapModificaitonError> {
173 let Some(list) = self.map.get_mut(&name) else {
174 return Err(BindingMapModificaitonError::NotFound);
175 };
176
177 let BindingList::Vector(bindings) = list else {
178 return Err(BindingMapModificaitonError::TypeMismatch);
179 };
180
181 if !bindings.contains(&value) {
182 return Err(BindingMapModificaitonError::BindingNotExists);
183 }
184
185 bindings.retain(|it| *it != value);
186
187 return Ok(());
188 }
189
190 pub fn get_bindings(&self, name: &InternString) -> Option<&BindingList> {
191 return self.map.get(name);
192 }
193
194 pub fn get_binding_kind(&self, name: &InternString) -> Option<BindingKind> {
195 let bindings = self.get_bindings(name)?;
196
197 match bindings {
198 BindingList::Digital(_) => return Some(BindingKind::Digital),
199 BindingList::Analog(_) => return Some(BindingKind::Analog),
200 BindingList::Vector(_) => return Some(BindingKind::Vector),
201 };
202 }
203}
204
205impl IntoIterator for BindingMap {
206 fn into_iter(self) -> Self::IntoIter {
207 return self.map.into_iter();
208 }
209
210 type Item = (InternString, BindingList);
211
212 type IntoIter = <HashMap<InternString, BindingList> as IntoIterator>::IntoIter;
213}
214
215impl<'a> IntoIterator for &'a BindingMap {
216 fn into_iter(self) -> Self::IntoIter {
217 return <&'a HashMap<InternString, BindingList> as IntoIterator>::into_iter(&self.map);
218 }
219
220 type Item = (&'a InternString, &'a BindingList);
221
222 type IntoIter = <&'a HashMap<InternString, BindingList> as IntoIterator>::IntoIter;
223}