use crate::{bench::BenchResult, bench_id::BenchId};
use std::any::Any;
#[derive(Debug, Clone, Copy)]
pub enum PluginEvents<'a> {
GroupBenchNumIters {
num_iter: usize,
},
GroupNumIters {
num_iter: usize,
},
GroupStart {
runner_name: Option<&'a str>,
group_name: Option<&'a str>,
output_value_column_title: &'static str,
},
GroupStop {
runner_name: Option<&'a str>,
group_name: Option<&'a str>,
results: &'a [BenchResult],
output_value_column_title: &'static str,
},
BenchStart {
bench_id: &'a BenchId,
},
BenchStop {
bench_id: &'a BenchId,
duration: u64,
},
}
pub trait EventListener: Any {
fn prio(&self) -> u32 {
u32::MAX / 2
}
fn name(&self) -> &'static str;
fn on_event(&mut self, event: PluginEvents);
fn as_any(&mut self) -> &mut dyn Any;
}
pub struct PluginManager {
listeners: Vec<(String, Box<dyn EventListener>)>,
}
impl PluginManager {
pub fn new() -> Self {
Self {
listeners: Vec::new(),
}
}
pub fn replace_plugin<L: EventListener + 'static>(&mut self, listener: L) -> &mut Self {
self.remove_plugin_by_name(listener.name());
self.add_plugin(listener);
self
}
pub fn add_plugin<L: EventListener + 'static>(&mut self, listener: L) -> &mut Self {
self.listeners
.push((listener.name().to_owned(), Box::new(listener)));
self.listeners.sort_by_key(|(_, l)| l.prio());
self
}
pub fn add_plugin_if_absent<L: EventListener + 'static>(&mut self, listener: L) -> &mut Self {
if self.get_plugins(listener.name()).is_some() {
return self;
}
self.add_plugin(listener);
self
}
pub fn get_plugins(&mut self, name: &str) -> Option<&mut Box<dyn EventListener>> {
self.listeners
.iter_mut()
.find(|(n, _)| n == name)
.map(|(_, l)| l)
}
pub fn downcast_plugin<T: 'static>(&mut self, name: &str) -> Option<&mut T> {
self.get_plugins(name)?.as_any().downcast_mut::<T>()
}
pub fn remove_plugin_by_name(&mut self, name: &str) {
self.listeners.retain(|(n, _)| n != name);
}
pub fn emit(&mut self, event: PluginEvents) {
if matches!(event, PluginEvents::BenchStop { .. }) {
for (_, listener) in self.listeners.iter_mut().rev() {
listener.on_event(event);
}
} else {
for (_, listener) in self.listeners.iter_mut() {
listener.on_event(event);
}
}
}
}
impl Default for PluginManager {
fn default() -> Self {
Self::new()
}
}