Files
renderbug/src/events.rs
2024-12-15 17:52:17 +01:00

197 lines
4.7 KiB
Rust

use core::fmt::{Debug, Display};
use std::{collections::{LinkedList, VecDeque}, sync::{Arc, Mutex}};
use rgb::Rgb;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Variant {
SignedByte(i8),
Byte(u8),
UInt(u32),
Int(i32),
BigUInt(u64),
BigInt(i64),
Boolean(bool),
String(String),
RGB(Rgb<u8>),
Vec(Vec<Variant>)
}
macro_rules! impl_variant_type {
($type:ty, $var_type:tt) => {
impl From<$type> for Variant {
fn from(value: $type) -> Self {
Variant::$var_type(value)
}
}
impl Into<$type> for Variant {
fn into(self) -> $type {
match self {
Variant::$var_type(value) => value,
_ => panic!(concat!("Expected Variant::", stringify!($var_type), "but got {:?}"), self)
}
}
}
};
}
impl_variant_type!(u8, Byte);
impl_variant_type!(i8, SignedByte);
impl_variant_type!(u32, UInt);
impl_variant_type!(i32, Int);
impl_variant_type!(i64, BigInt);
impl_variant_type!(u64, BigUInt);
impl_variant_type!(bool, Boolean);
impl_variant_type!(String, String);
impl_variant_type!(Rgb<u8>, RGB);
impl_variant_type!(Vec<Variant>, Vec);
impl<'a> From<&'a str> for Variant {
fn from(value: &'a str) -> Self {
Variant::String(value.to_owned())
}
}
#[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 {
pending: Arc<Mutex<VecDeque<Event>>>,
props: Arc<Mutex<Properties>>
}
impl EventBus {
pub fn new() -> Self {
EventBus {
pending: Arc::new(Mutex::new(VecDeque::with_capacity(32))),
props: Arc::new(Mutex::new(Properties::new()))
}
}
pub fn next(&mut self) -> Event {
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.lock().unwrap().push_back(event);
}
pub fn property(&self, key: &'static str) -> Option<Variant> {
self.props.lock().unwrap().get(key)
}
}