197 lines
4.7 KiB
Rust
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)
|
|
}
|
|
} |