smart_keymap/key/
composite.rs

1//! This module aggregates various [crate::key::System] implementations.
2
3use core::fmt::Debug;
4use core::marker::PhantomData;
5use core::ops::Index;
6
7use serde::Deserialize;
8
9use crate::{key, keymap};
10
11use crate::init::AUTOMATION_INSTRUCTION_COUNT;
12use crate::init::CHORDED_MAX_CHORDS;
13use crate::init::CHORDED_MAX_CHORD_SIZE;
14use crate::init::CHORDED_MAX_OVERLAPPING_CHORD_SIZE;
15use crate::init::LAYERED_LAYER_COUNT;
16use crate::init::TAP_DANCE_MAX_DEFINITIONS as TAP_DANCE_MAX_DEF_COUNT;
17
18const CHORDED_MAX_PRESSED_INDICES: usize = CHORDED_MAX_CHORD_SIZE * 2;
19
20/// Type aliases for convenience.
21pub type AutomationRef = key::automation::Ref;
22/// Type aliases for convenience.
23pub type AutomationKey = key::automation::Key;
24/// Type aliases for convenience.
25pub type AutomationConfig = key::automation::Config<AUTOMATION_INSTRUCTION_COUNT>;
26/// Type aliases for convenience.
27pub type AutomationContext = key::automation::Context<AUTOMATION_INSTRUCTION_COUNT>;
28/// Type aliases for convenience.
29pub type AutomationEvent = key::automation::Event;
30/// Type aliases for convenience.
31pub type AutomationPendingKeyState = key::automation::PendingKeyState;
32/// Type aliases for convenience.
33pub type AutomationKeyState = key::automation::KeyState;
34/// Type aliases for convenience.
35pub type AutomationSystem<D> = key::automation::System<Ref, D, AUTOMATION_INSTRUCTION_COUNT>;
36
37/// Type aliases for convenience.
38pub type CallbackRef = key::callback::Ref;
39/// Type aliases for convenience.
40pub type CallbackKey = key::callback::Key;
41/// Type aliases for convenience.
42pub type CallbackContext = key::callback::Context;
43/// Type aliases for convenience.
44pub type CallbackEvent = key::callback::Event;
45/// Type aliases for convenience.
46pub type CallbackPendingKeyState = key::callback::PendingKeyState;
47/// Type aliases for convenience.
48pub type CallbackKeyState = key::callback::KeyState;
49/// Type aliases for convenience.
50pub type CallbackSystem<D> = key::callback::System<Ref, D>;
51
52/// Type aliases for convenience.
53pub type CapsWordRef = key::caps_word::Ref;
54/// Type aliases for convenience.
55pub type CapsWordKey = key::caps_word::Key;
56/// Type aliases for convenience.
57pub type CapsWordContext = key::caps_word::Context;
58/// Type aliases for convenience.
59pub type CapsWordEvent = key::caps_word::Event;
60/// Type aliases for convenience.
61pub type CapsWordPendingKeyState = key::caps_word::PendingKeyState;
62/// Type aliases for convenience.
63pub type CapsWordKeyState = key::caps_word::KeyState;
64/// Type aliases for convenience.
65pub type CapsWordSystem = key::caps_word::System<Ref>;
66
67/// Type aliases for convenience.
68pub type ChordedRef = key::chorded::Ref;
69/// Type aliases for convenience.
70pub type ChordedKey = key::chorded::Key<
71    Ref,
72    CHORDED_MAX_CHORDS,
73    CHORDED_MAX_CHORD_SIZE,
74    CHORDED_MAX_OVERLAPPING_CHORD_SIZE,
75    CHORDED_MAX_PRESSED_INDICES,
76>;
77/// Type aliases for convenience.
78pub type ChordedAuxiliaryKey = key::chorded::AuxiliaryKey<
79    Ref,
80    CHORDED_MAX_CHORDS,
81    CHORDED_MAX_CHORD_SIZE,
82    CHORDED_MAX_PRESSED_INDICES,
83>;
84/// Type aliases for convenience.
85pub type ChordedConfig = key::chorded::Config<CHORDED_MAX_CHORDS, CHORDED_MAX_CHORD_SIZE>;
86/// Type aliases for convenience.
87pub type ChordedContext =
88    key::chorded::Context<CHORDED_MAX_CHORDS, CHORDED_MAX_CHORD_SIZE, CHORDED_MAX_PRESSED_INDICES>;
89/// Type aliases for convenience.
90pub type ChordedEvent = key::chorded::Event;
91/// Type aliases for convenience.
92pub type ChordedPendingKeyState = key::chorded::PendingKeyState<
93    CHORDED_MAX_CHORDS,
94    CHORDED_MAX_CHORD_SIZE,
95    CHORDED_MAX_PRESSED_INDICES,
96>;
97/// Type aliases for convenience.
98pub type ChordedKeyState = key::chorded::KeyState;
99/// Type aliases for convenience.
100pub type ChordedSystem<D, AuxD> = key::chorded::System<
101    Ref,
102    D,
103    AuxD,
104    CHORDED_MAX_CHORDS,
105    CHORDED_MAX_CHORD_SIZE,
106    CHORDED_MAX_OVERLAPPING_CHORD_SIZE,
107    CHORDED_MAX_PRESSED_INDICES,
108>;
109
110/// Type aliases for convenience.
111pub type ConsumerRef = key::consumer::Ref;
112/// Type aliases for convenience.
113pub type ConsumerContext = key::consumer::Context;
114/// Type aliases for convenience.
115pub type ConsumerEvent = key::consumer::Event;
116/// Type aliases for convenience.
117pub type ConsumerPendingKeyState = key::consumer::PendingKeyState;
118/// Type aliases for convenience.
119pub type ConsumerKeyState = key::consumer::KeyState;
120/// Type aliases for convenience.
121pub type ConsumerSystem = key::consumer::System<Ref>;
122
123/// Type aliases for convenience.
124pub type CustomRef = key::custom::Ref;
125/// Type aliases for convenience.
126pub type CustomContext = key::custom::Context;
127/// Type aliases for convenience.
128pub type CustomEvent = key::custom::Event;
129/// Type aliases for convenience.
130pub type CustomPendingKeyState = key::custom::PendingKeyState;
131/// Type aliases for convenience.
132pub type CustomKeyState = key::custom::KeyState;
133/// Type aliases for convenience.
134pub type CustomSystem = key::custom::System<Ref>;
135
136/// Type aliases for convenience.
137pub type KeyboardRef = key::keyboard::Ref;
138/// Type aliases for convenience.
139pub type KeyboardKey = key::keyboard::Key;
140/// Type aliases for convenience.
141pub type KeyboardContext = key::keyboard::Context;
142/// Type aliases for convenience.
143pub type KeyboardEvent = key::keyboard::Event;
144/// Type aliases for convenience.
145pub type KeyboardPendingKeyState = key::keyboard::PendingKeyState;
146/// Type aliases for convenience.
147pub type KeyboardKeyState = key::keyboard::KeyState;
148/// Type aliases for convenience.
149pub type KeyboardSystem<D> = key::keyboard::System<Ref, D>;
150
151/// Type aliases for convenience.
152pub type LayeredRef = key::layered::Ref;
153/// Type aliases for convenience.
154pub type LayeredKey = key::layered::LayeredKey<Ref, LAYERED_LAYER_COUNT>;
155/// Type aliases for convenience.
156pub type LayeredModifierKey = key::layered::ModifierKey;
157/// Type aliases for convenience.
158pub type LayeredContext = key::layered::Context<LAYERED_LAYER_COUNT>;
159/// Type aliases for convenience.
160pub type LayeredEvent = key::layered::LayerEvent;
161/// Type aliases for convenience.
162pub type LayeredPendingKeyState = key::layered::PendingKeyState;
163/// Type aliases for convenience.
164pub type LayeredKeyState = key::layered::ModifierKeyState;
165/// Type aliases for convenience.
166pub type LayeredSystem<LM, L> = key::layered::System<Ref, LM, L, LAYERED_LAYER_COUNT>;
167
168/// Type aliases for convenience.
169pub type MouseRef = key::mouse::Ref;
170/// Type aliases for convenience.
171pub type MouseContext = key::mouse::Context;
172/// Type aliases for convenience.
173pub type MouseEvent = key::mouse::Event;
174/// Type aliases for convenience.
175pub type MousePendingKeyState = key::mouse::PendingKeyState;
176/// Type aliases for convenience.
177pub type MouseKeyState = key::mouse::KeyState;
178/// Type aliases for convenience.
179pub type MouseSystem = key::mouse::System<Ref>;
180
181/// Type aliases for convenience.
182pub type StickyRef = key::sticky::Ref;
183/// Type aliases for convenience.
184pub type StickyKey = key::sticky::Key;
185/// Type aliases for convenience.
186pub type StickyConfig = key::sticky::Config;
187/// Type aliases for convenience.
188pub type StickyContext = key::sticky::Context;
189/// Type aliases for convenience.
190pub type StickyEvent = key::sticky::Event;
191/// Type aliases for convenience.
192pub type StickyPendingKeyState = key::sticky::PendingKeyState;
193/// Type aliases for convenience.
194pub type StickyKeyState = key::sticky::KeyState;
195/// Type aliases for convenience.
196pub type StickySystem<D> = key::sticky::System<Ref, D>;
197
198/// Type aliases for convenience.
199pub type TapDanceRef = key::tap_dance::Ref;
200/// Type aliases for convenience.
201pub type TapDanceKey = key::tap_dance::Key<Ref, TAP_DANCE_MAX_DEF_COUNT>;
202/// Type aliases for convenience.
203pub type TapDanceConfig = key::tap_dance::Config;
204/// Type aliases for convenience.
205pub type TapDanceContext = key::tap_dance::Context;
206/// Type aliases for convenience.
207pub type TapDanceEvent = key::tap_dance::Event;
208/// Type aliases for convenience.
209pub type TapDancePendingKeyState = key::tap_dance::PendingKeyState;
210/// Type aliases for convenience.
211pub type TapDanceKeyState = key::tap_dance::KeyState;
212/// Type aliases for convenience.
213pub type TapDanceSystem<D> = key::tap_dance::System<Ref, D, TAP_DANCE_MAX_DEF_COUNT>;
214
215/// Type aliases for convenience.
216pub type TapHoldRef = key::tap_hold::Ref;
217/// Type aliases for convenience.
218pub type TapHoldKey = key::tap_hold::Key<Ref>;
219/// Type aliases for convenience.
220pub type TapHoldConfig = key::tap_hold::Config;
221/// Type aliases for convenience.
222pub type TapHoldContext = key::tap_hold::Context;
223/// Type aliases for convenience.
224pub type TapHoldEvent = key::tap_hold::Event;
225/// Type aliases for convenience.
226pub type TapHoldPendingKeyState = key::tap_hold::PendingKeyState;
227/// Type aliases for convenience.
228pub type TapHoldKeyState = key::tap_hold::KeyState;
229/// Type aliases for convenience.
230pub type TapHoldSystem<D> = key::tap_hold::System<Ref, D>;
231
232/// Aggregate enum for key references.
233#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
234pub enum Ref {
235    /// [key::automation::Ref] variant.
236    Automation(AutomationRef),
237    /// [key::callback::Ref] variant.
238    Callback(CallbackRef),
239    /// [key::caps_word::Ref] variant.
240    CapsWord(CapsWordRef),
241    /// [key::chorded::Ref] variant.
242    Chorded(ChordedRef),
243    /// [key::consumer::Ref] variant.
244    Consumer(ConsumerRef),
245    /// [key::custom::Ref] variant.
246    Custom(CustomRef),
247    /// [key::keyboard::Ref] variant.
248    Keyboard(KeyboardRef),
249    /// [key::layered::Ref] variant.
250    Layered(LayeredRef),
251    /// [key::mouse::Ref] variant.
252    Mouse(MouseRef),
253    /// [key::sticky::Ref] variant.
254    Sticky(StickyRef),
255    /// [key::tap_dance::Ref] variant.
256    TapDance(TapDanceRef),
257    /// [key::tap_hold::Ref] variant.
258    TapHold(TapHoldRef),
259}
260
261#[cfg(feature = "std")]
262impl Default for Ref {
263    fn default() -> Self {
264        Ref::Keyboard(key::keyboard::Ref::KeyCode(0))
265    }
266}
267
268/// Aggregate config.
269#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
270pub struct Config {
271    /// The automation configuration.
272    #[serde(default)]
273    pub automation: AutomationConfig,
274    /// The chorded configuration.
275    #[serde(default)]
276    pub chorded: key::chorded::Config<CHORDED_MAX_CHORDS, CHORDED_MAX_CHORD_SIZE>,
277    /// The sticky modifier configuration
278    #[serde(default)]
279    pub sticky: StickyConfig,
280    /// The tap dance configuration.
281    #[serde(default)]
282    pub tap_dance: TapDanceConfig,
283    /// The tap hold configuration.
284    #[serde(default)]
285    pub tap_hold: TapHoldConfig,
286}
287
288impl Config {
289    /// Constructs a new [Config] with default values.
290    pub const fn new() -> Self {
291        Config {
292            automation: key::automation::Config::new(),
293            chorded: key::chorded::Config::new(),
294            sticky: key::sticky::Config::new(),
295            tap_dance: key::tap_dance::Config::new(),
296            tap_hold: key::tap_hold::Config::new(),
297        }
298    }
299}
300
301/// An aggregate context for [key::Context]s.
302#[derive(Debug, Clone, Copy)]
303pub struct Context {
304    keymap_context: keymap::KeymapContext,
305    automation: AutomationContext,
306    callback: CallbackContext,
307    caps_word: CapsWordContext,
308    chorded: ChordedContext,
309    consumer: ConsumerContext,
310    custom: CustomContext,
311    keyboard: KeyboardContext,
312    layered: LayeredContext,
313    mouse: MouseContext,
314    sticky: StickyContext,
315    tap_dance: TapDanceContext,
316    tap_hold: TapHoldContext,
317}
318
319impl Context {
320    /// Constructs a [Context] from the given [Config].
321    pub const fn from_config(config: Config) -> Self {
322        Self {
323            keymap_context: keymap::KeymapContext::new(),
324            automation: key::automation::Context::from_config(config.automation),
325            callback: key::callback::Context,
326            caps_word: key::caps_word::Context::new(),
327            chorded: key::chorded::Context::from_config(config.chorded),
328            consumer: key::consumer::Context,
329            custom: key::custom::Context,
330            keyboard: key::keyboard::Context,
331            layered: key::layered::Context::new(),
332            mouse: key::mouse::Context,
333            sticky: key::sticky::Context::from_config(config.sticky),
334            tap_dance: key::tap_dance::Context::from_config(config.tap_dance),
335            tap_hold: key::tap_hold::Context::from_config(config.tap_hold),
336        }
337    }
338}
339
340impl Default for Context {
341    /// Returns the default context.
342    fn default() -> Self {
343        Self::from_config(Config::new())
344    }
345}
346
347impl key::Context for Context {
348    type Event = Event;
349    fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
350        let mut pke = key::KeyEvents::no_events();
351
352        if let Ok(e) = event.try_into_key_event() {
353            pke.extend(self.automation.handle_event(e).into_events());
354        }
355
356        if let Ok(e) = event.try_into_key_event() {
357            pke.extend(self.caps_word.handle_event(e).into_events());
358        }
359
360        if let Ok(e) = event.try_into_key_event() {
361            pke.extend(self.chorded.handle_event(e).into_events());
362        }
363
364        if let Ok(e) = event.try_into_key_event() {
365            pke.extend(self.layered.handle_event(e).into_events());
366        }
367
368        if let Ok(e) = event.try_into_key_event() {
369            pke.extend(self.sticky.handle_event(e).into_events());
370        }
371
372        pke
373    }
374}
375
376impl keymap::SetKeymapContext for Context {
377    fn set_keymap_context(&mut self, context: keymap::KeymapContext) {
378        self.keymap_context = context;
379
380        self.chorded.update_keymap_context(&context);
381        self.tap_hold.update_keymap_context(&context);
382    }
383}
384
385/// Sum type aggregating the [key::Event] types.
386#[derive(Debug, Clone, Copy, PartialEq)]
387pub enum Event {
388    /// An automation event.
389    Automation(AutomationEvent),
390    /// A callback event.
391    Callback(CallbackEvent),
392    /// A caps word event.
393    CapsWord(CapsWordEvent),
394    /// A chorded event.
395    Chorded(ChordedEvent),
396    /// A consumer event.
397    Consumer(ConsumerEvent),
398    /// A custom event.
399    Custom(CustomEvent),
400    /// A keyboard event.
401    Keyboard(KeyboardEvent),
402    /// A layer modification event.
403    Layered(LayeredEvent),
404    /// A mouse event.
405    Mouse(MouseEvent),
406    /// A sticky modifier event.
407    Sticky(StickyEvent),
408    /// A tap-dance event.
409    TapDance(TapDanceEvent),
410    /// A tap-hold event.
411    TapHold(TapHoldEvent),
412}
413
414impl From<AutomationEvent> for Event {
415    fn from(ev: AutomationEvent) -> Self {
416        Event::Automation(ev)
417    }
418}
419
420impl From<CallbackEvent> for Event {
421    fn from(ev: CallbackEvent) -> Self {
422        Event::Callback(ev)
423    }
424}
425
426impl From<CapsWordEvent> for Event {
427    fn from(ev: CapsWordEvent) -> Self {
428        Event::CapsWord(ev)
429    }
430}
431
432impl From<ChordedEvent> for Event {
433    fn from(ev: ChordedEvent) -> Self {
434        Event::Chorded(ev)
435    }
436}
437
438impl From<ConsumerEvent> for Event {
439    fn from(ev: ConsumerEvent) -> Self {
440        Event::Consumer(ev)
441    }
442}
443
444impl From<CustomEvent> for Event {
445    fn from(ev: CustomEvent) -> Self {
446        Event::Custom(ev)
447    }
448}
449
450impl From<KeyboardEvent> for Event {
451    fn from(ev: KeyboardEvent) -> Self {
452        Event::Keyboard(ev)
453    }
454}
455
456impl From<LayeredEvent> for Event {
457    fn from(ev: LayeredEvent) -> Self {
458        Event::Layered(ev)
459    }
460}
461
462impl From<MouseEvent> for Event {
463    fn from(ev: MouseEvent) -> Self {
464        Event::Mouse(ev)
465    }
466}
467
468impl From<StickyEvent> for Event {
469    fn from(ev: StickyEvent) -> Self {
470        Event::Sticky(ev)
471    }
472}
473
474impl From<TapDanceEvent> for Event {
475    fn from(ev: TapDanceEvent) -> Self {
476        Event::TapDance(ev)
477    }
478}
479
480impl From<TapHoldEvent> for Event {
481    fn from(ev: TapHoldEvent) -> Self {
482        Event::TapHold(ev)
483    }
484}
485
486impl TryFrom<Event> for AutomationEvent {
487    type Error = key::EventError;
488
489    fn try_from(ev: Event) -> Result<Self, Self::Error> {
490        match ev {
491            Event::Automation(ev) => Ok(ev),
492            _ => Err(key::EventError::UnmappableEvent),
493        }
494    }
495}
496
497impl TryFrom<Event> for CapsWordEvent {
498    type Error = key::EventError;
499
500    fn try_from(ev: Event) -> Result<Self, Self::Error> {
501        match ev {
502            Event::CapsWord(ev) => Ok(ev),
503            _ => Err(key::EventError::UnmappableEvent),
504        }
505    }
506}
507
508impl TryFrom<Event> for ChordedEvent {
509    type Error = key::EventError;
510
511    fn try_from(ev: Event) -> Result<Self, Self::Error> {
512        match ev {
513            Event::Chorded(ev) => Ok(ev),
514            _ => Err(key::EventError::UnmappableEvent),
515        }
516    }
517}
518
519impl TryFrom<Event> for ConsumerEvent {
520    type Error = key::EventError;
521
522    fn try_from(ev: Event) -> Result<Self, Self::Error> {
523        match ev {
524            Event::Consumer(ev) => Ok(ev),
525            _ => Err(key::EventError::UnmappableEvent),
526        }
527    }
528}
529
530impl TryFrom<Event> for KeyboardEvent {
531    type Error = key::EventError;
532
533    fn try_from(ev: Event) -> Result<Self, Self::Error> {
534        match ev {
535            Event::Keyboard(ev) => Ok(ev),
536            _ => Err(key::EventError::UnmappableEvent),
537        }
538    }
539}
540
541impl TryFrom<Event> for LayeredEvent {
542    type Error = key::EventError;
543
544    fn try_from(ev: Event) -> Result<Self, Self::Error> {
545        match ev {
546            Event::Layered(ev) => Ok(ev),
547            _ => Err(key::EventError::UnmappableEvent),
548        }
549    }
550}
551
552impl TryFrom<Event> for MouseEvent {
553    type Error = key::EventError;
554
555    fn try_from(ev: Event) -> Result<Self, Self::Error> {
556        match ev {
557            Event::Mouse(ev) => Ok(ev),
558            _ => Err(key::EventError::UnmappableEvent),
559        }
560    }
561}
562
563impl TryFrom<Event> for StickyEvent {
564    type Error = key::EventError;
565
566    fn try_from(ev: Event) -> Result<Self, Self::Error> {
567        match ev {
568            Event::Sticky(ev) => Ok(ev),
569            _ => Err(key::EventError::UnmappableEvent),
570        }
571    }
572}
573
574impl TryFrom<Event> for TapDanceEvent {
575    type Error = key::EventError;
576
577    fn try_from(ev: Event) -> Result<Self, Self::Error> {
578        match ev {
579            Event::TapDance(ev) => Ok(ev),
580            _ => Err(key::EventError::UnmappableEvent),
581        }
582    }
583}
584
585impl TryFrom<Event> for TapHoldEvent {
586    type Error = key::EventError;
587
588    fn try_from(ev: Event) -> Result<Self, Self::Error> {
589        match ev {
590            Event::TapHold(ev) => Ok(ev),
591            _ => Err(key::EventError::UnmappableEvent),
592        }
593    }
594}
595
596/// Aggregate enum for pending key state.
597#[derive(Debug, Clone, PartialEq)]
598#[allow(clippy::large_enum_variant)]
599pub enum PendingKeyState {
600    /// Pending key state for [key::automation::PendingKeyState].
601    Automation(AutomationPendingKeyState),
602    /// Pending key state for [key::callback::PendingKeyState].
603    Callback(CallbackPendingKeyState),
604    /// Pending key state for [key::caps_word::PendingKeyState].
605    CapsWord(CapsWordPendingKeyState),
606    /// Pending key state for [key::chorded::PendingKeyState].
607    Chorded(ChordedPendingKeyState),
608    /// Pending key state for [key::consumer::PendingKeyState].
609    Consumer(ConsumerPendingKeyState),
610    /// Pending key state for [key::custom::PendingKeyState].
611    Custom(CustomPendingKeyState),
612    /// Pending key state for [key::keyboard::PendingKeyState].
613    Keyboard(KeyboardPendingKeyState),
614    /// Pending key state for [key::layered::PendingKeyState].
615    Layered(LayeredPendingKeyState),
616    /// Pending key state for [key::mouse::PendingKeyState].
617    Mouse(MousePendingKeyState),
618    /// Pending key state for [key::sticky::PendingKeyState].
619    Sticky(StickyPendingKeyState),
620    /// Pending key state for [key::tap_dance::PendingKeyState].
621    TapDance(TapDancePendingKeyState),
622    /// Pending key state for [key::tap_hold::PendingKeyState].
623    TapHold(TapHoldPendingKeyState),
624}
625
626impl From<AutomationPendingKeyState> for PendingKeyState {
627    fn from(pks: AutomationPendingKeyState) -> Self {
628        PendingKeyState::Automation(pks)
629    }
630}
631
632impl From<CallbackPendingKeyState> for PendingKeyState {
633    fn from(pks: CallbackPendingKeyState) -> Self {
634        PendingKeyState::Callback(pks)
635    }
636}
637
638impl From<CapsWordPendingKeyState> for PendingKeyState {
639    fn from(pks: CapsWordPendingKeyState) -> Self {
640        PendingKeyState::CapsWord(pks)
641    }
642}
643
644impl From<ChordedPendingKeyState> for PendingKeyState {
645    fn from(pks: ChordedPendingKeyState) -> Self {
646        PendingKeyState::Chorded(pks)
647    }
648}
649
650impl From<ConsumerPendingKeyState> for PendingKeyState {
651    fn from(pks: ConsumerPendingKeyState) -> Self {
652        PendingKeyState::Consumer(pks)
653    }
654}
655
656impl From<CustomPendingKeyState> for PendingKeyState {
657    fn from(pks: CustomPendingKeyState) -> Self {
658        PendingKeyState::Custom(pks)
659    }
660}
661
662impl From<KeyboardPendingKeyState> for PendingKeyState {
663    fn from(pks: KeyboardPendingKeyState) -> Self {
664        PendingKeyState::Keyboard(pks)
665    }
666}
667
668impl From<LayeredPendingKeyState> for PendingKeyState {
669    fn from(pks: LayeredPendingKeyState) -> Self {
670        PendingKeyState::Layered(pks)
671    }
672}
673
674impl From<MousePendingKeyState> for PendingKeyState {
675    fn from(pks: MousePendingKeyState) -> Self {
676        PendingKeyState::Mouse(pks)
677    }
678}
679
680impl From<StickyPendingKeyState> for PendingKeyState {
681    fn from(pks: StickyPendingKeyState) -> Self {
682        PendingKeyState::Sticky(pks)
683    }
684}
685
686impl From<TapDancePendingKeyState> for PendingKeyState {
687    fn from(pks: TapDancePendingKeyState) -> Self {
688        PendingKeyState::TapDance(pks)
689    }
690}
691
692impl From<TapHoldPendingKeyState> for PendingKeyState {
693    fn from(pks: TapHoldPendingKeyState) -> Self {
694        PendingKeyState::TapHold(pks)
695    }
696}
697
698impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut ChordedPendingKeyState {
699    type Error = ();
700
701    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
702        match pks {
703            PendingKeyState::Chorded(pks) => Ok(pks),
704            _ => Err(()),
705        }
706    }
707}
708
709impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut TapDancePendingKeyState {
710    type Error = ();
711
712    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
713        match pks {
714            PendingKeyState::TapDance(pks) => Ok(pks),
715            _ => Err(()),
716        }
717    }
718}
719
720impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut TapHoldPendingKeyState {
721    type Error = ();
722
723    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
724        match pks {
725            PendingKeyState::TapHold(pks) => Ok(pks),
726            _ => Err(()),
727        }
728    }
729}
730
731/// Aggregate enum for key state. (i.e. pressed key data).
732#[derive(Debug, Clone, Copy, PartialEq)]
733pub enum KeyState {
734    /// No-op key state.
735    NoOp, // e.g. chorded::AuxiliaryKey's state is a no-op
736    /// Key state for [key::automation::KeyState].
737    Automation(AutomationKeyState),
738    /// Key state for [key::callback::KeyState].
739    Callback(CallbackKeyState),
740    /// Key state for [key::caps_word::KeyState].
741    CapsWord(CapsWordKeyState),
742    /// Key state for [key::chorded::KeyState].
743    Chorded(ChordedKeyState),
744    /// Key state for [key::consumer::KeyState].
745    Consumer(ConsumerKeyState),
746    /// Key state for [key::custom::KeyState].
747    Custom(CustomKeyState),
748    /// Key state for [key::keyboard::KeyState].
749    Keyboard(KeyboardKeyState),
750    /// Key state for [key::layered::ModifierKeyState].
751    LayerModifier(LayeredKeyState),
752    /// Key state for [key::mouse::KeyState].
753    Mouse(MouseKeyState),
754    /// Key state for [key::sticky::KeyState].
755    Sticky(StickyKeyState),
756    /// Key state for [key::tap_dance::KeyState].
757    TapDance(TapDanceKeyState),
758    /// Key state for [key::tap_hold::KeyState].
759    TapHold(TapHoldKeyState),
760}
761
762impl From<key::NoOpKeyState> for KeyState {
763    fn from(_: key::NoOpKeyState) -> Self {
764        KeyState::NoOp
765    }
766}
767
768impl From<AutomationKeyState> for KeyState {
769    fn from(ks: AutomationKeyState) -> Self {
770        KeyState::Automation(ks)
771    }
772}
773
774impl From<CallbackKeyState> for KeyState {
775    fn from(ks: CallbackKeyState) -> Self {
776        KeyState::Callback(ks)
777    }
778}
779
780impl From<CapsWordKeyState> for KeyState {
781    fn from(ks: CapsWordKeyState) -> Self {
782        KeyState::CapsWord(ks)
783    }
784}
785
786impl From<ChordedKeyState> for KeyState {
787    fn from(ks: ChordedKeyState) -> Self {
788        KeyState::Chorded(ks)
789    }
790}
791
792impl From<ConsumerKeyState> for KeyState {
793    fn from(ks: ConsumerKeyState) -> Self {
794        KeyState::Consumer(ks)
795    }
796}
797
798impl From<CustomKeyState> for KeyState {
799    fn from(ks: CustomKeyState) -> Self {
800        KeyState::Custom(ks)
801    }
802}
803
804impl From<KeyboardKeyState> for KeyState {
805    fn from(ks: KeyboardKeyState) -> Self {
806        KeyState::Keyboard(ks)
807    }
808}
809
810impl From<LayeredKeyState> for KeyState {
811    fn from(ks: LayeredKeyState) -> Self {
812        KeyState::LayerModifier(ks)
813    }
814}
815
816impl From<MouseKeyState> for KeyState {
817    fn from(ks: MouseKeyState) -> Self {
818        KeyState::Mouse(ks)
819    }
820}
821
822impl From<TapDanceKeyState> for KeyState {
823    fn from(ks: TapDanceKeyState) -> Self {
824        KeyState::TapDance(ks)
825    }
826}
827
828impl From<TapHoldKeyState> for KeyState {
829    fn from(ks: TapHoldKeyState) -> Self {
830        KeyState::TapHold(ks)
831    }
832}
833
834impl From<StickyKeyState> for KeyState {
835    fn from(ks: StickyKeyState) -> Self {
836        KeyState::Sticky(ks)
837    }
838}
839
840/// Convenience trait for the data storage types.
841pub trait Keys {
842    /// Type used by [key::automation::System].
843    type Automation: Debug + Index<usize, Output = AutomationKey>;
844    /// Type used by [key::callback::System].
845    type Callback: Debug + Index<usize, Output = CallbackKey>;
846    /// Type used by [key::chorded::System].
847    type Chorded: Debug + Index<usize, Output = ChordedKey>;
848    /// Type used by [key::chorded::System].
849    type ChordedAuxiliary: Debug + Index<usize, Output = ChordedAuxiliaryKey>;
850    /// Type used by [key::keyboard::System].
851    type Keyboard: Debug + Index<usize, Output = KeyboardKey>;
852    /// Type used by [key::layered::System].
853    type LayerModifiers: Debug + Index<usize, Output = LayeredModifierKey>;
854    /// Type used by [key::layered::System].
855    type Layered: Debug + Index<usize, Output = LayeredKey>;
856    /// Type used by [key::sticky::System].
857    type Sticky: Debug + Index<usize, Output = StickyKey>;
858    /// Type used by [key::tap_dance::System].
859    type TapDance: Debug + Index<usize, Output = TapDanceKey>;
860    /// Type used by [key::tap_hold::System].
861    type TapHold: Debug + Index<usize, Output = TapHoldKey>;
862}
863
864/// Array-based data implementations.
865#[derive(Debug)]
866pub struct KeyArrays<
867    const AUTOMATION: usize,
868    const CALLBACK: usize,
869    const CHORDED: usize,
870    const CHORDED_AUXILIARY: usize,
871    const KEYBOARD: usize,
872    const LAYERED: usize,
873    const LAYER_MODIFIERS: usize,
874    const STICKY: usize,
875    const TAP_DANCE: usize,
876    const TAP_HOLD: usize,
877>;
878
879impl<
880        const AUTOMATION: usize,
881        const CALLBACK: usize,
882        const CHORDED: usize,
883        const CHORDED_AUXILIARY: usize,
884        const KEYBOARD: usize,
885        const LAYERED: usize,
886        const LAYER_MODIFIERS: usize,
887        const STICKY: usize,
888        const TAP_DANCE: usize,
889        const TAP_HOLD: usize,
890    > Keys
891    for KeyArrays<
892        AUTOMATION,
893        CALLBACK,
894        CHORDED,
895        CHORDED_AUXILIARY,
896        KEYBOARD,
897        LAYERED,
898        LAYER_MODIFIERS,
899        STICKY,
900        TAP_DANCE,
901        TAP_HOLD,
902    >
903{
904    type Automation = [AutomationKey; AUTOMATION];
905    type Callback = [CallbackKey; CALLBACK];
906    type Chorded = [ChordedKey; CHORDED];
907    type ChordedAuxiliary = [ChordedAuxiliaryKey; CHORDED_AUXILIARY];
908    type Keyboard = [KeyboardKey; KEYBOARD];
909    type LayerModifiers = [LayeredModifierKey; LAYER_MODIFIERS];
910    type Layered = [LayeredKey; LAYERED];
911    type Sticky = [StickyKey; STICKY];
912    type TapDance = [TapDanceKey; TAP_DANCE];
913    type TapHold = [TapHoldKey; TAP_HOLD];
914}
915
916/// Vec-based data implementations.
917#[derive(Debug)]
918#[cfg(feature = "std")]
919pub struct KeyVecs;
920
921#[cfg(feature = "std")]
922impl Keys for KeyVecs {
923    type Automation = Vec<AutomationKey>;
924    type Callback = Vec<CallbackKey>;
925    type Chorded = Vec<ChordedKey>;
926    type ChordedAuxiliary = Vec<ChordedAuxiliaryKey>;
927    type Keyboard = Vec<KeyboardKey>;
928    type LayerModifiers = Vec<LayeredModifierKey>;
929    type Layered = Vec<LayeredKey>;
930    type Sticky = Vec<StickyKey>;
931    type TapDance = Vec<TapDanceKey>;
932    type TapHold = Vec<TapHoldKey>;
933}
934
935/// Aggregate [key::System] implementation.
936#[derive(Debug, Clone, Copy, PartialEq)]
937pub struct System<D: Keys> {
938    automation: AutomationSystem<D::Automation>,
939    callback: CallbackSystem<D::Callback>,
940    caps_word: CapsWordSystem,
941    consumer: ConsumerSystem,
942    chorded: ChordedSystem<D::Chorded, D::ChordedAuxiliary>,
943    custom: CustomSystem,
944    keyboard: KeyboardSystem<D::Keyboard>,
945    layered: LayeredSystem<D::LayerModifiers, D::Layered>,
946    mouse: MouseSystem,
947    sticky: StickySystem<D::Sticky>,
948    tap_dance: TapDanceSystem<D::TapDance>,
949    tap_hold: TapHoldSystem<D::TapHold>,
950    marker: PhantomData<D>,
951}
952
953impl<
954        const AUTOMATION: usize,
955        const CALLBACK: usize,
956        const CHORDED: usize,
957        const CHORDED_AUXILIARY: usize,
958        const KEYBOARD: usize,
959        const LAYERED: usize,
960        const LAYER_MODIFIERS: usize,
961        const STICKY: usize,
962        const TAP_DANCE: usize,
963        const TAP_HOLD: usize,
964    >
965    System<
966        KeyArrays<
967            AUTOMATION,
968            CALLBACK,
969            CHORDED,
970            CHORDED_AUXILIARY,
971            KEYBOARD,
972            LAYERED,
973            LAYER_MODIFIERS,
974            STICKY,
975            TAP_DANCE,
976            TAP_HOLD,
977        >,
978    >
979{
980    /// Constructs a new [System].
981    pub const fn array_based(
982        automation: AutomationSystem<[AutomationKey; AUTOMATION]>,
983        callback: CallbackSystem<[CallbackKey; CALLBACK]>,
984        chorded: ChordedSystem<[ChordedKey; CHORDED], [ChordedAuxiliaryKey; CHORDED_AUXILIARY]>,
985        keyboard: KeyboardSystem<[KeyboardKey; KEYBOARD]>,
986        layered: LayeredSystem<[LayeredModifierKey; LAYER_MODIFIERS], [LayeredKey; LAYERED]>,
987        sticky: StickySystem<[StickyKey; STICKY]>,
988        tap_dance: TapDanceSystem<[TapDanceKey; TAP_DANCE]>,
989        tap_hold: TapHoldSystem<[TapHoldKey; TAP_HOLD]>,
990    ) -> Self {
991        System {
992            automation,
993            callback,
994            caps_word: key::caps_word::System::new(),
995            consumer: key::consumer::System::new(),
996            chorded,
997            custom: key::custom::System::new(),
998            keyboard,
999            layered,
1000            mouse: key::mouse::System::new(),
1001            sticky,
1002            tap_dance,
1003            tap_hold,
1004            marker: PhantomData,
1005        }
1006    }
1007}
1008
1009#[cfg(feature = "std")]
1010impl System<KeyVecs> {
1011    /// Constructs a new [System].
1012    pub const fn vec_based(
1013        automation: AutomationSystem<Vec<AutomationKey>>,
1014        callback: CallbackSystem<Vec<CallbackKey>>,
1015        chorded: ChordedSystem<Vec<ChordedKey>, Vec<ChordedAuxiliaryKey>>,
1016        keyboard: KeyboardSystem<Vec<KeyboardKey>>,
1017        layered: LayeredSystem<Vec<LayeredModifierKey>, Vec<LayeredKey>>,
1018        sticky: StickySystem<Vec<StickyKey>>,
1019        tap_dance: TapDanceSystem<Vec<TapDanceKey>>,
1020        tap_hold: TapHoldSystem<Vec<TapHoldKey>>,
1021    ) -> Self {
1022        System {
1023            automation,
1024            callback,
1025            caps_word: key::caps_word::System::new(),
1026            consumer: key::consumer::System::new(),
1027            chorded,
1028            custom: key::custom::System::new(),
1029            keyboard,
1030            layered,
1031            mouse: key::mouse::System::new(),
1032            sticky,
1033            tap_dance,
1034            tap_hold,
1035            marker: PhantomData,
1036        }
1037    }
1038}
1039
1040impl<K: Debug + Keys> key::System<Ref> for System<K> {
1041    type Ref = Ref;
1042    type Context = Context;
1043    type Event = Event;
1044    type PendingKeyState = PendingKeyState;
1045    type KeyState = KeyState;
1046
1047    fn new_pressed_key(
1048        &self,
1049        keymap_index: u16,
1050        context: &Self::Context,
1051        key_ref: Ref,
1052    ) -> (
1053        key::PressedKeyResult<Ref, Self::PendingKeyState, Self::KeyState>,
1054        key::KeyEvents<Self::Event>,
1055    ) {
1056        match key_ref {
1057            Ref::Automation(key_ref) => {
1058                let (pkr, pke) =
1059                    self.automation
1060                        .new_pressed_key(keymap_index, &context.automation, key_ref);
1061                (pkr.into_result(), pke.into_events())
1062            }
1063            Ref::Callback(key_ref) => {
1064                let (pkr, pke) =
1065                    self.callback
1066                        .new_pressed_key(keymap_index, &context.callback, key_ref);
1067                (pkr.into_result(), pke.into_events())
1068            }
1069            Ref::CapsWord(key_ref) => {
1070                let (pkr, pke) =
1071                    self.caps_word
1072                        .new_pressed_key(keymap_index, &context.caps_word, key_ref);
1073                (pkr.into_result(), pke.into_events())
1074            }
1075            Ref::Chorded(key_ref) => {
1076                let (pkr, pke) =
1077                    self.chorded
1078                        .new_pressed_key(keymap_index, &context.chorded, key_ref);
1079                (pkr.into_result(), pke.into_events())
1080            }
1081            Ref::Consumer(key_ref) => {
1082                let (pkr, pke) =
1083                    self.consumer
1084                        .new_pressed_key(keymap_index, &context.consumer, key_ref);
1085                (pkr.into_result(), pke.into_events())
1086            }
1087            Ref::Custom(key_ref) => {
1088                let (pkr, pke) =
1089                    self.custom
1090                        .new_pressed_key(keymap_index, &context.custom, key_ref);
1091                (pkr.into_result(), pke.into_events())
1092            }
1093            Ref::Keyboard(key_ref) => {
1094                let (pkr, pke) =
1095                    self.keyboard
1096                        .new_pressed_key(keymap_index, &context.keyboard, key_ref);
1097                (pkr.into_result(), pke.into_events())
1098            }
1099            Ref::Layered(key_ref) => {
1100                let (pkr, pke) =
1101                    self.layered
1102                        .new_pressed_key(keymap_index, &context.layered, key_ref);
1103                (pkr.into_result(), pke.into_events())
1104            }
1105            Ref::Mouse(key_ref) => {
1106                let (pkr, pke) = self
1107                    .mouse
1108                    .new_pressed_key(keymap_index, &context.mouse, key_ref);
1109                (pkr.into_result(), pke.into_events())
1110            }
1111            Ref::Sticky(key_ref) => {
1112                let (pkr, pke) =
1113                    self.sticky
1114                        .new_pressed_key(keymap_index, &context.sticky, key_ref);
1115                (pkr.into_result(), pke.into_events())
1116            }
1117            Ref::TapDance(key_ref) => {
1118                let (pkr, pke) =
1119                    self.tap_dance
1120                        .new_pressed_key(keymap_index, &context.tap_dance, key_ref);
1121                (pkr.into_result(), pke.into_events())
1122            }
1123            Ref::TapHold(key_ref) => {
1124                let (pkr, pke) =
1125                    self.tap_hold
1126                        .new_pressed_key(keymap_index, &context.tap_hold, key_ref);
1127                (pkr.into_result(), pke.into_events())
1128            }
1129        }
1130    }
1131
1132    fn update_pending_state(
1133        &self,
1134        pending_state: &mut Self::PendingKeyState,
1135        keymap_index: u16,
1136        context: &Self::Context,
1137        key_ref: Ref,
1138        event: key::Event<Self::Event>,
1139    ) -> (Option<key::NewPressedKey<Ref>>, key::KeyEvents<Self::Event>) {
1140        match (key_ref, pending_state) {
1141            (Ref::Chorded(key_ref), PendingKeyState::Chorded(pending_state)) => {
1142                if let Ok(event) = event.try_into_key_event() {
1143                    let (maybe_npk, pke) = self.chorded.update_pending_state(
1144                        pending_state,
1145                        keymap_index,
1146                        &context.chorded,
1147                        key_ref,
1148                        event,
1149                    );
1150                    (maybe_npk, pke.into_events())
1151                } else {
1152                    (None, key::KeyEvents::no_events())
1153                }
1154            }
1155            (Ref::TapDance(key_ref), PendingKeyState::TapDance(pending_state)) => {
1156                if let Ok(event) = event.try_into_key_event() {
1157                    let (maybe_npk, pke) = self.tap_dance.update_pending_state(
1158                        pending_state,
1159                        keymap_index,
1160                        &context.tap_dance,
1161                        key_ref,
1162                        event,
1163                    );
1164                    (maybe_npk, pke.into_events())
1165                } else {
1166                    (None, key::KeyEvents::no_events())
1167                }
1168            }
1169            (Ref::TapHold(key_ref), PendingKeyState::TapHold(pending_state)) => {
1170                if let Ok(event) = event.try_into_key_event() {
1171                    let (maybe_npk, pke) = self.tap_hold.update_pending_state(
1172                        pending_state,
1173                        keymap_index,
1174                        &context.tap_hold,
1175                        key_ref,
1176                        event,
1177                    );
1178                    (maybe_npk, pke.into_events())
1179                } else {
1180                    (None, key::KeyEvents::no_events())
1181                }
1182            }
1183            (_, _) => panic!("Mismatched key_ref and key_state variants"),
1184        }
1185    }
1186
1187    fn update_state(
1188        &self,
1189        key_state: &mut Self::KeyState,
1190        key_ref: &Self::Ref,
1191        context: &Self::Context,
1192        keymap_index: u16,
1193        event: key::Event<Self::Event>,
1194    ) -> key::KeyEvents<Self::Event> {
1195        match (key_ref, key_state) {
1196            (Ref::Automation(key_ref), KeyState::Automation(key_state)) => {
1197                if let Ok(event) = event.try_into_key_event() {
1198                    let pke = self.automation.update_state(
1199                        key_state,
1200                        key_ref,
1201                        &context.automation,
1202                        keymap_index,
1203                        event,
1204                    );
1205                    pke.into_events()
1206                } else {
1207                    key::KeyEvents::no_events()
1208                }
1209            }
1210            (Ref::Consumer(key_ref), KeyState::Consumer(key_state)) => {
1211                if let Ok(event) = event.try_into_key_event() {
1212                    let pke = self.consumer.update_state(
1213                        key_state,
1214                        key_ref,
1215                        &context.consumer,
1216                        keymap_index,
1217                        event,
1218                    );
1219                    pke.into_events()
1220                } else {
1221                    key::KeyEvents::no_events()
1222                }
1223            }
1224            (Ref::Keyboard(key_ref), KeyState::Keyboard(key_state)) => {
1225                if let Ok(event) = event.try_into_key_event() {
1226                    let pke = self.keyboard.update_state(
1227                        key_state,
1228                        key_ref,
1229                        &context.keyboard,
1230                        keymap_index,
1231                        event,
1232                    );
1233                    pke.into_events()
1234                } else {
1235                    key::KeyEvents::no_events()
1236                }
1237            }
1238            (Ref::Layered(key_ref), KeyState::LayerModifier(key_state)) => {
1239                if let Ok(event) = event.try_into_key_event() {
1240                    let pke = self.layered.update_state(
1241                        key_state,
1242                        key_ref,
1243                        &context.layered,
1244                        keymap_index,
1245                        event,
1246                    );
1247                    pke.into_events()
1248                } else {
1249                    key::KeyEvents::no_events()
1250                }
1251            }
1252            (Ref::Sticky(key_ref), KeyState::Sticky(key_state)) => {
1253                if let Ok(event) = event.try_into_key_event() {
1254                    let pke = self.sticky.update_state(
1255                        key_state,
1256                        key_ref,
1257                        &context.sticky,
1258                        keymap_index,
1259                        event,
1260                    );
1261                    pke.into_events()
1262                } else {
1263                    key::KeyEvents::no_events()
1264                }
1265            }
1266            (_, _) => key::KeyEvents::no_events(),
1267        }
1268    }
1269
1270    fn key_output(
1271        &self,
1272        key_ref: &Self::Ref,
1273        key_state: &Self::KeyState,
1274    ) -> Option<key::KeyOutput> {
1275        match (key_ref, key_state) {
1276            (Ref::Consumer(r), KeyState::Consumer(ks)) => self.consumer.key_output(r, ks),
1277            (Ref::Custom(r), KeyState::Custom(ks)) => self.custom.key_output(r, ks),
1278            (Ref::Keyboard(r), KeyState::Keyboard(ks)) => self.keyboard.key_output(r, ks),
1279            (Ref::Mouse(r), KeyState::Mouse(ks)) => self.mouse.key_output(r, ks),
1280            (Ref::Sticky(r), KeyState::Sticky(ks)) => self.sticky.key_output(r, ks),
1281            (_, _) => None,
1282        }
1283    }
1284}
1285
1286#[cfg(test)]
1287mod tests {
1288    use super::*;
1289
1290    #[test]
1291    fn test_sizeof_ref() {
1292        assert_eq!(3, core::mem::size_of::<Ref>());
1293    }
1294
1295    #[test]
1296    fn test_sizeof_event() {
1297        assert_eq!(12, core::mem::size_of::<Event>());
1298    }
1299}