139 lines
3.4 KiB
Rust
139 lines
3.4 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use crate::events::{ProcessEvent, ProcessEventKind};
|
|
|
|
type ProcessEventListener = Box<dyn FnMut(&ProcessEvent)>;
|
|
|
|
pub trait BacktestProcessMod {
|
|
fn name(&self) -> &str;
|
|
fn install(&mut self, bus: &mut ProcessEventBus);
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct BacktestProcessModLoader {
|
|
modules: Vec<Box<dyn BacktestProcessMod>>,
|
|
}
|
|
|
|
impl BacktestProcessModLoader {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn register<M>(&mut self, module: M)
|
|
where
|
|
M: BacktestProcessMod + 'static,
|
|
{
|
|
self.modules.push(Box::new(module));
|
|
}
|
|
|
|
pub fn module_names(&self) -> Vec<String> {
|
|
self.modules
|
|
.iter()
|
|
.map(|module| module.name().to_string())
|
|
.collect()
|
|
}
|
|
|
|
pub fn install_all(&mut self, bus: &mut ProcessEventBus) -> Vec<String> {
|
|
self.modules
|
|
.iter_mut()
|
|
.map(|module| {
|
|
let name = module.name().to_string();
|
|
module.install(bus);
|
|
name
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub fn install_enabled(
|
|
&mut self,
|
|
bus: &mut ProcessEventBus,
|
|
enabled_names: &[String],
|
|
) -> Vec<String> {
|
|
if enabled_names.is_empty() {
|
|
return self.install_all(bus);
|
|
}
|
|
self.modules
|
|
.iter_mut()
|
|
.filter(|module| {
|
|
enabled_names
|
|
.iter()
|
|
.any(|name| name.eq_ignore_ascii_case(module.name()))
|
|
})
|
|
.map(|module| {
|
|
let name = module.name().to_string();
|
|
module.install(bus);
|
|
name
|
|
})
|
|
.collect()
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct ProcessEventBus {
|
|
listeners: BTreeMap<ProcessEventKind, Vec<ProcessEventListener>>,
|
|
any_listeners: Vec<ProcessEventListener>,
|
|
}
|
|
|
|
impl ProcessEventBus {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn add_listener<F>(&mut self, kind: ProcessEventKind, listener: F)
|
|
where
|
|
F: FnMut(&ProcessEvent) + 'static,
|
|
{
|
|
self.listeners
|
|
.entry(kind)
|
|
.or_default()
|
|
.push(Box::new(listener));
|
|
}
|
|
|
|
pub fn prepend_listener<F>(&mut self, kind: ProcessEventKind, listener: F)
|
|
where
|
|
F: FnMut(&ProcessEvent) + 'static,
|
|
{
|
|
self.listeners
|
|
.entry(kind)
|
|
.or_default()
|
|
.insert(0, Box::new(listener));
|
|
}
|
|
|
|
pub fn add_any_listener<F>(&mut self, listener: F)
|
|
where
|
|
F: FnMut(&ProcessEvent) + 'static,
|
|
{
|
|
self.any_listeners.push(Box::new(listener));
|
|
}
|
|
|
|
pub fn install_mod<M>(&mut self, module: &mut M)
|
|
where
|
|
M: BacktestProcessMod,
|
|
{
|
|
module.install(self);
|
|
}
|
|
|
|
pub fn install_mod_loader(&mut self, loader: &mut BacktestProcessModLoader) -> Vec<String> {
|
|
loader.install_all(self)
|
|
}
|
|
|
|
pub fn install_enabled_mods(
|
|
&mut self,
|
|
loader: &mut BacktestProcessModLoader,
|
|
enabled_names: &[String],
|
|
) -> Vec<String> {
|
|
loader.install_enabled(self, enabled_names)
|
|
}
|
|
|
|
pub fn publish(&mut self, event: &ProcessEvent) {
|
|
if let Some(listeners) = self.listeners.get_mut(&event.kind) {
|
|
for listener in listeners {
|
|
listener(event);
|
|
}
|
|
}
|
|
for listener in &mut self.any_listeners {
|
|
listener(event);
|
|
}
|
|
}
|
|
}
|