Skip to main content

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 Default for Config {
289    fn default() -> Self {
290        Self::new()
291    }
292}
293
294impl Config {
295    /// Constructs a new [Config] with default values.
296    pub const fn new() -> Self {
297        Config {
298            automation: key::automation::Config::new(),
299            chorded: key::chorded::Config::new(),
300            sticky: key::sticky::Config::new(),
301            tap_dance: key::tap_dance::Config::new(),
302            tap_hold: key::tap_hold::Config::new(),
303        }
304    }
305}
306
307/// An aggregate context for [key::Context]s.
308#[derive(Debug, Clone, Copy)]
309pub struct Context {
310    keymap_context: keymap::KeymapContext,
311    automation: AutomationContext,
312    callback: CallbackContext,
313    caps_word: CapsWordContext,
314    chorded: ChordedContext,
315    consumer: ConsumerContext,
316    custom: CustomContext,
317    keyboard: KeyboardContext,
318    layered: LayeredContext,
319    mouse: MouseContext,
320    sticky: StickyContext,
321    tap_dance: TapDanceContext,
322    tap_hold: TapHoldContext,
323}
324
325impl Context {
326    /// Constructs a [Context] from the given [Config].
327    pub const fn from_config(config: Config) -> Self {
328        Self {
329            keymap_context: keymap::KeymapContext::new(),
330            automation: key::automation::Context::from_config(config.automation),
331            callback: key::callback::Context,
332            caps_word: key::caps_word::Context::new(),
333            chorded: key::chorded::Context::from_config(config.chorded),
334            consumer: key::consumer::Context,
335            custom: key::custom::Context,
336            keyboard: key::keyboard::Context,
337            layered: key::layered::Context::new(),
338            mouse: key::mouse::Context,
339            sticky: key::sticky::Context::from_config(config.sticky),
340            tap_dance: key::tap_dance::Context::from_config(config.tap_dance),
341            tap_hold: key::tap_hold::Context::from_config(config.tap_hold),
342        }
343    }
344}
345
346impl Default for Context {
347    /// Returns the default context.
348    fn default() -> Self {
349        Self::from_config(Config::new())
350    }
351}
352
353impl key::Context for Context {
354    type Event = Event;
355    fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
356        let mut pke = key::KeyEvents::no_events();
357
358        if let Ok(e) = event.try_into_key_event() {
359            pke.extend(self.automation.handle_event(e).into_events());
360        }
361
362        if let Ok(e) = event.try_into_key_event() {
363            pke.extend(self.caps_word.handle_event(e).into_events());
364        }
365
366        if let Ok(e) = event.try_into_key_event() {
367            pke.extend(self.chorded.handle_event(e).into_events());
368        }
369
370        if let Ok(e) = event.try_into_key_event() {
371            pke.extend(self.layered.handle_event(e).into_events());
372        }
373
374        if let Ok(e) = event.try_into_key_event() {
375            pke.extend(self.sticky.handle_event(e).into_events());
376        }
377
378        pke
379    }
380}
381
382impl keymap::SetKeymapContext for Context {
383    fn set_keymap_context(&mut self, context: keymap::KeymapContext) {
384        self.keymap_context = context;
385
386        self.chorded.update_keymap_context(&context);
387        self.tap_hold.update_keymap_context(&context);
388    }
389}
390
391/// Sum type aggregating the [key::Event] types.
392#[derive(Debug, Clone, Copy, PartialEq)]
393pub enum Event {
394    /// An automation event.
395    Automation(AutomationEvent),
396    /// A callback event.
397    Callback(CallbackEvent),
398    /// A caps word event.
399    CapsWord(CapsWordEvent),
400    /// A chorded event.
401    Chorded(ChordedEvent),
402    /// A consumer event.
403    Consumer(ConsumerEvent),
404    /// A custom event.
405    Custom(CustomEvent),
406    /// A keyboard event.
407    Keyboard(KeyboardEvent),
408    /// A layer modification event.
409    Layered(LayeredEvent),
410    /// A mouse event.
411    Mouse(MouseEvent),
412    /// A sticky modifier event.
413    Sticky(StickyEvent),
414    /// A tap-dance event.
415    TapDance(TapDanceEvent),
416    /// A tap-hold event.
417    TapHold(TapHoldEvent),
418}
419
420impl From<AutomationEvent> for Event {
421    fn from(ev: AutomationEvent) -> Self {
422        Event::Automation(ev)
423    }
424}
425
426impl From<CallbackEvent> for Event {
427    fn from(ev: CallbackEvent) -> Self {
428        Event::Callback(ev)
429    }
430}
431
432impl From<CapsWordEvent> for Event {
433    fn from(ev: CapsWordEvent) -> Self {
434        Event::CapsWord(ev)
435    }
436}
437
438impl From<ChordedEvent> for Event {
439    fn from(ev: ChordedEvent) -> Self {
440        Event::Chorded(ev)
441    }
442}
443
444impl From<ConsumerEvent> for Event {
445    fn from(ev: ConsumerEvent) -> Self {
446        Event::Consumer(ev)
447    }
448}
449
450impl From<CustomEvent> for Event {
451    fn from(ev: CustomEvent) -> Self {
452        Event::Custom(ev)
453    }
454}
455
456impl From<KeyboardEvent> for Event {
457    fn from(ev: KeyboardEvent) -> Self {
458        Event::Keyboard(ev)
459    }
460}
461
462impl From<LayeredEvent> for Event {
463    fn from(ev: LayeredEvent) -> Self {
464        Event::Layered(ev)
465    }
466}
467
468impl From<MouseEvent> for Event {
469    fn from(ev: MouseEvent) -> Self {
470        Event::Mouse(ev)
471    }
472}
473
474impl From<StickyEvent> for Event {
475    fn from(ev: StickyEvent) -> Self {
476        Event::Sticky(ev)
477    }
478}
479
480impl From<TapDanceEvent> for Event {
481    fn from(ev: TapDanceEvent) -> Self {
482        Event::TapDance(ev)
483    }
484}
485
486impl From<TapHoldEvent> for Event {
487    fn from(ev: TapHoldEvent) -> Self {
488        Event::TapHold(ev)
489    }
490}
491
492impl TryFrom<Event> for AutomationEvent {
493    type Error = key::EventError;
494
495    fn try_from(ev: Event) -> Result<Self, Self::Error> {
496        match ev {
497            Event::Automation(ev) => Ok(ev),
498            _ => Err(key::EventError::UnmappableEvent),
499        }
500    }
501}
502
503impl TryFrom<Event> for CapsWordEvent {
504    type Error = key::EventError;
505
506    fn try_from(ev: Event) -> Result<Self, Self::Error> {
507        match ev {
508            Event::CapsWord(ev) => Ok(ev),
509            _ => Err(key::EventError::UnmappableEvent),
510        }
511    }
512}
513
514impl TryFrom<Event> for ChordedEvent {
515    type Error = key::EventError;
516
517    fn try_from(ev: Event) -> Result<Self, Self::Error> {
518        match ev {
519            Event::Chorded(ev) => Ok(ev),
520            _ => Err(key::EventError::UnmappableEvent),
521        }
522    }
523}
524
525impl TryFrom<Event> for ConsumerEvent {
526    type Error = key::EventError;
527
528    fn try_from(ev: Event) -> Result<Self, Self::Error> {
529        match ev {
530            Event::Consumer(ev) => Ok(ev),
531            _ => Err(key::EventError::UnmappableEvent),
532        }
533    }
534}
535
536impl TryFrom<Event> for KeyboardEvent {
537    type Error = key::EventError;
538
539    fn try_from(ev: Event) -> Result<Self, Self::Error> {
540        match ev {
541            Event::Keyboard(ev) => Ok(ev),
542            _ => Err(key::EventError::UnmappableEvent),
543        }
544    }
545}
546
547impl TryFrom<Event> for LayeredEvent {
548    type Error = key::EventError;
549
550    fn try_from(ev: Event) -> Result<Self, Self::Error> {
551        match ev {
552            Event::Layered(ev) => Ok(ev),
553            _ => Err(key::EventError::UnmappableEvent),
554        }
555    }
556}
557
558impl TryFrom<Event> for MouseEvent {
559    type Error = key::EventError;
560
561    fn try_from(ev: Event) -> Result<Self, Self::Error> {
562        match ev {
563            Event::Mouse(ev) => Ok(ev),
564            _ => Err(key::EventError::UnmappableEvent),
565        }
566    }
567}
568
569impl TryFrom<Event> for StickyEvent {
570    type Error = key::EventError;
571
572    fn try_from(ev: Event) -> Result<Self, Self::Error> {
573        match ev {
574            Event::Sticky(ev) => Ok(ev),
575            _ => Err(key::EventError::UnmappableEvent),
576        }
577    }
578}
579
580impl TryFrom<Event> for TapDanceEvent {
581    type Error = key::EventError;
582
583    fn try_from(ev: Event) -> Result<Self, Self::Error> {
584        match ev {
585            Event::TapDance(ev) => Ok(ev),
586            _ => Err(key::EventError::UnmappableEvent),
587        }
588    }
589}
590
591impl TryFrom<Event> for TapHoldEvent {
592    type Error = key::EventError;
593
594    fn try_from(ev: Event) -> Result<Self, Self::Error> {
595        match ev {
596            Event::TapHold(ev) => Ok(ev),
597            _ => Err(key::EventError::UnmappableEvent),
598        }
599    }
600}
601
602/// Aggregate enum for pending key state.
603#[derive(Debug, Clone, PartialEq)]
604#[allow(clippy::large_enum_variant)]
605pub enum PendingKeyState {
606    /// Pending key state for [key::automation::PendingKeyState].
607    Automation(AutomationPendingKeyState),
608    /// Pending key state for [key::callback::PendingKeyState].
609    Callback(CallbackPendingKeyState),
610    /// Pending key state for [key::caps_word::PendingKeyState].
611    CapsWord(CapsWordPendingKeyState),
612    /// Pending key state for [key::chorded::PendingKeyState].
613    Chorded(ChordedPendingKeyState),
614    /// Pending key state for [key::consumer::PendingKeyState].
615    Consumer(ConsumerPendingKeyState),
616    /// Pending key state for [key::custom::PendingKeyState].
617    Custom(CustomPendingKeyState),
618    /// Pending key state for [key::keyboard::PendingKeyState].
619    Keyboard(KeyboardPendingKeyState),
620    /// Pending key state for [key::layered::PendingKeyState].
621    Layered(LayeredPendingKeyState),
622    /// Pending key state for [key::mouse::PendingKeyState].
623    Mouse(MousePendingKeyState),
624    /// Pending key state for [key::sticky::PendingKeyState].
625    Sticky(StickyPendingKeyState),
626    /// Pending key state for [key::tap_dance::PendingKeyState].
627    TapDance(TapDancePendingKeyState),
628    /// Pending key state for [key::tap_hold::PendingKeyState].
629    TapHold(TapHoldPendingKeyState),
630}
631
632impl From<AutomationPendingKeyState> for PendingKeyState {
633    fn from(pks: AutomationPendingKeyState) -> Self {
634        PendingKeyState::Automation(pks)
635    }
636}
637
638impl From<CallbackPendingKeyState> for PendingKeyState {
639    fn from(pks: CallbackPendingKeyState) -> Self {
640        PendingKeyState::Callback(pks)
641    }
642}
643
644impl From<CapsWordPendingKeyState> for PendingKeyState {
645    fn from(pks: CapsWordPendingKeyState) -> Self {
646        PendingKeyState::CapsWord(pks)
647    }
648}
649
650impl From<ChordedPendingKeyState> for PendingKeyState {
651    fn from(pks: ChordedPendingKeyState) -> Self {
652        PendingKeyState::Chorded(pks)
653    }
654}
655
656impl From<ConsumerPendingKeyState> for PendingKeyState {
657    fn from(pks: ConsumerPendingKeyState) -> Self {
658        PendingKeyState::Consumer(pks)
659    }
660}
661
662impl From<CustomPendingKeyState> for PendingKeyState {
663    fn from(pks: CustomPendingKeyState) -> Self {
664        PendingKeyState::Custom(pks)
665    }
666}
667
668impl From<KeyboardPendingKeyState> for PendingKeyState {
669    fn from(pks: KeyboardPendingKeyState) -> Self {
670        PendingKeyState::Keyboard(pks)
671    }
672}
673
674impl From<LayeredPendingKeyState> for PendingKeyState {
675    fn from(pks: LayeredPendingKeyState) -> Self {
676        PendingKeyState::Layered(pks)
677    }
678}
679
680impl From<MousePendingKeyState> for PendingKeyState {
681    fn from(pks: MousePendingKeyState) -> Self {
682        PendingKeyState::Mouse(pks)
683    }
684}
685
686impl From<StickyPendingKeyState> for PendingKeyState {
687    fn from(pks: StickyPendingKeyState) -> Self {
688        PendingKeyState::Sticky(pks)
689    }
690}
691
692impl From<TapDancePendingKeyState> for PendingKeyState {
693    fn from(pks: TapDancePendingKeyState) -> Self {
694        PendingKeyState::TapDance(pks)
695    }
696}
697
698impl From<TapHoldPendingKeyState> for PendingKeyState {
699    fn from(pks: TapHoldPendingKeyState) -> Self {
700        PendingKeyState::TapHold(pks)
701    }
702}
703
704impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut ChordedPendingKeyState {
705    type Error = ();
706
707    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
708        match pks {
709            PendingKeyState::Chorded(pks) => Ok(pks),
710            _ => Err(()),
711        }
712    }
713}
714
715impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut TapDancePendingKeyState {
716    type Error = ();
717
718    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
719        match pks {
720            PendingKeyState::TapDance(pks) => Ok(pks),
721            _ => Err(()),
722        }
723    }
724}
725
726impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut TapHoldPendingKeyState {
727    type Error = ();
728
729    fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
730        match pks {
731            PendingKeyState::TapHold(pks) => Ok(pks),
732            _ => Err(()),
733        }
734    }
735}
736
737/// Aggregate enum for key state. (i.e. pressed key data).
738#[derive(Debug, Clone, Copy, PartialEq)]
739pub enum KeyState {
740    /// No-op key state.
741    NoOp, // e.g. chorded::AuxiliaryKey's state is a no-op
742    /// Key state for [key::automation::KeyState].
743    Automation(AutomationKeyState),
744    /// Key state for [key::callback::KeyState].
745    Callback(CallbackKeyState),
746    /// Key state for [key::caps_word::KeyState].
747    CapsWord(CapsWordKeyState),
748    /// Key state for [key::chorded::KeyState].
749    Chorded(ChordedKeyState),
750    /// Key state for [key::consumer::KeyState].
751    Consumer(ConsumerKeyState),
752    /// Key state for [key::custom::KeyState].
753    Custom(CustomKeyState),
754    /// Key state for [key::keyboard::KeyState].
755    Keyboard(KeyboardKeyState),
756    /// Key state for [key::layered::ModifierKeyState].
757    LayerModifier(LayeredKeyState),
758    /// Key state for [key::mouse::KeyState].
759    Mouse(MouseKeyState),
760    /// Key state for [key::sticky::KeyState].
761    Sticky(StickyKeyState),
762    /// Key state for [key::tap_dance::KeyState].
763    TapDance(TapDanceKeyState),
764    /// Key state for [key::tap_hold::KeyState].
765    TapHold(TapHoldKeyState),
766}
767
768impl From<key::NoOpKeyState> for KeyState {
769    fn from(_: key::NoOpKeyState) -> Self {
770        KeyState::NoOp
771    }
772}
773
774impl From<AutomationKeyState> for KeyState {
775    fn from(ks: AutomationKeyState) -> Self {
776        KeyState::Automation(ks)
777    }
778}
779
780impl From<CallbackKeyState> for KeyState {
781    fn from(ks: CallbackKeyState) -> Self {
782        KeyState::Callback(ks)
783    }
784}
785
786impl From<CapsWordKeyState> for KeyState {
787    fn from(ks: CapsWordKeyState) -> Self {
788        KeyState::CapsWord(ks)
789    }
790}
791
792impl From<ChordedKeyState> for KeyState {
793    fn from(ks: ChordedKeyState) -> Self {
794        KeyState::Chorded(ks)
795    }
796}
797
798impl From<ConsumerKeyState> for KeyState {
799    fn from(ks: ConsumerKeyState) -> Self {
800        KeyState::Consumer(ks)
801    }
802}
803
804impl From<CustomKeyState> for KeyState {
805    fn from(ks: CustomKeyState) -> Self {
806        KeyState::Custom(ks)
807    }
808}
809
810impl From<KeyboardKeyState> for KeyState {
811    fn from(ks: KeyboardKeyState) -> Self {
812        KeyState::Keyboard(ks)
813    }
814}
815
816impl From<LayeredKeyState> for KeyState {
817    fn from(ks: LayeredKeyState) -> Self {
818        KeyState::LayerModifier(ks)
819    }
820}
821
822impl From<MouseKeyState> for KeyState {
823    fn from(ks: MouseKeyState) -> Self {
824        KeyState::Mouse(ks)
825    }
826}
827
828impl From<TapDanceKeyState> for KeyState {
829    fn from(ks: TapDanceKeyState) -> Self {
830        KeyState::TapDance(ks)
831    }
832}
833
834impl From<TapHoldKeyState> for KeyState {
835    fn from(ks: TapHoldKeyState) -> Self {
836        KeyState::TapHold(ks)
837    }
838}
839
840impl From<StickyKeyState> for KeyState {
841    fn from(ks: StickyKeyState) -> Self {
842        KeyState::Sticky(ks)
843    }
844}
845
846/// Convenience trait for the data storage types.
847pub trait Keys {
848    /// Type used by [key::automation::System].
849    type Automation: Debug + Index<usize, Output = AutomationKey>;
850    /// Type used by [key::callback::System].
851    type Callback: Debug + Index<usize, Output = CallbackKey>;
852    /// Type used by [key::chorded::System].
853    type Chorded: Debug + Index<usize, Output = ChordedKey>;
854    /// Type used by [key::chorded::System].
855    type ChordedAuxiliary: Debug + Index<usize, Output = ChordedAuxiliaryKey>;
856    /// Type used by [key::keyboard::System].
857    type Keyboard: Debug + Index<usize, Output = KeyboardKey>;
858    /// Type used by [key::layered::System].
859    type LayerModifiers: Debug + Index<usize, Output = LayeredModifierKey>;
860    /// Type used by [key::layered::System].
861    type Layered: Debug + Index<usize, Output = LayeredKey>;
862    /// Type used by [key::sticky::System].
863    type Sticky: Debug + Index<usize, Output = StickyKey>;
864    /// Type used by [key::tap_dance::System].
865    type TapDance: Debug + Index<usize, Output = TapDanceKey>;
866    /// Type used by [key::tap_hold::System].
867    type TapHold: Debug + Index<usize, Output = TapHoldKey>;
868}
869
870/// Array-based data implementations.
871#[derive(Debug)]
872pub struct KeyArrays<
873    const AUTOMATION: usize,
874    const CALLBACK: usize,
875    const CHORDED: usize,
876    const CHORDED_AUXILIARY: usize,
877    const KEYBOARD: usize,
878    const LAYERED: usize,
879    const LAYER_MODIFIERS: usize,
880    const STICKY: usize,
881    const TAP_DANCE: usize,
882    const TAP_HOLD: usize,
883>;
884
885impl<
886        const AUTOMATION: usize,
887        const CALLBACK: usize,
888        const CHORDED: usize,
889        const CHORDED_AUXILIARY: usize,
890        const KEYBOARD: usize,
891        const LAYERED: usize,
892        const LAYER_MODIFIERS: usize,
893        const STICKY: usize,
894        const TAP_DANCE: usize,
895        const TAP_HOLD: usize,
896    > Keys
897    for KeyArrays<
898        AUTOMATION,
899        CALLBACK,
900        CHORDED,
901        CHORDED_AUXILIARY,
902        KEYBOARD,
903        LAYERED,
904        LAYER_MODIFIERS,
905        STICKY,
906        TAP_DANCE,
907        TAP_HOLD,
908    >
909{
910    type Automation = [AutomationKey; AUTOMATION];
911    type Callback = [CallbackKey; CALLBACK];
912    type Chorded = [ChordedKey; CHORDED];
913    type ChordedAuxiliary = [ChordedAuxiliaryKey; CHORDED_AUXILIARY];
914    type Keyboard = [KeyboardKey; KEYBOARD];
915    type LayerModifiers = [LayeredModifierKey; LAYER_MODIFIERS];
916    type Layered = [LayeredKey; LAYERED];
917    type Sticky = [StickyKey; STICKY];
918    type TapDance = [TapDanceKey; TAP_DANCE];
919    type TapHold = [TapHoldKey; TAP_HOLD];
920}
921
922/// Vec-based data implementations.
923#[derive(Debug)]
924#[cfg(feature = "std")]
925pub struct KeyVecs;
926
927#[cfg(feature = "std")]
928impl Keys for KeyVecs {
929    type Automation = Vec<AutomationKey>;
930    type Callback = Vec<CallbackKey>;
931    type Chorded = Vec<ChordedKey>;
932    type ChordedAuxiliary = Vec<ChordedAuxiliaryKey>;
933    type Keyboard = Vec<KeyboardKey>;
934    type LayerModifiers = Vec<LayeredModifierKey>;
935    type Layered = Vec<LayeredKey>;
936    type Sticky = Vec<StickyKey>;
937    type TapDance = Vec<TapDanceKey>;
938    type TapHold = Vec<TapHoldKey>;
939}
940
941/// Aggregate [key::System] implementation.
942#[derive(Debug, Clone, Copy, PartialEq)]
943pub struct System<D: Keys> {
944    automation: AutomationSystem<D::Automation>,
945    callback: CallbackSystem<D::Callback>,
946    caps_word: CapsWordSystem,
947    consumer: ConsumerSystem,
948    chorded: ChordedSystem<D::Chorded, D::ChordedAuxiliary>,
949    custom: CustomSystem,
950    keyboard: KeyboardSystem<D::Keyboard>,
951    layered: LayeredSystem<D::LayerModifiers, D::Layered>,
952    mouse: MouseSystem,
953    sticky: StickySystem<D::Sticky>,
954    tap_dance: TapDanceSystem<D::TapDance>,
955    tap_hold: TapHoldSystem<D::TapHold>,
956    marker: PhantomData<D>,
957}
958
959impl<
960        const AUTOMATION: usize,
961        const CALLBACK: usize,
962        const CHORDED: usize,
963        const CHORDED_AUXILIARY: usize,
964        const KEYBOARD: usize,
965        const LAYERED: usize,
966        const LAYER_MODIFIERS: usize,
967        const STICKY: usize,
968        const TAP_DANCE: usize,
969        const TAP_HOLD: usize,
970    >
971    System<
972        KeyArrays<
973            AUTOMATION,
974            CALLBACK,
975            CHORDED,
976            CHORDED_AUXILIARY,
977            KEYBOARD,
978            LAYERED,
979            LAYER_MODIFIERS,
980            STICKY,
981            TAP_DANCE,
982            TAP_HOLD,
983        >,
984    >
985{
986    /// Constructs a new [System].
987    #[allow(clippy::too_many_arguments)]
988    pub const fn array_based(
989        automation: AutomationSystem<[AutomationKey; AUTOMATION]>,
990        callback: CallbackSystem<[CallbackKey; CALLBACK]>,
991        chorded: ChordedSystem<[ChordedKey; CHORDED], [ChordedAuxiliaryKey; CHORDED_AUXILIARY]>,
992        keyboard: KeyboardSystem<[KeyboardKey; KEYBOARD]>,
993        layered: LayeredSystem<[LayeredModifierKey; LAYER_MODIFIERS], [LayeredKey; LAYERED]>,
994        sticky: StickySystem<[StickyKey; STICKY]>,
995        tap_dance: TapDanceSystem<[TapDanceKey; TAP_DANCE]>,
996        tap_hold: TapHoldSystem<[TapHoldKey; TAP_HOLD]>,
997    ) -> Self {
998        System {
999            automation,
1000            callback,
1001            caps_word: key::caps_word::System::new(),
1002            consumer: key::consumer::System::new(),
1003            chorded,
1004            custom: key::custom::System::new(),
1005            keyboard,
1006            layered,
1007            mouse: key::mouse::System::new(),
1008            sticky,
1009            tap_dance,
1010            tap_hold,
1011            marker: PhantomData,
1012        }
1013    }
1014}
1015
1016#[cfg(feature = "std")]
1017impl System<KeyVecs> {
1018    /// Constructs a new [System].
1019    #[allow(clippy::too_many_arguments)]
1020    pub const fn vec_based(
1021        automation: AutomationSystem<Vec<AutomationKey>>,
1022        callback: CallbackSystem<Vec<CallbackKey>>,
1023        chorded: ChordedSystem<Vec<ChordedKey>, Vec<ChordedAuxiliaryKey>>,
1024        keyboard: KeyboardSystem<Vec<KeyboardKey>>,
1025        layered: LayeredSystem<Vec<LayeredModifierKey>, Vec<LayeredKey>>,
1026        sticky: StickySystem<Vec<StickyKey>>,
1027        tap_dance: TapDanceSystem<Vec<TapDanceKey>>,
1028        tap_hold: TapHoldSystem<Vec<TapHoldKey>>,
1029    ) -> Self {
1030        System {
1031            automation,
1032            callback,
1033            caps_word: key::caps_word::System::new(),
1034            consumer: key::consumer::System::new(),
1035            chorded,
1036            custom: key::custom::System::new(),
1037            keyboard,
1038            layered,
1039            mouse: key::mouse::System::new(),
1040            sticky,
1041            tap_dance,
1042            tap_hold,
1043            marker: PhantomData,
1044        }
1045    }
1046}
1047
1048impl<K: Debug + Keys> key::System<Ref> for System<K> {
1049    type Ref = Ref;
1050    type Context = Context;
1051    type Event = Event;
1052    type PendingKeyState = PendingKeyState;
1053    type KeyState = KeyState;
1054
1055    fn new_pressed_key(
1056        &self,
1057        keymap_index: u16,
1058        context: &Self::Context,
1059        key_ref: Ref,
1060    ) -> (
1061        key::PressedKeyResult<Ref, Self::PendingKeyState, Self::KeyState>,
1062        key::KeyEvents<Self::Event>,
1063    ) {
1064        match key_ref {
1065            Ref::Automation(key_ref) => {
1066                let (pkr, pke) =
1067                    self.automation
1068                        .new_pressed_key(keymap_index, &context.automation, key_ref);
1069                (pkr.into_result(), pke.into_events())
1070            }
1071            Ref::Callback(key_ref) => {
1072                let (pkr, pke) =
1073                    self.callback
1074                        .new_pressed_key(keymap_index, &context.callback, key_ref);
1075                (pkr.into_result(), pke.into_events())
1076            }
1077            Ref::CapsWord(key_ref) => {
1078                let (pkr, pke) =
1079                    self.caps_word
1080                        .new_pressed_key(keymap_index, &context.caps_word, key_ref);
1081                (pkr.into_result(), pke.into_events())
1082            }
1083            Ref::Chorded(key_ref) => {
1084                let (pkr, pke) =
1085                    self.chorded
1086                        .new_pressed_key(keymap_index, &context.chorded, key_ref);
1087                (pkr.into_result(), pke.into_events())
1088            }
1089            Ref::Consumer(key_ref) => {
1090                let (pkr, pke) =
1091                    self.consumer
1092                        .new_pressed_key(keymap_index, &context.consumer, key_ref);
1093                (pkr.into_result(), pke.into_events())
1094            }
1095            Ref::Custom(key_ref) => {
1096                let (pkr, pke) =
1097                    self.custom
1098                        .new_pressed_key(keymap_index, &context.custom, key_ref);
1099                (pkr.into_result(), pke.into_events())
1100            }
1101            Ref::Keyboard(key_ref) => {
1102                let (pkr, pke) =
1103                    self.keyboard
1104                        .new_pressed_key(keymap_index, &context.keyboard, key_ref);
1105                (pkr.into_result(), pke.into_events())
1106            }
1107            Ref::Layered(key_ref) => {
1108                let (pkr, pke) =
1109                    self.layered
1110                        .new_pressed_key(keymap_index, &context.layered, key_ref);
1111                (pkr.into_result(), pke.into_events())
1112            }
1113            Ref::Mouse(key_ref) => {
1114                let (pkr, pke) = self
1115                    .mouse
1116                    .new_pressed_key(keymap_index, &context.mouse, key_ref);
1117                (pkr.into_result(), pke.into_events())
1118            }
1119            Ref::Sticky(key_ref) => {
1120                let (pkr, pke) =
1121                    self.sticky
1122                        .new_pressed_key(keymap_index, &context.sticky, key_ref);
1123                (pkr.into_result(), pke.into_events())
1124            }
1125            Ref::TapDance(key_ref) => {
1126                let (pkr, pke) =
1127                    self.tap_dance
1128                        .new_pressed_key(keymap_index, &context.tap_dance, key_ref);
1129                (pkr.into_result(), pke.into_events())
1130            }
1131            Ref::TapHold(key_ref) => {
1132                let (pkr, pke) =
1133                    self.tap_hold
1134                        .new_pressed_key(keymap_index, &context.tap_hold, key_ref);
1135                (pkr.into_result(), pke.into_events())
1136            }
1137        }
1138    }
1139
1140    fn update_pending_state(
1141        &self,
1142        pending_state: &mut Self::PendingKeyState,
1143        keymap_index: u16,
1144        context: &Self::Context,
1145        key_ref: Ref,
1146        event: key::Event<Self::Event>,
1147    ) -> (Option<key::NewPressedKey<Ref>>, key::KeyEvents<Self::Event>) {
1148        match (key_ref, pending_state) {
1149            (Ref::Chorded(key_ref), PendingKeyState::Chorded(pending_state)) => {
1150                if let Ok(event) = event.try_into_key_event() {
1151                    let (maybe_npk, pke) = self.chorded.update_pending_state(
1152                        pending_state,
1153                        keymap_index,
1154                        &context.chorded,
1155                        key_ref,
1156                        event,
1157                    );
1158                    (maybe_npk, pke.into_events())
1159                } else {
1160                    (None, key::KeyEvents::no_events())
1161                }
1162            }
1163            (Ref::TapDance(key_ref), PendingKeyState::TapDance(pending_state)) => {
1164                if let Ok(event) = event.try_into_key_event() {
1165                    let (maybe_npk, pke) = self.tap_dance.update_pending_state(
1166                        pending_state,
1167                        keymap_index,
1168                        &context.tap_dance,
1169                        key_ref,
1170                        event,
1171                    );
1172                    (maybe_npk, pke.into_events())
1173                } else {
1174                    (None, key::KeyEvents::no_events())
1175                }
1176            }
1177            (Ref::TapHold(key_ref), PendingKeyState::TapHold(pending_state)) => {
1178                if let Ok(event) = event.try_into_key_event() {
1179                    let (maybe_npk, pke) = self.tap_hold.update_pending_state(
1180                        pending_state,
1181                        keymap_index,
1182                        &context.tap_hold,
1183                        key_ref,
1184                        event,
1185                    );
1186                    (maybe_npk, pke.into_events())
1187                } else {
1188                    (None, key::KeyEvents::no_events())
1189                }
1190            }
1191            (_, _) => panic!("Mismatched key_ref and key_state variants"),
1192        }
1193    }
1194
1195    fn update_state(
1196        &self,
1197        key_state: &mut Self::KeyState,
1198        key_ref: &Self::Ref,
1199        context: &Self::Context,
1200        keymap_index: u16,
1201        event: key::Event<Self::Event>,
1202    ) -> key::KeyEvents<Self::Event> {
1203        match (key_ref, key_state) {
1204            (Ref::Automation(key_ref), KeyState::Automation(key_state)) => {
1205                if let Ok(event) = event.try_into_key_event() {
1206                    let pke = self.automation.update_state(
1207                        key_state,
1208                        key_ref,
1209                        &context.automation,
1210                        keymap_index,
1211                        event,
1212                    );
1213                    pke.into_events()
1214                } else {
1215                    key::KeyEvents::no_events()
1216                }
1217            }
1218            (Ref::Consumer(key_ref), KeyState::Consumer(key_state)) => {
1219                if let Ok(event) = event.try_into_key_event() {
1220                    let pke = self.consumer.update_state(
1221                        key_state,
1222                        key_ref,
1223                        &context.consumer,
1224                        keymap_index,
1225                        event,
1226                    );
1227                    pke.into_events()
1228                } else {
1229                    key::KeyEvents::no_events()
1230                }
1231            }
1232            (Ref::Keyboard(key_ref), KeyState::Keyboard(key_state)) => {
1233                if let Ok(event) = event.try_into_key_event() {
1234                    let pke = self.keyboard.update_state(
1235                        key_state,
1236                        key_ref,
1237                        &context.keyboard,
1238                        keymap_index,
1239                        event,
1240                    );
1241                    pke.into_events()
1242                } else {
1243                    key::KeyEvents::no_events()
1244                }
1245            }
1246            (Ref::Layered(key_ref), KeyState::LayerModifier(key_state)) => {
1247                if let Ok(event) = event.try_into_key_event() {
1248                    let pke = self.layered.update_state(
1249                        key_state,
1250                        key_ref,
1251                        &context.layered,
1252                        keymap_index,
1253                        event,
1254                    );
1255                    pke.into_events()
1256                } else {
1257                    key::KeyEvents::no_events()
1258                }
1259            }
1260            (Ref::Sticky(key_ref), KeyState::Sticky(key_state)) => {
1261                if let Ok(event) = event.try_into_key_event() {
1262                    let pke = self.sticky.update_state(
1263                        key_state,
1264                        key_ref,
1265                        &context.sticky,
1266                        keymap_index,
1267                        event,
1268                    );
1269                    pke.into_events()
1270                } else {
1271                    key::KeyEvents::no_events()
1272                }
1273            }
1274            (_, _) => key::KeyEvents::no_events(),
1275        }
1276    }
1277
1278    fn key_output(
1279        &self,
1280        key_ref: &Self::Ref,
1281        key_state: &Self::KeyState,
1282    ) -> Option<key::KeyOutput> {
1283        match (key_ref, key_state) {
1284            (Ref::Consumer(r), KeyState::Consumer(ks)) => self.consumer.key_output(r, ks),
1285            (Ref::Custom(r), KeyState::Custom(ks)) => self.custom.key_output(r, ks),
1286            (Ref::Keyboard(r), KeyState::Keyboard(ks)) => self.keyboard.key_output(r, ks),
1287            (Ref::Mouse(r), KeyState::Mouse(ks)) => self.mouse.key_output(r, ks),
1288            (Ref::Sticky(r), KeyState::Sticky(ks)) => self.sticky.key_output(r, ks),
1289            (Ref::Layered(r), KeyState::LayerModifier(ks)) => self.layered.key_output(r, ks),
1290            (_, _) => None,
1291        }
1292    }
1293}
1294
1295#[cfg(test)]
1296mod tests {
1297    use super::*;
1298
1299    #[test]
1300    fn test_sizeof_ref() {
1301        assert_eq!(3, core::mem::size_of::<Ref>());
1302    }
1303
1304    #[test]
1305    fn test_sizeof_event() {
1306        assert_eq!(12, core::mem::size_of::<Event>());
1307    }
1308}