rmk-types 0.3.0

Common types in RMK
Documentation
//! LED indicator.
//!
//! This module handles keyboard LED indicators such as Caps Lock, Num Lock,
//! and Scroll Lock. It provides efficient bitfield operations for these indicators.
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};

use bitfield_struct::bitfield;
use postcard::experimental::max_size::MaxSize;

/// Indicators defined in the HID spec 11.1
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum LedIndicatorType {
    NumLock,
    CapsLock,
    ScrollLock,
    Compose,
    Kana,
}

#[bitfield(u8, defmt = cfg(feature = "defmt"))]
#[derive(Eq, PartialEq, MaxSize)]
pub struct LedIndicator {
    #[bits(1)]
    pub num_lock: bool,
    #[bits(1)]
    pub caps_lock: bool,
    #[bits(1)]
    pub scroll_lock: bool,
    #[bits(1)]
    pub compose: bool,
    #[bits(1)]
    pub kana: bool,
    #[bits(3)]
    _reserved: u8,
}

// u8 on the wire (postcard); named bools on serde-wasm-bindgen / serde_json (TS).
crate::bitfield_named_serde!(LedIndicator, "LedIndicator", {
    num_lock = with_num_lock,
    caps_lock = with_caps_lock,
    scroll_lock = with_scroll_lock,
    compose = with_compose,
    kana = with_kana,
});

impl BitOr for LedIndicator {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self::Output {
        Self::from_bits(self.into_bits() | rhs.into_bits())
    }
}

impl BitAnd for LedIndicator {
    type Output = Self;

    fn bitand(self, rhs: Self) -> Self::Output {
        Self::from_bits(self.into_bits() & rhs.into_bits())
    }
}

impl Not for LedIndicator {
    type Output = Self;

    fn not(self) -> Self::Output {
        Self::from_bits(!self.into_bits())
    }
}

impl BitAndAssign for LedIndicator {
    fn bitand_assign(&mut self, rhs: Self) {
        *self = *self & rhs;
    }
}

impl BitOrAssign for LedIndicator {
    fn bitor_assign(&mut self, rhs: Self) {
        *self = *self | rhs;
    }
}

impl LedIndicator {
    pub const NUM_LOCK: Self = Self::new().with_num_lock(true);
    pub const CAPS_LOCK: Self = Self::new().with_caps_lock(true);
    pub const SCROLL_LOCK: Self = Self::new().with_scroll_lock(true);
    pub const COMPOSE: Self = Self::new().with_compose(true);
    pub const KANA: Self = Self::new().with_kana(true);

    pub const fn new_from(num_lock: bool, caps_lock: bool, scroll_lock: bool, compose: bool, kana: bool) -> Self {
        Self::new()
            .with_num_lock(num_lock)
            .with_caps_lock(caps_lock)
            .with_scroll_lock(scroll_lock)
            .with_compose(compose)
            .with_kana(kana)
    }
}