use std::collections::HashSet;
use crate::ModuleDefinitionBuilder;
#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
#[non_exhaustive]
pub enum PluginError {
#[error("IRONIC_PLUGIN_DUPLICATE: plugin `{0}` is registered more than once")]
Duplicate(&'static str),
#[error("IRONIC_PLUGIN_CONFIGURATION: plugin `{plugin}`: {message}")]
Configuration {
plugin: &'static str,
message: String,
},
}
pub trait Plugin: Send + Sync + 'static {
fn name(&self) -> &'static str;
fn version(&self) -> &'static str;
fn apply(
&self,
module: ModuleDefinitionBuilder,
) -> Result<ModuleDefinitionBuilder, PluginError>;
}
#[derive(Default)]
pub struct PluginRegistry {
plugins: Vec<Box<dyn Plugin>>,
names: HashSet<&'static str>,
}
impl PluginRegistry {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, plugin: impl Plugin) -> Result<&mut Self, PluginError> {
if !self.names.insert(plugin.name()) {
return Err(PluginError::Duplicate(plugin.name()));
}
self.plugins.push(Box::new(plugin));
Ok(self)
}
pub fn apply(
&self,
mut module: ModuleDefinitionBuilder,
) -> Result<ModuleDefinitionBuilder, PluginError> {
for plugin in &self.plugins {
module = plugin.apply(module)?;
}
Ok(module)
}
#[must_use]
pub fn inventory(&self) -> Vec<(&'static str, &'static str)> {
self.plugins
.iter()
.map(|plugin| (plugin.name(), plugin.version()))
.collect()
}
}