Files
fidc-backtest-engine/crates/fidc-core/src/event_bus.rs
2026-04-23 21:51:45 -07:00

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);
}
}
}