events: implement property events and state management
This commit is contained in:
parent
da2a8f5bfc
commit
f180171ee7
311
src/events.rs
311
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)]
|
use rgb::Rgb;
|
||||||
pub enum InputEvent {
|
|
||||||
PowerOn,
|
|
||||||
PowerOff,
|
|
||||||
NetworkActivity,
|
|
||||||
NetworkOnline,
|
|
||||||
NetworkOffline
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Variant {
|
pub enum Variant {
|
||||||
|
SignedByte(i8),
|
||||||
Byte(u8),
|
Byte(u8),
|
||||||
UInt(u32),
|
UInt(u32),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
BigUInt(u64),
|
BigUInt(u64),
|
||||||
BigInt(i64),
|
BigInt(i64),
|
||||||
Boolean(bool)
|
Boolean(bool),
|
||||||
|
String(String),
|
||||||
|
RGB(Rgb<u8>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
impl From<u8> for Variant {
|
||||||
pub enum Event {
|
fn from(value: u8) -> Self {
|
||||||
ReadyToRock,
|
Variant::Byte(value)
|
||||||
Tick,
|
|
||||||
StartThing(&'static str),
|
|
||||||
StopThing(&'static str),
|
|
||||||
Input(InputEvent),
|
|
||||||
PropertyChange(&'static str, Variant)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SystemState {
|
|
||||||
key: &'static str,
|
|
||||||
value: Variant,
|
|
||||||
values: Vec::<Box<SystemState>>
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Variant> {
|
|
||||||
match self.get_key(key) {
|
|
||||||
None => None,
|
|
||||||
Some(v) => Some(v.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set<V>(&mut self, key: &'static str, value: V) where Variant: From<V> {
|
|
||||||
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<T>(key: &'static str, data: T) -> Self where Variant: From<T> {
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +31,21 @@ impl Into<u8> for Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u64> for Variant {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Variant::BigUInt(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u64> for Variant {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
match self {
|
||||||
|
Variant::BigUInt(b) => b,
|
||||||
|
_ => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<bool> for Variant {
|
impl From<bool> for Variant {
|
||||||
fn from(value: bool) -> Self {
|
fn from(value: bool) -> Self {
|
||||||
Variant::Boolean(value)
|
Variant::Boolean(value)
|
||||||
@ -132,32 +58,197 @@ impl From<i64> for Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u8> for Variant {
|
impl From<u32> for Variant {
|
||||||
fn from(value: u8) -> Self {
|
fn from(value: u32) -> Self {
|
||||||
Variant::Byte(value)
|
Variant::UInt(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Variant {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
Variant::Int(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> 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<Rgb<u8>> for Variant {
|
||||||
|
fn from(value: Rgb<u8>) -> Self {
|
||||||
|
Variant::RGB(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i8> 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<T>(key: &'static str, data: T) -> Self where Variant: From<T> {
|
||||||
|
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<Property>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Variant> {
|
||||||
|
match self.get_key(key) {
|
||||||
|
None => None,
|
||||||
|
Some(v) => Some(v.value.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set<V>(&mut self, key: &'static str, value: V) -> bool where Variant: From<V> {
|
||||||
|
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 {
|
pub struct EventBus {
|
||||||
pending: Vec<Event>
|
pending: Arc<Mutex<VecDeque<Event>>>,
|
||||||
|
props: Arc<Mutex<Properties>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventBus {
|
impl EventBus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
EventBus {
|
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 {
|
pub fn next(&mut self) -> Event {
|
||||||
if self.pending.len() == 0 {
|
let next = self.pending.lock().unwrap().pop_front().unwrap_or(Event::new_tick());
|
||||||
Event::new_tick()
|
|
||||||
} else {
|
match next {
|
||||||
self.pending.pop().unwrap()
|
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) {
|
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<Variant> {
|
||||||
|
self.props.lock().unwrap().get(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user