use sim_kernel::{Cx, Error, Result, Symbol};
use std::{
collections::BTreeMap,
sync::{Arc, Mutex, OnceLock},
};
use crate::{EvalSite, LineDriver, ServerAddress};
pub struct ResolvedAddress {
pub site: Arc<dyn EvalSite>,
pub selected_codec: Symbol,
pub supported_codecs: Vec<Symbol>,
}
pub type AddressResolver =
fn(&mut Cx, &ServerAddress, &[Symbol]) -> Result<Option<ResolvedAddress>>;
pub type LineDriverFactory = fn(&mut Cx, &sim_kernel::Expr) -> Result<Option<Box<dyn LineDriver>>>;
pub(crate) fn address_resolvers() -> &'static Mutex<BTreeMap<String, AddressResolver>> {
static RESOLVERS: OnceLock<Mutex<BTreeMap<String, AddressResolver>>> = OnceLock::new();
RESOLVERS.get_or_init(|| Mutex::new(BTreeMap::new()))
}
pub(crate) fn line_driver_factories() -> &'static Mutex<BTreeMap<String, LineDriverFactory>> {
static FACTORIES: OnceLock<Mutex<BTreeMap<String, LineDriverFactory>>> = OnceLock::new();
FACTORIES.get_or_init(|| Mutex::new(BTreeMap::new()))
}
pub fn register_address_resolver(kind: Symbol, resolver: AddressResolver) -> Result<()> {
let mut resolvers = address_resolvers()
.lock()
.map_err(|_| Error::HostError("address resolver registry mutex poisoned".to_owned()))?;
resolvers.insert(kind.to_string(), resolver);
Ok(())
}
pub fn register_line_driver(name: Symbol, factory: LineDriverFactory) -> Result<()> {
let mut factories = line_driver_factories()
.lock()
.map_err(|_| Error::HostError("line driver registry mutex poisoned".to_owned()))?;
factories.insert(name.to_string(), factory);
Ok(())
}