1use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
7
8use bitfield_struct::bitfield;
9use postcard::experimental::max_size::MaxSize;
10
11use crate::keycode::HidKeyCode;
12
13#[bitfield(u8, order = Lsb, debug = false)]
15#[derive(MaxSize, Eq, PartialEq)]
16pub struct ModifierCombination {
17 #[bits(1)]
18 pub left_ctrl: bool,
19 #[bits(1)]
20 pub left_shift: bool,
21 #[bits(1)]
22 pub left_alt: bool,
23 #[bits(1)]
24 pub left_gui: bool,
25 #[bits(1)]
26 pub right_ctrl: bool,
27 #[bits(1)]
28 pub right_shift: bool,
29 #[bits(1)]
30 pub right_alt: bool,
31 #[bits(1)]
32 pub right_gui: bool,
33}
34
35crate::impl_debug_list!(ModifierCombination, |self| [
36 (self.left_ctrl(), HidKeyCode::LCtrl),
37 (self.left_shift(), HidKeyCode::LShift),
38 (self.left_alt(), HidKeyCode::LAlt),
39 (self.left_gui(), HidKeyCode::LGui),
40 (self.right_ctrl(), HidKeyCode::RCtrl),
41 (self.right_shift(), HidKeyCode::RShift),
42 (self.right_alt(), HidKeyCode::RAlt),
43 (self.right_gui(), HidKeyCode::RGui),
44]
45.into_iter()
46.filter_map(|(state, label)| state.then_some(label)));
47
48crate::bitfield_named_serde!(ModifierCombination, "ModifierCombination", {
50 left_ctrl = with_left_ctrl,
51 left_shift = with_left_shift,
52 left_alt = with_left_alt,
53 left_gui = with_left_gui,
54 right_ctrl = with_right_ctrl,
55 right_shift = with_right_shift,
56 right_alt = with_right_alt,
57 right_gui = with_right_gui,
58});
59
60impl BitOr for ModifierCombination {
61 type Output = Self;
62
63 fn bitor(self, rhs: Self) -> Self::Output {
64 Self::from_bits(self.into_bits() | rhs.into_bits())
65 }
66}
67
68impl BitAnd for ModifierCombination {
69 type Output = Self;
70
71 fn bitand(self, rhs: Self) -> Self::Output {
72 Self::from_bits(self.into_bits() & rhs.into_bits())
73 }
74}
75
76impl BitAndAssign for ModifierCombination {
77 fn bitand_assign(&mut self, rhs: Self) {
78 *self = *self & rhs;
79 }
80}
81
82impl BitOrAssign for ModifierCombination {
83 fn bitor_assign(&mut self, rhs: Self) {
84 *self = *self | rhs;
85 }
86}
87
88impl Not for ModifierCombination {
89 type Output = Self;
90
91 fn not(self) -> Self::Output {
92 Self::from_bits(!self.into_bits())
93 }
94}
95
96impl ModifierCombination {
97 pub const LCTRL: Self = Self::new().with_left_ctrl(true);
98 pub const LSHIFT: Self = Self::new().with_left_shift(true);
99 pub const LALT: Self = Self::new().with_left_alt(true);
100 pub const LGUI: Self = Self::new().with_left_gui(true);
101
102 pub const RCTRL: Self = Self::new().with_right_ctrl(true);
103 pub const RSHIFT: Self = Self::new().with_right_shift(true);
104 pub const RALT: Self = Self::new().with_right_alt(true);
105 pub const RGUI: Self = Self::new().with_right_gui(true);
106
107 pub const fn new_from(right: bool, gui: bool, alt: bool, shift: bool, ctrl: bool) -> Self {
108 if right {
109 ModifierCombination::new()
110 .with_right_gui(gui)
111 .with_right_alt(alt)
112 .with_right_shift(shift)
113 .with_right_ctrl(ctrl)
114 } else {
115 ModifierCombination::new()
116 .with_left_gui(gui)
117 .with_left_alt(alt)
118 .with_left_shift(shift)
119 .with_left_ctrl(ctrl)
120 }
121 }
122
123 #[allow(clippy::too_many_arguments)]
124 pub const fn new_from_vals(
125 left_ctrl: bool,
126 left_shift: bool,
127 left_alt: bool,
128 left_gui: bool,
129 right_ctrl: bool,
130 right_shift: bool,
131 right_alt: bool,
132 right_gui: bool,
133 ) -> Self {
134 ModifierCombination::new()
135 .with_left_ctrl(left_ctrl)
136 .with_left_shift(left_shift)
137 .with_left_alt(left_alt)
138 .with_left_gui(left_gui)
139 .with_right_ctrl(right_ctrl)
140 .with_right_shift(right_shift)
141 .with_right_alt(right_alt)
142 .with_right_gui(right_gui)
143 }
144
145 pub const fn into_packed_bits(self) -> u8 {
154 let bits = self.into_bits();
155 if bits == 0 {
156 return 0;
157 }
158 let left_bits = bits & 0x0F; let right_bits = bits >> 4; if left_bits != 0 {
163 left_bits
164 } else {
165 right_bits | 0x10 }
167 }
168
169 pub const fn from_packed_bits(bits: u8) -> Self {
177 let modifier_bits = bits & 0x0F; let is_right = (bits & 0x10) != 0; if is_right {
181 Self::from_bits(modifier_bits << 4) } else {
183 Self::from_bits(modifier_bits) }
185 }
186}