use std::collections::HashMap;
use std::any::{Any, TypeId};
use crate::error::{Result, Error};
pub trait Extension: Send + Sync {
fn name(&self) -> &str;
fn initialize(&mut self) -> Result<()>;
fn shutdown(&mut self) -> Result<()>;
fn is_enabled(&self) -> bool;
fn set_enabled(&mut self, enabled: bool);
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
pub struct ExtensionRegistry {
extensions: HashMap<String, Box<dyn Extension>>,
type_map: HashMap<TypeId, String>,
}
impl Default for ExtensionRegistry {
fn default() -> Self {
Self::new()
}
}
impl ExtensionRegistry {
pub fn new() -> Self {
Self {
extensions: HashMap::new(),
type_map: HashMap::new(),
}
}
pub fn register<E: Extension + 'static>(&mut self, extension: E) -> Result<()> {
let name = extension.name().to_string();
let type_id = TypeId::of::<E>();
if self.extensions.contains_key(&name) {
return Err(Error::ExtensionError(format!(
"Extension with name '{}' is already registered", name
)));
}
self.type_map.insert(type_id, name.clone());
self.extensions.insert(name, Box::new(extension));
Ok(())
}
pub fn get(&self, name: &str) -> Option<&dyn Extension> {
self.extensions.get(name).map(|ext| ext.as_ref())
}
pub fn get_mut(&mut self, name: &str) -> Option<&mut dyn Extension> {
if let Some(ext) = self.extensions.get_mut(name) {
Some(&mut **ext)
} else {
None
}
}
pub fn get_by_type<E: Extension + 'static>(&self) -> Option<&E> {
let type_id = TypeId::of::<E>();
if let Some(name) = self.type_map.get(&type_id) {
if let Some(ext) = self.extensions.get(name) {
return ext.as_any().downcast_ref::<E>();
}
}
None
}
pub fn get_mut_by_type<E: Extension + 'static>(&mut self) -> Option<&mut E> {
let type_id = TypeId::of::<E>();
if let Some(name) = self.type_map.get(&type_id).cloned() {
if let Some(ext) = self.extensions.get_mut(&name) {
return ext.as_any_mut().downcast_mut::<E>();
}
}
None
}
pub fn remove(&mut self, name: &str) -> Option<Box<dyn Extension>> {
self.extensions.remove(name)
}
pub fn initialize_all(&mut self) -> Result<()> {
for (name, ext) in &mut self.extensions {
if let Err(e) = ext.initialize() {
return Err(Error::ExtensionError(format!(
"Failed to initialize extension '{}': {}", name, e
)));
}
}
Ok(())
}
pub fn shutdown_all(&mut self) -> Result<()> {
for (name, ext) in &mut self.extensions {
if let Err(e) = ext.shutdown() {
return Err(Error::ExtensionError(format!(
"Failed to shutdown extension '{}': {}", name, e
)));
}
}
Ok(())
}
}