Skip to main content

sim_lib_stream_host/
registry.rs

1//! Registry for host stream backends.
2
3use std::{collections::BTreeMap, sync::Arc};
4
5use sim_kernel::{Error, Expr, Result, Symbol};
6
7use crate::{
8    HostBackend, HostDeviceInventory, HostOpenStream, HostStreamConfigRequest,
9    missing_capability_card_expr,
10};
11
12/// Deterministic registry of host stream backends.
13#[derive(Default)]
14pub struct HostBackendRegistry {
15    backends: BTreeMap<Symbol, Arc<dyn HostBackend>>,
16}
17
18impl HostBackendRegistry {
19    /// Creates an empty backend registry.
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    /// Registers a backend by its stable backend id.
25    pub fn register<B>(&mut self, backend: B) -> Result<()>
26    where
27        B: HostBackend + 'static,
28    {
29        self.register_arc(Arc::new(backend))
30    }
31
32    /// Registers an already shared backend.
33    pub fn register_arc(&mut self, backend: Arc<dyn HostBackend>) -> Result<()> {
34        let id = backend.info().id().clone();
35        if self.backends.contains_key(&id) {
36            return Err(Error::Eval(format!(
37                "stream host backend {id} is already registered"
38            )));
39        }
40        self.backends.insert(id, backend);
41        Ok(())
42    }
43
44    /// Returns a registered backend by id.
45    pub fn backend(&self, id: &Symbol) -> Option<Arc<dyn HostBackend>> {
46        self.backends.get(id).cloned()
47    }
48
49    /// Enumerates every registered backend.
50    pub fn enumerate(&self) -> Result<Vec<HostDeviceInventory>> {
51        self.backends
52            .values()
53            .map(|backend| backend.enumerate())
54            .collect()
55    }
56
57    /// Opens a stream using the backend named in the request.
58    pub fn open(&self, request: HostStreamConfigRequest) -> Result<HostOpenStream> {
59        let backend = self.backends.get(request.backend()).ok_or_else(|| {
60            Error::Eval(format!(
61                "stream host backend {} is not registered",
62                request.backend()
63            ))
64        })?;
65        backend.open(request)
66    }
67
68    /// Emits backend, device, and port browse card expressions.
69    pub fn card_exprs(&self) -> Result<Vec<Expr>> {
70        let mut cards = Vec::new();
71        for backend in self.backends.values() {
72            cards.push(backend.info().card_expr());
73            cards.extend(backend.enumerate()?.card_exprs());
74        }
75        Ok(cards)
76    }
77
78    /// Emits a browse card for a missing backend capability.
79    pub fn missing_capability_card(
80        &self,
81        backend: &Symbol,
82        capability: crate::HostBackendCapability,
83    ) -> Expr {
84        missing_capability_card_expr(backend, capability)
85    }
86}