1use heapless::Vec;
4use postcard::experimental::max_size::MaxSize;
5use serde::{Deserialize, Serialize};
6
7use crate::action::KeyAction;
8use crate::constants::COMBO_SIZE;
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
22#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
23pub struct Combo {
24 #[cfg_attr(feature = "wasm", tsify(type = "KeyAction[]"))]
25 pub actions: Vec<KeyAction, COMBO_SIZE>,
26 pub output: KeyAction,
27 pub layer: Option<u8>,
28}
29
30impl MaxSize for Combo {
31 const POSTCARD_MAX_SIZE: usize = crate::heapless_vec_max_size::<KeyAction, COMBO_SIZE>()
32 + KeyAction::POSTCARD_MAX_SIZE
33 + Option::<u8>::POSTCARD_MAX_SIZE;
34}
35
36impl Combo {
37 pub fn new<I: IntoIterator<Item = KeyAction>>(actions: I, output: KeyAction, layer: Option<u8>) -> Self {
42 let mut combo_actions = Vec::new();
43 for action in actions {
44 if action != KeyAction::No && combo_actions.push(action).is_err() {
45 break;
46 }
47 }
48 Self {
49 actions: combo_actions,
50 output,
51 layer,
52 }
53 }
54
55 pub fn empty() -> Self {
57 Self {
58 actions: Vec::new(),
59 output: KeyAction::No,
60 layer: None,
61 }
62 }
63
64 pub fn size(&self) -> usize {
66 self.actions.len()
67 }
68
69 pub fn find_key_action_index(&self, key_action: &KeyAction) -> Option<usize> {
71 self.actions.iter().position(|a| a == key_action)
72 }
73
74 pub fn contains(&self, key_action: &KeyAction) -> bool {
76 self.actions.contains(key_action)
77 }
78}