use std::any::Any;
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
pub struct RegistryError {
message: String,
}
impl RegistryError {
pub fn new(message: &str) -> Self {
RegistryError {
message: message.to_string(),
}
}
}
impl std::fmt::Display for RegistryError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Registry error: {}", self.message)
}
}
impl std::error::Error for RegistryError {}
pub trait ComponentRegistry: Send + Sync {
fn register<T: 'static + Send + Sync>(&mut self, name: &str, component: Arc<RwLock<T>>) -> Result<(), RegistryError>;
fn get<T: 'static + Send + Sync>(&self, name: &str) -> Option<Arc<RwLock<T>>>;
fn get_mut<T: 'static + Send + Sync>(&self, name: &str) -> Option<Arc<RwLock<T>>>;
fn contains(&self, name: &str) -> bool;
}
pub struct HTTComponentRegistry {
components: HashMap<String, Arc<RwLock<Box<dyn Any + Send + Sync>>>>,
}
impl Debug for HTTComponentRegistry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HTTComponentRegistry")
.field("components_count", &self.components.len())
.finish()
}
}
impl HTTComponentRegistry {
pub fn new() -> Self {
HTTComponentRegistry {
components: HashMap::new(),
}
}
pub fn len(&self) -> usize {
self.components.len()
}
pub fn is_empty(&self) -> bool {
self.components.is_empty()
}
}
impl ComponentRegistry for HTTComponentRegistry {
fn register<T: 'static + Send + Sync>(&mut self, name: &str, component: Arc<RwLock<T>>) -> Result<(), RegistryError> {
let boxed: Box<dyn Any + Send + Sync> = Box::new(component);
self.components.insert(name.to_string(), Arc::new(RwLock::new(boxed)));
Ok(())
}
fn get<T: 'static + Send + Sync>(&self, name: &str) -> Option<Arc<RwLock<T>>> {
self.components.get(name).and_then(|boxed_any| {
let guard = boxed_any.read().ok()?;
guard.downcast_ref::<Arc<RwLock<T>>>().cloned()
})
}
fn get_mut<T: 'static + Send + Sync>(&self, name: &str) -> Option<Arc<RwLock<T>>> {
self.get(name)
}
fn contains(&self, name: &str) -> bool {
self.components.contains_key(name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug)]
struct TestComponent {
value: i32,
}
#[test]
fn test_registry_operations() {
let mut registry = HTTComponentRegistry::new();
let component = Arc::new(RwLock::new(TestComponent { value: 42 }));
registry.register("test", component).unwrap();
assert!(registry.contains("test"));
assert!(!registry.contains("nonexistent"));
let retrieved = registry.get::<TestComponent>("test").unwrap();
assert_eq!(retrieved.read().unwrap().value, 42);
{
let mut comp = retrieved.write().unwrap();
comp.value = 100;
}
let retrieved_again = registry.get::<TestComponent>("test").unwrap();
assert_eq!(retrieved_again.read().unwrap().value, 100);
}
#[test]
fn test_multiple_components() {
let mut registry = HTTComponentRegistry::new();
registry.register("comp1", Arc::new(RwLock::new(TestComponent { value: 1 }))).unwrap();
registry.register("comp2", Arc::new(RwLock::new(TestComponent { value: 2 }))).unwrap();
registry.register("comp3", Arc::new(RwLock::new(TestComponent { value: 3 }))).unwrap();
assert_eq!(registry.len(), 3);
let comp1 = registry.get::<TestComponent>("comp1").unwrap();
let comp2 = registry.get::<TestComponent>("comp2").unwrap();
let comp3 = registry.get::<TestComponent>("comp3").unwrap();
assert_eq!(comp1.read().unwrap().value, 1);
assert_eq!(comp2.read().unwrap().value, 2);
assert_eq!(comp3.read().unwrap().value, 3);
}
}