diff --git a/src/events.rs b/src/events.rs index bdaad0b..bf51f5e 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,113 +1,24 @@ -use core::fmt::Debug; +use core::fmt::{Debug, Display}; +use std::{collections::{LinkedList, VecDeque}, sync::{Arc, Mutex}}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum InputEvent { - PowerOn, - PowerOff, - NetworkActivity, - NetworkOnline, - NetworkOffline -} +use rgb::Rgb; -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Variant { + SignedByte(i8), Byte(u8), UInt(u32), Int(i32), BigUInt(u64), BigInt(i64), - Boolean(bool) + Boolean(bool), + String(String), + RGB(Rgb) } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Event { - ReadyToRock, - Tick, - StartThing(&'static str), - StopThing(&'static str), - Input(InputEvent), - PropertyChange(&'static str, Variant) -} - -pub struct SystemState { - key: &'static str, - value: Variant, - values: Vec::> -} - -impl SystemState { - pub fn new() -> Self { - SystemState { - key: "", - value: Variant::Byte(0), - values: Vec::new() - } - } - - fn get_key(&self, key: &'static str) -> Option<&Self> { - if key == self.key { - Some(self) - } else { - for next in self.values.iter() { - match next.get_key(key) { - None => (), - Some(next_val) => return Some(next_val) - } - } - return None - } - } - - fn get_key_mut(&mut self, key: &'static str) -> Option<&mut Self> { - if key == self.key { - Some(self) - } else { - for next in self.values.iter_mut() { - match next.get_key_mut(key) { - None => (), - Some(next_val) => return Some(next_val) - } - } - return None - } - } - - pub fn get(&self, key: &'static str) -> Option { - match self.get_key(key) { - None => None, - Some(v) => Some(v.value) - } - } - - pub fn set(&mut self, key: &'static str, value: V) where Variant: From { - match self.get_key_mut(key) { - None => self.values.push(Box::new(SystemState { - value: value.into(), - key: key, - values: Vec::new() - })), - Some(found_key) => { - found_key.value = value.into() - } - } - } -} - -impl Event { - pub fn new_tick() -> Self { - Event::Tick - } - - pub fn new_property_change(key: &'static str, data: T) -> Self where Variant: From { - Event::PropertyChange(key, Variant::from(data)) - } - - pub fn new_ready_to_rock() -> Self { - Event::ReadyToRock - } - - pub fn new_input_event(event: InputEvent) -> Self { - Event::Input(event) +impl From for Variant { + fn from(value: u8) -> Self { + Variant::Byte(value) } } @@ -120,6 +31,21 @@ impl Into for Variant { } } +impl From for Variant { + fn from(value: u64) -> Self { + Variant::BigUInt(value) + } +} + +impl Into for Variant { + fn into(self) -> u64 { + match self { + Variant::BigUInt(b) => b, + _ => 0 + } + } +} + impl From for Variant { fn from(value: bool) -> Self { Variant::Boolean(value) @@ -132,32 +58,197 @@ impl From for Variant { } } -impl From for Variant { - fn from(value: u8) -> Self { - Variant::Byte(value) +impl From for Variant { + fn from(value: u32) -> Self { + Variant::UInt(value) } } +impl From for Variant { + fn from(value: i32) -> Self { + Variant::Int(value) + } +} + +impl From for Variant { + fn from(value: String) -> Self { + Variant::String(value) + } +} + +impl<'a> From<&'a str> for Variant { + fn from(value: &'a str) -> Self { + Variant::String(value.to_owned()) + } +} + +impl From> for Variant { + fn from(value: Rgb) -> Self { + Variant::RGB(value) + } +} + +impl From for Variant { + fn from(value: i8) -> Self { + Variant::SignedByte(value) + } +} + +impl Display for Variant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Variant::BigInt(i) => (i as &dyn Display).fmt(f), + Variant::BigUInt(i) => (i as &dyn Display).fmt(f), + Variant::Boolean(i) => (i as &dyn Display).fmt(f), + Variant::Byte(i) => (i as &dyn Display).fmt(f), + Variant::Int(i) => (i as &dyn Display).fmt(f), + Variant::String(i) => (i as &dyn Display).fmt(f), + Variant::UInt(i) => (i as &dyn Display).fmt(f), + Variant::SignedByte(b) => (b as &dyn Display).fmt(f), + Variant::RGB(rgb) => f.write_fmt(format_args!("[{}, {}, {}]", rgb.r, rgb.g, rgb.b)), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Event { + ReadyToRock, + Tick, + StartThing(&'static str), + StopThing(&'static str), + PropertyChange(&'static str, Variant) +} + +impl Event { + pub const fn new_tick() -> Self { + Event::Tick + } + + pub fn new_property_change(key: &'static str, data: T) -> Self where Variant: From { + Event::PropertyChange(key, Variant::from(data)) + } + + pub const fn new_ready_to_rock() -> Self { + Event::ReadyToRock + } + + pub const fn new_start_thing(name: &'static str) -> Self { + Event::StartThing(name) + } + + pub const fn new_stop_thing(name: &'static str) -> Self { + Event::StopThing(name) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Property { + key: &'static str, + value: Variant +} + +impl Property { + pub const fn new(key: &'static str, value: Variant) -> Self { + Property { + key, + value: value + } + } +} + +#[derive(Debug, Clone)] +pub struct Properties { + contents: LinkedList +} + +impl Properties { + fn new() -> Self { + Properties { + contents: LinkedList::new() + } + } + + fn get_key(&self, key: &'static str) -> Option<&Property> { + for next in self.contents.iter() { + if next.key == key { + return Some(next); + } + } + + return None; + } + + fn get_key_mut(&mut self, key: &'static str) -> Option<&mut Property> { + for next in self.contents.iter_mut() { + if next.key == key { + return Some(next); + } + } + + return None; + } + + pub fn get(&self, key: &'static str) -> Option { + match self.get_key(key) { + None => None, + Some(v) => Some(v.value.clone()) + } + } + + pub fn set(&mut self, key: &'static str, value: V) -> bool where Variant: From { + let as_variant: Variant = value.into(); + match self.get_key_mut(key) { + None => { + self.contents.push_front(Property::new(key, as_variant)); + return true + }, + Some(found_key) => { + if found_key.value != as_variant { + found_key.value = as_variant; + return true + } + } + } + + return false + } +} + +#[derive(Clone)] pub struct EventBus { - pending: Vec + pending: Arc>>, + props: Arc> } impl EventBus { pub fn new() -> Self { EventBus { - pending: Vec::new() + pending: Arc::new(Mutex::new(VecDeque::with_capacity(32))), + props: Arc::new(Mutex::new(Properties::new())) } } pub fn next(&mut self) -> Event { - if self.pending.len() == 0 { - Event::new_tick() - } else { - self.pending.pop().unwrap() + let next = self.pending.lock().unwrap().pop_front().unwrap_or(Event::new_tick()); + + match next { + Event::PropertyChange(key, value) => { + if self.props.lock().unwrap().set(key, value.clone()) { + log::trace!("prop-update key={} value={:?}", key, value); + Event::PropertyChange(key, value) + } else { + Event::new_tick() + } + }, + _ => next } } pub fn push(&mut self, event: Event) { - self.pending.push(event); + self.pending.lock().unwrap().push_back(event); + } + + pub fn property(&self, key: &'static str) -> Option { + self.props.lock().unwrap().get(key) } } \ No newline at end of file