Skip to content

Commit

Permalink
Remove event emission and handle comments from review
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonasher committed Jul 28, 2024
1 parent 766f888 commit b1620b3
Showing 1 changed file with 14 additions and 124 deletions.
138 changes: 14 additions & 124 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ use std::{
any::{Any, TypeId},
cmp::Ordering,
collections::{BinaryHeap, HashMap, HashSet, VecDeque},
rc::Rc,
};

use derivative::Derivative;

pub trait Component: Any {
fn init(context: &mut Context);
}

pub trait Plugin: Any {
type DataContainer;

Expand Down Expand Up @@ -116,25 +111,20 @@ impl PlanQueue {
}

type Callback = dyn FnOnce(&mut Context);
type EventHandler<E> = dyn Fn(&mut Context, E);
pub struct Context {
plan_queue: PlanQueue,
callback_queue: VecDeque<Box<Callback>>,
event_handlers: HashMap<TypeId, Box<dyn Any>>,
immediate_event_handlers: HashMap<TypeId, Box<dyn Any>>,
plugin_data: HashMap<TypeId, Box<dyn Any>>,
time: f64,
current_time: f64,
}

impl Context {
pub fn new() -> Context {
Context {
plan_queue: PlanQueue::new(),
callback_queue: VecDeque::new(),
event_handlers: HashMap::new(),
immediate_event_handlers: HashMap::new(),
plugin_data: HashMap::new(),
time: 0.0,
current_time: 0.0,
}
}

Expand All @@ -161,94 +151,26 @@ impl Context {
if !self.plugin_data.contains_key(type_id) {
self.add_plugin::<T>();
}
let data_container = self
.plugin_data
self.plugin_data
.get_mut(type_id)
.unwrap()
.downcast_mut::<T::DataContainer>();
match data_container {
Some(x) => x,
None => panic!("Plugin data container of incorrect type"),
}
.downcast_mut::<T::DataContainer>()
.unwrap()
}

pub fn get_data_container<T: Plugin>(&self) -> Option<&T::DataContainer> {
let type_id = &TypeId::of::<T>();
if !self.plugin_data.contains_key(type_id) {
return None;
}
let data_container = self
.plugin_data
self.plugin_data
.get(type_id)
.unwrap()
.downcast_ref::<T::DataContainer>();
match data_container {
Some(x) => Some(x),
None => panic!("Plugin data container of incorrect type"),
}
}

pub fn get_time(&self) -> f64 {
self.time
}

pub fn add_component<T: Component>(&mut self) {
T::init(self);
}

fn add_handlers<E: Copy + 'static>(
event_handlers: &mut HashMap<TypeId, Box<dyn Any>>,
callback: impl Fn(&mut Context, E) + 'static,
) {
let callback_vec = event_handlers
.entry(TypeId::of::<E>())
.or_insert_with(|| Box::<Vec<Rc<EventHandler<E>>>>::default());
let callback_vec: &mut Vec<Rc<EventHandler<E>>> = callback_vec.downcast_mut().unwrap();
callback_vec.push(Rc::new(callback));
}

pub fn subscribe_to_event<E: Copy + 'static>(
&mut self,
callback: impl Fn(&mut Context, E) + 'static,
) {
Self::add_handlers(&mut self.event_handlers, callback);
.downcast_ref::<T::DataContainer>()
}

pub fn subscribe_immediately_to_event<E: Copy + 'static>(
&mut self,
callback: impl Fn(&mut Context, E) + 'static,
) {
Self::add_handlers(&mut self.immediate_event_handlers, callback);
}

fn collect_callbacks<E: Copy + 'static>(
event_handlers: &HashMap<TypeId, Box<dyn Any>>,
event: E,
) -> Vec<Box<Callback>> {
let mut callbacks_to_return = Vec::<Box<Callback>>::new();
let callback_vec = event_handlers.get(&TypeId::of::<E>());
if let Some(callback_vec) = callback_vec {
let callback_vec: &Vec<Rc<EventHandler<E>>> = callback_vec.downcast_ref().unwrap();
if !callback_vec.is_empty() {
for callback in callback_vec {
let internal_callback = Rc::clone(callback);
callbacks_to_return
.push(Box::new(move |context| internal_callback(context, event)));
}
}
}
callbacks_to_return
}

pub fn release_event<E: Copy + 'static>(&mut self, event: E) {
// Queue standard handlers
for callback in Self::collect_callbacks(&self.event_handlers, event) {
self.queue_callback(callback);
}
// Process immediate handlers
for callback in Self::collect_callbacks(&self.immediate_event_handlers, event) {
callback(self);
}
pub fn get_current_time(&self) -> f64 {
self.current_time
}

pub fn execute(&mut self) {
Expand All @@ -265,7 +187,7 @@ impl Context {
let timed_plan = self.plan_queue.get_next_timed_plan();
match timed_plan {
Some(timed_plan) => {
self.time = timed_plan.time;
self.current_time = timed_plan.time;
(timed_plan.callback)(self);
loop {
let callback = self.callback_queue.pop_front();
Expand All @@ -289,8 +211,6 @@ impl Default for Context {

#[cfg(test)]
mod tests {
use std::{cell::RefCell, rc::Rc};

use super::*;

define_plugin!(ComponentA, u32, 0);
Expand All @@ -299,9 +219,7 @@ mod tests {
fn increment_counter(context: &mut Context) {
*(context.get_data_container_mut::<ComponentA>()) += 1;
}
}

impl Component for ComponentA {
fn init(context: &mut Context) {
context.add_plan(1.0, Self::increment_counter);
}
Expand All @@ -310,45 +228,17 @@ mod tests {
#[test]
fn test_component_and_planning() {
let mut context = Context::new();
context.add_component::<ComponentA>();
assert_eq!(context.get_time(), 0.0);
ComponentA::init(&mut context);
assert_eq!(context.get_current_time(), 0.0);
assert_eq!(*context.get_data_container_mut::<ComponentA>(), 0);
context.execute();
assert_eq!(context.get_time(), 1.0);
assert_eq!(context.get_current_time(), 1.0);
assert_eq!(*context.get_data_container_mut::<ComponentA>(), 1);
let plan_to_cancel = context.add_plan(3.0, ComponentA::increment_counter);
context.add_plan(2.0, ComponentA::increment_counter);
context.cancel_plan(plan_to_cancel);
context.execute();
assert_eq!(context.get_time(), 2.0);
assert_eq!(context.get_current_time(), 2.0);
assert_eq!(*context.get_data_container_mut::<ComponentA>(), 2);
}

#[derive(Copy, Clone)]
struct Event {
pub data: usize,
}
#[test]
fn test_events() {
let mut context = Context::new();

let obs_data = Rc::new(RefCell::new(0));
let immediate_obs_data = Rc::new(RefCell::new(0));

let obs_data_clone = Rc::clone(&obs_data);
context.subscribe_to_event::<Event>(move |_, event| {
*obs_data_clone.borrow_mut() = event.data;
});

let immediate_obs_data_clone = Rc::clone(&immediate_obs_data);
context.subscribe_immediately_to_event::<Event>(move |_, event| {
*immediate_obs_data_clone.borrow_mut() = event.data;
});

context.release_event(Event { data: 1 });
assert_eq!(*immediate_obs_data.borrow(), 1);

context.execute();
assert_eq!(*obs_data.borrow(), 1);
}
}

0 comments on commit b1620b3

Please sign in to comment.