use super::support::*;
pub trait ProviderFactory: Send + Sync {
fn kind(&self) -> &'static str;
fn deserialize(&self, config: serde_json::Value) -> Result<ProviderComponents, String>;
}
#[derive(Clone, Default)]
pub struct ProviderRegistry {
factories: BTreeMap<&'static str, Arc<dyn ProviderFactory>>,
}
impl ProviderRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, factory: Arc<dyn ProviderFactory>) {
self.factories.insert(factory.kind(), factory);
}
pub fn build_from_spec(&self, spec: &ProviderSpec) -> Result<ProviderComponents, String> {
let factory = self.factories.get(spec.kind.as_str()).ok_or_else(|| {
format!(
"provider `{}` is not registered. Call `lash_core::register_provider_factory` at startup.",
spec.kind
)
})?;
factory.deserialize(spec.config.clone())
}
pub fn factory(&self, kind: &str) -> Option<&Arc<dyn ProviderFactory>> {
self.factories.get(kind)
}
}
static PROVIDER_REGISTRY: LazyLock<RwLock<ProviderRegistry>> =
LazyLock::new(|| RwLock::new(ProviderRegistry::new()));
pub fn register_provider_factory(factory: Arc<dyn ProviderFactory>) {
PROVIDER_REGISTRY.write().unwrap().register(factory);
}
pub fn build_provider(spec: &ProviderSpec) -> Result<ProviderComponents, String> {
PROVIDER_REGISTRY.read().unwrap().build_from_spec(spec)
}
pub fn provider_factory(kind: &str) -> Option<Arc<dyn ProviderFactory>> {
PROVIDER_REGISTRY.read().unwrap().factory(kind).cloned()
}