1use core::fmt::Debug;
2use core::ops::Index;
3
4use serde::Deserialize;
5
6use crate::input;
7use crate::key;
8
9const EXECUTION_QUEUE_SIZE: usize = 8;
10
11#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
13pub struct Ref(pub u8);
14
15#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
17pub struct Execution {
18 pub start: u16,
20 pub length: u16,
22}
23
24impl Execution {
25 pub const EMPTY: Self = Self {
27 start: 0,
28 length: 0,
29 };
30
31 pub const fn is_empty(&self) -> bool {
33 self.length == 0
34 }
35
36 pub fn incr(&mut self) {
38 if self.length > 0 {
39 self.start += 1;
40 self.length -= 1;
41 }
42 }
43}
44
45#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
47pub struct KeyInstructions {
48 pub on_press: Execution,
50 pub while_pressed: Execution,
52 pub on_release: Execution,
54}
55
56#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
58pub struct Key {
59 pub automation_instructions: KeyInstructions,
61}
62
63#[derive(Deserialize, Debug, Default, Clone, Copy, PartialEq)]
65pub enum Instruction {
66 #[default]
68 NoOp,
69 Press(key::KeyOutput),
71 Release(key::KeyOutput),
73 Tap(key::KeyOutput),
75 Wait(u16),
77}
78
79#[derive(Deserialize, Clone, Copy, PartialEq)]
81pub struct Config<const INSTRUCTION_COUNT: usize> {
82 #[serde(deserialize_with = "deserialize_instructions")]
86 pub instructions: [Instruction; INSTRUCTION_COUNT],
87
88 #[serde(default = "default_instruction_duration")]
90 pub instruction_duration: u16,
91}
92
93struct InstructionsDebugHelper<'a, const INSTRUCTION_COUNT: usize> {
94 instructions: &'a [Instruction; INSTRUCTION_COUNT],
95}
96
97impl<'a, const INSTRUCTION_COUNT: usize> core::fmt::Debug
98 for InstructionsDebugHelper<'a, INSTRUCTION_COUNT>
99{
100 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
101 let last_non_noop_inst_pos = self
103 .instructions
104 .iter()
105 .rposition(|inst| *inst != Instruction::NoOp)
106 .map_or(0, |pos| pos + 1);
107 if last_non_noop_inst_pos < INSTRUCTION_COUNT {
108 f.debug_list()
109 .entries(&self.instructions[..last_non_noop_inst_pos])
110 .finish_non_exhaustive()
111 } else {
112 f.debug_list().entries(&self.instructions[..]).finish()
113 }
114 }
115}
116
117impl<const INSTRUCTION_COUNT: usize> core::fmt::Debug for Config<INSTRUCTION_COUNT> {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 f.debug_struct("Config")
120 .field(
121 "instructions",
122 &InstructionsDebugHelper {
123 instructions: &self.instructions,
124 },
125 )
126 .field("instruction_duration", &self.instruction_duration)
127 .finish()
128 }
129}
130
131pub const fn instructions<const N: usize, const INSTRUCTION_COUNT: usize>(
133 instructions: [Instruction; N],
134) -> [Instruction; INSTRUCTION_COUNT] {
135 let mut cfg_instructions: [Instruction; INSTRUCTION_COUNT] =
136 [Instruction::NoOp; INSTRUCTION_COUNT];
137
138 if N > INSTRUCTION_COUNT {
139 panic!("Too many instructions for instructions array");
140 }
141
142 let mut i = 0;
143
144 while i < N {
145 cfg_instructions[i] = instructions[i];
146 i += 1;
147 }
148
149 cfg_instructions
150}
151
152fn deserialize_instructions<'de, D, const INSTRUCTION_COUNT: usize>(
154 deserializer: D,
155) -> Result<[Instruction; INSTRUCTION_COUNT], D::Error>
156where
157 D: serde::Deserializer<'de>,
158{
159 let instructions_vec: heapless::Vec<Instruction, INSTRUCTION_COUNT> =
160 Deserialize::deserialize(deserializer)?;
161
162 let mut instructions_array: [Instruction; INSTRUCTION_COUNT] =
163 [Instruction::NoOp; INSTRUCTION_COUNT];
164 for (i, instruction) in instructions_vec.iter().enumerate() {
165 instructions_array[i] = *instruction;
166 }
167
168 Ok(instructions_array)
169}
170
171fn default_instruction_duration() -> u16 {
172 DEFAULT_INSTRUCTION_DURATION
173}
174
175pub const DEFAULT_INSTRUCTION_DURATION: u16 = 10;
177
178impl<const INSTRUCTION_COUNT: usize> Config<INSTRUCTION_COUNT> {
179 pub const fn new() -> Self {
181 Self {
182 instructions: [{ Instruction::NoOp }; INSTRUCTION_COUNT],
183 instruction_duration: DEFAULT_INSTRUCTION_DURATION,
184 }
185 }
186}
187
188impl<const INSTRUCTION_COUNT: usize> Default for Config<INSTRUCTION_COUNT> {
189 fn default() -> Self {
190 Self::new()
191 }
192}
193
194struct ExecutionsDebugHelper<'a> {
195 execution_queue: &'a [Execution; EXECUTION_QUEUE_SIZE],
196}
197
198impl core::fmt::Debug for ExecutionsDebugHelper<'_> {
199 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
200 let last_non_empty_exec_pos = self
202 .execution_queue
203 .iter()
204 .rposition(|exec| !exec.is_empty())
205 .map_or(0, |pos| pos + 1);
206 if last_non_empty_exec_pos < EXECUTION_QUEUE_SIZE {
207 f.debug_list()
208 .entries(&self.execution_queue[..last_non_empty_exec_pos])
209 .finish_non_exhaustive()
210 } else {
211 f.debug_list().entries(&self.execution_queue[..]).finish()
212 }
213 }
214}
215
216#[derive(Clone, Copy, PartialEq)]
218pub struct Context<const INSTRUCTION_COUNT: usize> {
219 config: Config<INSTRUCTION_COUNT>,
220 execution_queue: [Execution; EXECUTION_QUEUE_SIZE],
221}
222
223impl<const INSTRUCTION_COUNT: usize> core::fmt::Debug for Context<INSTRUCTION_COUNT> {
224 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
225 f.debug_struct("Context")
226 .field("config", &self.config)
227 .field(
228 "execution_queue",
229 &ExecutionsDebugHelper {
230 execution_queue: &self.execution_queue,
231 },
232 )
233 .finish()
234 }
235}
236
237impl<const INSTRUCTION_COUNT: usize> Context<INSTRUCTION_COUNT> {
238 pub const fn from_config(config: Config<INSTRUCTION_COUNT>) -> Self {
240 let execution_queue = [Execution::EMPTY; EXECUTION_QUEUE_SIZE];
241 Self {
242 config,
243 execution_queue,
244 }
245 }
246
247 pub fn enqueue(&mut self, new_execution: Execution) -> usize {
249 if new_execution.is_empty() {
251 return EXECUTION_QUEUE_SIZE;
252 }
253
254 for (i, exec) in self.execution_queue.iter_mut().enumerate() {
255 if exec.is_empty() {
256 *exec = new_execution;
257 return i;
258 }
259 }
260
261 EXECUTION_QUEUE_SIZE
263 }
264
265 fn execute_head(&mut self, keymap_index: u16) -> key::KeyEvents<Event> {
266 let mut pke = key_events_for(self.config, keymap_index, self.execution_queue[0]);
267
268 self.execution_queue[0].incr();
269
270 if self.execution_queue[0].is_empty() {
271 self.execution_queue.rotate_left(1);
272 self.execution_queue[EXECUTION_QUEUE_SIZE - 1] = Execution::EMPTY;
273
274 if !self.execution_queue[0].is_empty() {
276 pke.add_event(key::ScheduledEvent::after(
277 self.config.instruction_duration,
278 key::Event::Key {
279 keymap_index,
280 key_event: Event::NextInstruction,
281 },
282 ));
283 }
284 }
285
286 pke
287 }
288}
289
290impl<const INSTRUCTION_COUNT: usize> key::Context for Context<INSTRUCTION_COUNT> {
291 type Event = Event;
292
293 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
294 match event {
295 key::Event::Key {
296 key_event: Event::Enqueue(execution),
297 keymap_index,
298 } if !execution.is_empty() => {
299 let exec_immediately = self.execution_queue[0].is_empty();
300
301 self.enqueue(execution);
302
303 if exec_immediately {
304 self.execute_head(keymap_index)
305 } else {
306 key::KeyEvents::no_events()
307 }
308 }
309 key::Event::Key {
310 key_event: Event::NextInstruction,
311 keymap_index,
312 } => {
313 if !self.execution_queue[0].is_empty() {
314 self.execute_head(keymap_index)
315 } else {
316 key::KeyEvents::no_events()
317 }
318 }
319 _ => key::KeyEvents::no_events(),
320 }
321 }
322}
323
324#[derive(Debug, Clone, Copy, PartialEq)]
326pub enum Event {
327 Enqueue(Execution),
329 NextInstruction,
331 ExecutionFinished,
333}
334
335pub fn key_events_for<const INSTRUCTION_COUNT: usize>(
337 config: Config<INSTRUCTION_COUNT>,
338 keymap_index: u16,
339 Execution { start, length }: Execution,
340) -> key::KeyEvents<Event> {
341 let instruction = config.instructions[start as usize];
342
343 let next_key_ev = if length > 1 {
344 key::Event::Key {
345 keymap_index,
346 key_event: Event::NextInstruction,
347 }
348 } else {
349 key::Event::Key {
350 keymap_index,
351 key_event: Event::ExecutionFinished,
352 }
353 };
354
355 match instruction {
356 Instruction::NoOp => {
357 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
358 key::KeyEvents::scheduled_event(sch_ev)
359 }
360 Instruction::Press(key_output) => {
361 let sch_ev =
362 key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
363 key_output,
364 }));
365
366 let mut pke = key::KeyEvents::scheduled_event(sch_ev);
367 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
368 pke.add_event(sch_ev);
369
370 pke
371 }
372 Instruction::Release(key_output) => {
373 let sch_ev = key::ScheduledEvent::immediate(key::Event::Input(
374 input::Event::VirtualKeyRelease { key_output },
375 ));
376
377 let mut pke = key::KeyEvents::scheduled_event(sch_ev);
378 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
379 pke.add_event(sch_ev);
380
381 pke
382 }
383 Instruction::Tap(key_output) => {
384 let sch_press_ev =
385 key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
386 key_output,
387 }));
388 let sch_release_ev = key::ScheduledEvent::after(
389 config.instruction_duration,
390 key::Event::Input(input::Event::VirtualKeyRelease { key_output }),
391 );
392
393 let mut pke = key::KeyEvents::scheduled_event(sch_press_ev);
394 pke.add_event(sch_release_ev);
395 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
396 pke.add_event(sch_ev);
397
398 pke
399 }
400 Instruction::Wait(ticks) => {
401 let sch_ev = key::ScheduledEvent::after(ticks, next_key_ev);
402 key::KeyEvents::scheduled_event(sch_ev)
403 }
404 }
405}
406
407#[derive(Debug, Clone, Copy, PartialEq)]
409pub struct PendingKeyState;
410
411#[derive(Debug, Clone, Copy, PartialEq)]
413pub struct KeyState;
414
415#[derive(Debug, Clone, Copy, PartialEq)]
417pub struct System<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize> {
418 keys: Keys,
419 _marker: core::marker::PhantomData<(R, [(); INSTRUCTION_COUNT])>,
420}
421
422impl<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
423 System<R, Keys, INSTRUCTION_COUNT>
424{
425 pub const fn new(keys: Keys) -> Self {
427 Self {
428 keys,
429 _marker: core::marker::PhantomData,
430 }
431 }
432}
433
434impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
435 key::System<R> for System<R, Keys, INSTRUCTION_COUNT>
436{
437 type Ref = Ref;
438 type Context = Context<INSTRUCTION_COUNT>;
439 type Event = Event;
440 type PendingKeyState = PendingKeyState;
441 type KeyState = KeyState;
442
443 fn new_pressed_key(
444 &self,
445 keymap_index: u16,
446 _context: &Self::Context,
447 Ref(key_index): Ref,
448 ) -> (
449 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
450 key::KeyEvents<Self::Event>,
451 ) {
452 let pkr = key::PressedKeyResult::Resolved(KeyState);
453
454 let Key {
455 automation_instructions:
456 KeyInstructions {
457 on_press: execution,
458 ..
459 },
460 } = self.keys[key_index as usize];
461 let key_ev = key::Event::Key {
462 keymap_index,
463 key_event: if !execution.is_empty() {
464 Event::Enqueue(execution)
465 } else {
466 Event::ExecutionFinished
468 },
469 };
470 let pke = key::KeyEvents::event(key_ev);
471
472 (pkr, pke)
473 }
474
475 fn update_pending_state(
476 &self,
477 _pending_state: &mut Self::PendingKeyState,
478 _keymap_index: u16,
479 _context: &Self::Context,
480 _key_ref: Ref,
481 _event: key::Event<Self::Event>,
482 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
483 panic!()
484 }
485
486 fn update_state(
487 &self,
488 _key_state: &mut Self::KeyState,
489 Ref(key_index): &Self::Ref,
490 _context: &Self::Context,
491 keymap_index: u16,
492 event: key::Event<Self::Event>,
493 ) -> key::KeyEvents<Self::Event> {
494 match event {
495 key::Event::Key {
496 key_event: Event::ExecutionFinished,
497 keymap_index: ev_kmi,
498 } if keymap_index == ev_kmi => {
499 let Key {
502 automation_instructions:
503 KeyInstructions {
504 while_pressed: execution,
505 ..
506 },
507 } = self.keys[*key_index as usize];
508 let key_ev = key::Event::Key {
509 keymap_index,
510 key_event: Event::Enqueue(execution),
511 };
512 key::KeyEvents::event(key_ev)
513 }
514 key::Event::Input(input::Event::Release {
515 keymap_index: ev_kmi,
516 }) if keymap_index == ev_kmi => {
517 let Key {
520 automation_instructions:
521 KeyInstructions {
522 on_release: execution,
523 ..
524 },
525 } = self.keys[*key_index as usize];
526 let key_ev = key::Event::Key {
527 keymap_index,
528 key_event: Event::Enqueue(execution),
529 };
530 key::KeyEvents::event(key_ev)
531 }
532 _ => key::KeyEvents::no_events(),
533 }
534 }
535
536 fn key_output(
537 &self,
538 _key_ref: &Self::Ref,
539 _key_state: &Self::KeyState,
540 ) -> Option<key::KeyOutput> {
541 None
542 }
543}
544
545#[cfg(test)]
546mod tests {
547 use super::*;
548
549 #[test]
550 fn test_sizeof_ref() {
551 assert_eq!(1, core::mem::size_of::<Ref>());
552 }
553
554 #[test]
555 fn test_sizeof_event() {
556 assert_eq!(6, core::mem::size_of::<Event>());
557 }
558}