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 reset(&mut self) {
249 *self = Self::from_config(self.config);
250 }
251
252 pub fn enqueue(&mut self, new_execution: Execution) -> usize {
254 if new_execution.is_empty() {
256 return EXECUTION_QUEUE_SIZE;
257 }
258
259 for (i, exec) in self.execution_queue.iter_mut().enumerate() {
260 if exec.is_empty() {
261 *exec = new_execution;
262 return i;
263 }
264 }
265
266 EXECUTION_QUEUE_SIZE
268 }
269
270 fn execute_head(&mut self, keymap_index: u16) -> key::KeyEvents<Event> {
271 let mut pke = key_events_for(self.config, keymap_index, self.execution_queue[0]);
272
273 self.execution_queue[0].incr();
274
275 if self.execution_queue[0].is_empty() {
276 self.execution_queue.rotate_left(1);
277 self.execution_queue[EXECUTION_QUEUE_SIZE - 1] = Execution::EMPTY;
278
279 if !self.execution_queue[0].is_empty() {
281 pke.add_event(key::ScheduledEvent::after(
282 self.config.instruction_duration,
283 key::Event::Key {
284 keymap_index,
285 key_event: Event::NextInstruction,
286 },
287 ));
288 }
289 }
290
291 pke
292 }
293}
294
295impl<const INSTRUCTION_COUNT: usize> key::Context for Context<INSTRUCTION_COUNT> {
296 type Event = Event;
297
298 fn reset(&mut self) {
299 Context::reset(self);
300 }
301
302 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
303 match event {
304 key::Event::Key {
305 key_event: Event::Enqueue(execution),
306 keymap_index,
307 } if !execution.is_empty() => {
308 let exec_immediately = self.execution_queue[0].is_empty();
309
310 self.enqueue(execution);
311
312 if exec_immediately {
313 self.execute_head(keymap_index)
314 } else {
315 key::KeyEvents::no_events()
316 }
317 }
318 key::Event::Key {
319 key_event: Event::NextInstruction,
320 keymap_index,
321 } => {
322 if !self.execution_queue[0].is_empty() {
323 self.execute_head(keymap_index)
324 } else {
325 key::KeyEvents::no_events()
326 }
327 }
328 _ => key::KeyEvents::no_events(),
329 }
330 }
331}
332
333#[derive(Debug, Clone, Copy, PartialEq)]
335pub enum Event {
336 Enqueue(Execution),
338 NextInstruction,
340 ExecutionFinished,
342}
343
344pub fn key_events_for<const INSTRUCTION_COUNT: usize>(
346 config: Config<INSTRUCTION_COUNT>,
347 keymap_index: u16,
348 Execution { start, length }: Execution,
349) -> key::KeyEvents<Event> {
350 let instruction = config.instructions[start as usize];
351
352 let next_key_ev = if length > 1 {
353 key::Event::Key {
354 keymap_index,
355 key_event: Event::NextInstruction,
356 }
357 } else {
358 key::Event::Key {
359 keymap_index,
360 key_event: Event::ExecutionFinished,
361 }
362 };
363
364 match instruction {
365 Instruction::NoOp => {
366 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
367 key::KeyEvents::scheduled_event(sch_ev)
368 }
369 Instruction::Press(key_output) => {
370 let sch_ev =
371 key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
372 key_output,
373 }));
374
375 let mut pke = key::KeyEvents::scheduled_event(sch_ev);
376 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
377 pke.add_event(sch_ev);
378
379 pke
380 }
381 Instruction::Release(key_output) => {
382 let sch_ev = key::ScheduledEvent::immediate(key::Event::Input(
383 input::Event::VirtualKeyRelease { key_output },
384 ));
385
386 let mut pke = key::KeyEvents::scheduled_event(sch_ev);
387 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
388 pke.add_event(sch_ev);
389
390 pke
391 }
392 Instruction::Tap(key_output) => {
393 let sch_press_ev =
394 key::ScheduledEvent::immediate(key::Event::Input(input::Event::VirtualKeyPress {
395 key_output,
396 }));
397 let sch_release_ev = key::ScheduledEvent::after(
398 config.instruction_duration,
399 key::Event::Input(input::Event::VirtualKeyRelease { key_output }),
400 );
401
402 let mut pke = key::KeyEvents::scheduled_event(sch_press_ev);
403 pke.add_event(sch_release_ev);
404 let sch_ev = key::ScheduledEvent::after(config.instruction_duration, next_key_ev);
405 pke.add_event(sch_ev);
406
407 pke
408 }
409 Instruction::Wait(ticks) => {
410 let sch_ev = key::ScheduledEvent::after(ticks, next_key_ev);
411 key::KeyEvents::scheduled_event(sch_ev)
412 }
413 }
414}
415
416#[derive(Debug, Clone, Copy, PartialEq)]
418pub struct PendingKeyState;
419
420#[derive(Debug, Clone, Copy, PartialEq)]
422pub struct KeyState;
423
424#[derive(Debug, Clone, Copy, PartialEq)]
426pub struct System<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize> {
427 keys: Keys,
428 _marker: core::marker::PhantomData<(R, [(); INSTRUCTION_COUNT])>,
429}
430
431impl<R: Debug, Keys: Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
432 System<R, Keys, INSTRUCTION_COUNT>
433{
434 pub const fn new(keys: Keys) -> Self {
436 Self {
437 keys,
438 _marker: core::marker::PhantomData,
439 }
440 }
441}
442
443impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key>, const INSTRUCTION_COUNT: usize>
444 key::System<R> for System<R, Keys, INSTRUCTION_COUNT>
445{
446 type Ref = Ref;
447 type Context = Context<INSTRUCTION_COUNT>;
448 type Event = Event;
449 type PendingKeyState = PendingKeyState;
450 type KeyState = KeyState;
451
452 fn new_pressed_key(
453 &self,
454 keymap_index: u16,
455 _context: &Self::Context,
456 Ref(key_index): Ref,
457 ) -> (
458 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
459 key::KeyEvents<Self::Event>,
460 ) {
461 let pkr = key::PressedKeyResult::Resolved(KeyState);
462
463 let Key {
464 automation_instructions:
465 KeyInstructions {
466 on_press: execution,
467 ..
468 },
469 } = self.keys[key_index as usize];
470 let key_ev = key::Event::Key {
471 keymap_index,
472 key_event: if !execution.is_empty() {
473 Event::Enqueue(execution)
474 } else {
475 Event::ExecutionFinished
477 },
478 };
479 let pke = key::KeyEvents::event(key_ev);
480
481 (pkr, pke)
482 }
483
484 fn update_pending_state(
485 &self,
486 _pending_state: &mut Self::PendingKeyState,
487 _keymap_index: u16,
488 _context: &Self::Context,
489 _key_ref: Ref,
490 _event: key::Event<Self::Event>,
491 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
492 panic!()
493 }
494
495 fn update_state(
496 &self,
497 _key_state: &mut Self::KeyState,
498 Ref(key_index): &Self::Ref,
499 _context: &Self::Context,
500 keymap_index: u16,
501 event: key::Event<Self::Event>,
502 ) -> key::KeyEvents<Self::Event> {
503 match event {
504 key::Event::Key {
505 key_event: Event::ExecutionFinished,
506 keymap_index: ev_kmi,
507 } if keymap_index == ev_kmi => {
508 let Key {
511 automation_instructions:
512 KeyInstructions {
513 while_pressed: execution,
514 ..
515 },
516 } = self.keys[*key_index as usize];
517 let key_ev = key::Event::Key {
518 keymap_index,
519 key_event: Event::Enqueue(execution),
520 };
521 key::KeyEvents::event(key_ev)
522 }
523 key::Event::Input(input::Event::Release {
524 keymap_index: ev_kmi,
525 }) if keymap_index == ev_kmi => {
526 let Key {
529 automation_instructions:
530 KeyInstructions {
531 on_release: execution,
532 ..
533 },
534 } = self.keys[*key_index as usize];
535 let key_ev = key::Event::Key {
536 keymap_index,
537 key_event: Event::Enqueue(execution),
538 };
539 key::KeyEvents::event(key_ev)
540 }
541 _ => key::KeyEvents::no_events(),
542 }
543 }
544
545 fn key_output(
546 &self,
547 _key_ref: &Self::Ref,
548 _key_state: &Self::KeyState,
549 ) -> Option<key::KeyOutput> {
550 None
551 }
552}
553
554#[cfg(test)]
555mod tests {
556 use super::*;
557
558 #[test]
559 fn test_sizeof_ref() {
560 assert_eq!(1, core::mem::size_of::<Ref>());
561 }
562
563 #[test]
564 fn test_sizeof_event() {
565 assert_eq!(6, core::mem::size_of::<Event>());
566 }
567}