use crate::Error;
use crate::plugin::Plugin;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug, Default)]
pub struct Registry {
plugins: HashMap<String, Arc<dyn Plugin>>,
}
impl Registry {
pub fn new() -> Self {
Self {
plugins: HashMap::new(),
}
}
pub fn register(&mut self, plugin: Arc<dyn Plugin>) -> crate::Result<()> {
let name = plugin.name().to_string();
if self.plugins.contains_key(&name) {
return Err(Error::Plugin(format!(
"Plugin '{}' is already registered",
name
)));
}
self.plugins.insert(name, plugin);
Ok(())
}
pub fn register_replace(&mut self, plugin: Arc<dyn Plugin>) {
let name = plugin.name().to_string();
self.plugins.insert(name, plugin);
}
pub fn register_replace_with_name(&mut self, name: &str, plugin: Arc<dyn Plugin>) {
self.plugins.insert(name.to_string(), plugin);
}
pub fn get(&self, name: &str) -> Option<Arc<dyn Plugin>> {
self.plugins.get(name).cloned()
}
pub fn contains(&self, name: &str) -> bool {
self.plugins.contains_key(name)
}
pub fn remove(&mut self, name: &str) -> Option<Arc<dyn Plugin>> {
self.plugins.remove(name)
}
pub fn len(&self) -> usize {
self.plugins.len()
}
pub fn is_empty(&self) -> bool {
self.plugins.is_empty()
}
pub fn plugin_names(&self) -> Vec<String> {
self.plugins.keys().cloned().collect()
}
pub fn clear(&mut self) {
self.plugins.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::plugin::{Context, Plugin};
use async_trait::async_trait;
#[derive(Debug)]
struct TestPlugin {
name: String,
}
#[async_trait]
impl Plugin for TestPlugin {
async fn execute(&self, _ctx: &mut Context) -> crate::Result<()> {
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
#[test]
fn test_registry_creation() {
let registry = Registry::new();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
}
#[test]
fn test_register_plugin() {
let mut registry = Registry::new();
let plugin = Arc::new(TestPlugin {
name: "test".to_string(),
});
assert!(registry.register(plugin).is_ok());
assert!(!registry.is_empty());
assert_eq!(registry.len(), 1);
assert!(registry.contains("test"));
}
#[test]
fn test_register_duplicate() {
let mut registry = Registry::new();
let plugin1 = Arc::new(TestPlugin {
name: "test".to_string(),
});
let plugin2 = Arc::new(TestPlugin {
name: "test".to_string(),
});
assert!(registry.register(plugin1).is_ok());
assert!(registry.register(plugin2).is_err());
}
#[test]
fn test_register_replace() {
let mut registry = Registry::new();
let plugin1 = Arc::new(TestPlugin {
name: "test".to_string(),
});
let plugin2 = Arc::new(TestPlugin {
name: "test".to_string(),
});
registry.register_replace(plugin1);
assert_eq!(registry.len(), 1);
registry.register_replace(plugin2);
assert_eq!(registry.len(), 1);
}
#[test]
fn test_get_plugin() {
let mut registry = Registry::new();
let plugin = Arc::new(TestPlugin {
name: "test".to_string(),
});
registry.register(plugin).unwrap();
let retrieved = registry.get("test");
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().name(), "test");
assert!(registry.get("nonexistent").is_none());
}
#[test]
fn test_remove_plugin() {
let mut registry = Registry::new();
let plugin = Arc::new(TestPlugin {
name: "test".to_string(),
});
registry.register(plugin).unwrap();
assert!(registry.contains("test"));
let removed = registry.remove("test");
assert!(removed.is_some());
assert!(!registry.contains("test"));
assert!(registry.is_empty());
assert!(registry.remove("test").is_none());
}
#[test]
fn test_plugin_names() {
let mut registry = Registry::new();
registry
.register(Arc::new(TestPlugin {
name: "plugin1".to_string(),
}))
.unwrap();
registry
.register(Arc::new(TestPlugin {
name: "plugin2".to_string(),
}))
.unwrap();
let names = registry.plugin_names();
assert_eq!(names.len(), 2);
assert!(names.contains(&"plugin1".to_string()));
assert!(names.contains(&"plugin2".to_string()));
}
#[test]
fn test_clear() {
let mut registry = Registry::new();
registry
.register(Arc::new(TestPlugin {
name: "plugin1".to_string(),
}))
.unwrap();
registry
.register(Arc::new(TestPlugin {
name: "plugin2".to_string(),
}))
.unwrap();
assert_eq!(registry.len(), 2);
registry.clear();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
}
}