feat!: overhaul the light protocol (i.e. collection of traits)

This commit is contained in:
2025-05-02 17:33:21 -04:00
parent e680f10be8
commit 472ca50ec0
2 changed files with 117 additions and 24 deletions

View File

@@ -4,6 +4,16 @@ version = "0.1.0"
edition = "2021"
license = { workspace = true }
[features]
default = []
serde = ["dep:serde"]
[dependencies]
deranged = { workspace = true }
derive_more = { workspace = true }
ext-trait = { workspace = true }
palette = { workspace = true }
snafu = { workspace = true }
strum = { workspace = true, features = ["derive"] }
serde = { optional = true, workspace = true, features = ["derive"] }

View File

@@ -1,43 +1,126 @@
use std::{error::Error, future::Future};
use deranged::RangedU16;
use palette::Oklch;
use snafu::{ResultExt, Snafu};
pub trait Light {
type IsOnError: Error;
fn is_on(&self) -> impl Future<Output = Result<bool, Self::IsOnError>> + Send;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, strum::Display, strum::EnumIs,
)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum State {
Off,
On,
}
type IsOffError: Error;
fn is_off(&self) -> impl Future<Output = Result<bool, Self::IsOffError>> + Send;
impl State {
pub const fn invert(self) -> Self {
match self {
State::Off => State::On,
State::On => State::Off,
}
}
}
type TurnOnError: Error;
fn turn_on(&mut self) -> impl Future<Output = Result<(), Self::TurnOnError>> + Send;
impl From<bool> for State {
fn from(bool: bool) -> Self {
if bool {
State::On
} else {
State::Off
}
}
}
type TurnOffError: Error;
fn turn_off(&mut self) -> impl Future<Output = Result<(), Self::TurnOffError>> + Send;
impl From<State> for bool {
fn from(state: State) -> Self {
state.is_on()
}
}
type ToggleError: Error;
fn toggle(&mut self) -> impl Future<Output = Result<(), Self::ToggleError>> + Send;
pub trait GetState {
type Error: Error;
fn get_state(&self) -> impl Future<Output = Result<State, Self::Error>> + Send;
}
#[ext_trait::extension(trait IsOff)]
impl<T: GetState> T {
async fn is_off(&self) -> Result<bool, T::Error> {
Ok(self.get_state().await?.is_off())
}
}
#[ext_trait::extension(trait IsOn)]
impl<T: GetState> T {
async fn is_on(&self) -> Result<bool, T::Error> {
Ok(self.get_state().await?.is_on())
}
}
pub trait SetState {
type Error: Error;
fn set_state(&mut self, state: State) -> impl Future<Output = Result<(), Self::Error>> + Send;
}
#[ext_trait::extension(trait TurnOff)]
impl<T: SetState> T {
async fn turn_off(&mut self) -> Result<(), T::Error> {
self.set_state(State::Off).await
}
}
#[ext_trait::extension(trait TurnOn)]
impl<T: SetState> T {
async fn turn_on(&mut self) -> Result<(), T::Error> {
self.set_state(State::On).await
}
}
#[derive(Debug, Clone, Snafu)]
enum InvertToToggleError<GetStateError: Error + 'static, SetStateError: Error + 'static> {
GetStateError { source: GetStateError },
SetStateError { source: SetStateError },
}
#[ext_trait::extension(trait InvertToToggle)]
impl<T: GetState + SetState> T
where
<T as GetState>::Error: 'static,
<T as SetState>::Error: 'static,
{
/// Toggle the light by setting it to the inverse of its current state
async fn toggle(
&mut self,
) -> Result<(), InvertToToggleError<<T as GetState>::Error, <T as SetState>::Error>> {
let state = self.get_state().await.context(GetStateSnafu)?;
self.set_state(state.invert())
.await
.context(SetStateSnafu)?;
Ok(())
}
}
pub trait Toggle {
type Error: Error;
fn toggle(&mut self, state: State) -> impl Future<Output = Result<(), Self::Error>> + Send;
}
#[derive(Debug, Clone, Copy, derive_more::From, derive_more::Into)]
pub struct Kelvin(pub RangedU16<2000, 10000>);
pub trait KelvinLight: Light {
type TurnToKelvinError: Error;
fn turn_to_kelvin(
pub trait TurnToTemperature {
type TurnToTemperatureError: Error;
fn turn_to_temperature(
&mut self,
temperature: Kelvin,
) -> impl Future<Output = Result<(), Self::TurnToKelvinError>> + Send;
) -> impl Future<Output = Result<(), Self::TurnToTemperatureError>> + Send;
}
// TODO: replace with a type from a respected and useful library
#[derive(Debug, Clone, Copy, derive_more::From, derive_more::Into)]
pub struct Rgb(pub u8, pub u8, pub u8);
pub trait RgbLight: Light {
type TurnToRgbError: Error;
fn turn_to_rgb(
pub trait TurnToColor {
type TurnToColorError: Error;
fn turn_to_color(
&mut self,
color: Rgb,
) -> impl Future<Output = Result<(), Self::TurnToRgbError>> + Send;
color: Oklch<f64>,
) -> impl Future<Output = Result<(), Self::TurnToColorError>> + Send;
}