keebrs 0.3.0

Keyboard firmware building blocks
Documentation
use core::{
    pin::Pin,
    task::{
        Context,
        Poll,
    },
};

use futures::{
    prelude::*,
    ready,
};

use serde::{
    Deserialize,
    Serialize,
};

mod background;
pub mod chain;

pub use background::*;

#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone, Copy)]
pub enum Msg<T> {
    Broadcast { to: i8, from: i8, data: T },
    Direct { to: i8, from: i8, data: T },
}

impl<T> Msg<T> {
    pub fn broadcast(data: T) -> Self {
        Self::Broadcast {
            from: 0,
            to: 0,
            data,
        }
    }
    pub fn direct(to: i8, data: T) -> Self {
        Self::Direct { to, from: 0, data }
    }
    pub fn set_from(&mut self, new_from: i8) {
        match self {
            Self::Direct { ref mut from, .. } | Self::Broadcast { ref mut from, .. } => {
                *from = new_from;
            }
        }
    }
    pub fn unpack(self) -> (i8, T) {
        match self {
            Self::Direct { from, data, .. } | Self::Broadcast { from, data, .. } => (from, data),
        }
    }
}

pub trait NetSend<T>: Sink<Msg<T>> {}
impl<T, U> NetSend<T> for U where U: Sink<Msg<T>> {}

pub trait NetRecv<T>: TryStream<Ok = Msg<T>> {}
impl<T, U> NetRecv<T> for U where U: TryStream<Ok = Msg<T>> {}

/// A generic keyboard network.
///
/// It accepts messages to either send to all other boards, or to one specific
/// one via the Sink trait. When sending a message, the `from` field should be
/// left `0` in order to be filled in by the net implementation.
///
/// It receives messages via the `Stream` trait.
///
/// On startup, it should wait on the `poll_init` method to return `Poll::Ready`,
/// or for USB detection indicating that it is the "primary" board. If it is
/// determined to be the primary, it should initialize the other boards with
/// `poll_init_others`.
pub trait Net<T>: NetSend<T> + NetRecv<T> {
    fn addr(&self) -> i8;
}

pub trait NetSendExt<T>: NetSend<T> {
    fn send_to(&mut self, to: i8, msg: T) -> futures::sink::Send<Self, Msg<T>>
    where
        Self: Unpin,
    {
        self.send(Msg::direct(to, msg))
    }

    fn broadcast(&mut self, msg: T) -> futures::sink::Send<Self, Msg<T>>
    where
        Self: Unpin,
    {
        self.send(Msg::broadcast(msg))
    }

    fn poll_flush_unpin(
        &mut self,
        cx: &mut Context,
    ) -> Poll<Result<(), <Self as Sink<Msg<T>>>::Error>>
    where
        Self: Unpin,
    {
        Pin::new(self).poll_flush(cx)
    }

    fn poll_ready_unpin(
        &mut self,
        cx: &mut Context,
    ) -> Poll<Result<(), <Self as Sink<Msg<T>>>::Error>>
    where
        Self: Unpin,
    {
        Pin::new(self).poll_ready(cx)
    }
}

pub trait NetRecvExt<T>: NetRecv<T> {}

impl<T, U> NetSendExt<T> for U where U: NetSend<T> {}
impl<T, U> NetRecvExt<T> for U where U: NetRecv<T> {}