use std::{collections::BTreeMap, sync::Arc};
use sim_kernel::{Error, Expr, Result, Symbol};
use crate::{
HostBackend, HostDeviceInventory, HostOpenStream, HostStreamConfigRequest,
missing_capability_card_expr,
};
#[derive(Default)]
pub struct HostBackendRegistry {
backends: BTreeMap<Symbol, Arc<dyn HostBackend>>,
}
impl HostBackendRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register<B>(&mut self, backend: B) -> Result<()>
where
B: HostBackend + 'static,
{
self.register_arc(Arc::new(backend))
}
pub fn register_arc(&mut self, backend: Arc<dyn HostBackend>) -> Result<()> {
let id = backend.info().id().clone();
if self.backends.contains_key(&id) {
return Err(Error::Eval(format!(
"stream host backend {id} is already registered"
)));
}
self.backends.insert(id, backend);
Ok(())
}
pub fn backend(&self, id: &Symbol) -> Option<Arc<dyn HostBackend>> {
self.backends.get(id).cloned()
}
pub fn enumerate(&self) -> Result<Vec<HostDeviceInventory>> {
self.backends
.values()
.map(|backend| backend.enumerate())
.collect()
}
pub fn open(&self, request: HostStreamConfigRequest) -> Result<HostOpenStream> {
let backend = self.backends.get(request.backend()).ok_or_else(|| {
Error::Eval(format!(
"stream host backend {} is not registered",
request.backend()
))
})?;
backend.open(request)
}
pub fn card_exprs(&self) -> Result<Vec<Expr>> {
let mut cards = Vec::new();
for backend in self.backends.values() {
cards.push(backend.info().card_expr());
cards.extend(backend.enumerate()?.card_exprs());
}
Ok(cards)
}
pub fn missing_capability_card(
&self,
backend: &Symbol,
capability: crate::HostBackendCapability,
) -> Expr {
missing_capability_card_expr(backend, capability)
}
}