Skip to main content

sim_lib_server/
registries.rs

1use sim_kernel::{Cx, Error, Result, Symbol};
2use std::{
3    collections::BTreeMap,
4    sync::{Arc, Mutex, OnceLock},
5};
6
7use crate::{EvalSite, LineDriver, ServerAddress};
8
9/// Outcome of resolving a [`ServerAddress`] to a concrete eval site and codec set.
10pub struct ResolvedAddress {
11    /// Eval site that handles frames for the resolved address.
12    pub site: Arc<dyn EvalSite>,
13    /// Codec selected for the connection.
14    pub selected_codec: Symbol,
15    /// Codecs the resolved site supports.
16    pub supported_codecs: Vec<Symbol>,
17}
18
19/// Function that resolves a [`ServerAddress`] (with offered codecs) to a [`ResolvedAddress`].
20pub type AddressResolver =
21    fn(&mut Cx, &ServerAddress, &[Symbol]) -> Result<Option<ResolvedAddress>>;
22/// Function that builds a [`LineDriver`] from a configuration expression.
23pub type LineDriverFactory = fn(&mut Cx, &sim_kernel::Expr) -> Result<Option<Box<dyn LineDriver>>>;
24
25pub(crate) fn address_resolvers() -> &'static Mutex<BTreeMap<String, AddressResolver>> {
26    static RESOLVERS: OnceLock<Mutex<BTreeMap<String, AddressResolver>>> = OnceLock::new();
27    RESOLVERS.get_or_init(|| Mutex::new(BTreeMap::new()))
28}
29
30pub(crate) fn line_driver_factories() -> &'static Mutex<BTreeMap<String, LineDriverFactory>> {
31    static FACTORIES: OnceLock<Mutex<BTreeMap<String, LineDriverFactory>>> = OnceLock::new();
32    FACTORIES.get_or_init(|| Mutex::new(BTreeMap::new()))
33}
34
35/// Registers an [`AddressResolver`] under an address `kind` in the global resolver registry.
36pub fn register_address_resolver(kind: Symbol, resolver: AddressResolver) -> Result<()> {
37    let mut resolvers = address_resolvers()
38        .lock()
39        .map_err(|_| Error::HostError("address resolver registry mutex poisoned".to_owned()))?;
40    resolvers.insert(kind.to_string(), resolver);
41    Ok(())
42}
43
44/// Registers a [`LineDriverFactory`] under `name` in the global line-driver registry.
45pub fn register_line_driver(name: Symbol, factory: LineDriverFactory) -> Result<()> {
46    let mut factories = line_driver_factories()
47        .lock()
48        .map_err(|_| Error::HostError("line driver registry mutex poisoned".to_owned()))?;
49    factories.insert(name.to_string(), factory);
50    Ok(())
51}