use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use xtalforge_core::Error;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ModuleInfo {
pub name: String,
pub description: String,
pub version: String,
pub parameters: Vec<String>,
}
pub trait Module: std::fmt::Debug + Send + Sync {
fn info(&self) -> ModuleInfo;
fn available(&self) -> bool {
true
}
fn run(&self, _parameters: &serde_json::Value) -> Result<serde_json::Value, Error> {
Err(Error::InvalidInput(format!(
"module {} has no run implementation",
self.info().name
)))
}
}
#[derive(Debug, Default)]
pub struct ModuleRegistry {
modules: BTreeMap<String, Box<dyn Module>>,
}
impl ModuleRegistry {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, module: Box<dyn Module>) -> Result<(), Error> {
let info = module.info();
if info.name.trim().is_empty() {
return Err(Error::InvalidInput(
"a module needs a non-empty name".to_owned(),
));
}
if self.modules.contains_key(&info.name) {
return Err(Error::InvalidInput(format!(
"module {} is already registered",
info.name
)));
}
self.modules.insert(info.name, module);
Ok(())
}
pub fn unregister(&mut self, name: &str) -> bool {
self.modules.remove(name).is_some()
}
#[must_use]
pub fn get(&self, name: &str) -> Option<&dyn Module> {
self.modules.get(name).map(Box::as_ref)
}
#[must_use]
pub fn list(&self) -> Vec<ModuleInfo> {
self.modules.values().map(|module| module.info()).collect()
}
}