use crate::runtime::{add_node_handler, MessageHandler, NodeBase, Result, RobomotionError};
use async_trait::async_trait;
use parking_lot::RwLock;
use std::collections::HashMap;
#[async_trait]
pub trait NodeFactory: Send + Sync + 'static {
async fn on_create(&self, config: &[u8]) -> Result<()>;
}
lazy_static::lazy_static! {
static ref FACTORIES: RwLock<HashMap<String, Box<dyn NodeFactory>>> = RwLock::new(HashMap::new());
}
pub fn register_node_factory(name: &str, factory: Box<dyn NodeFactory>) {
FACTORIES.write().insert(name.to_string(), factory);
}
pub fn get_node_factory(name: &str) -> Option<Box<dyn NodeFactory>> {
None
}
pub fn has_node_factory(name: &str) -> bool {
FACTORIES.read().contains_key(name)
}
pub async fn create_node(name: &str, config: &[u8]) -> Result<()> {
let factories = FACTORIES.read();
let factory = factories
.get(name)
.ok_or_else(|| RobomotionError::FactoryNotFound(name.to_string()))?;
factory.on_create(config).await
}
pub struct GenericNodeFactory<F>
where
F: Fn() -> Box<dyn MessageHandler> + Send + Sync + 'static,
{
creator: F,
}
impl<F> GenericNodeFactory<F>
where
F: Fn() -> Box<dyn MessageHandler> + Send + Sync + 'static,
{
pub fn new(creator: F) -> Self {
Self { creator }
}
}
#[async_trait]
impl<F> NodeFactory for GenericNodeFactory<F>
where
F: Fn() -> Box<dyn MessageHandler> + Send + Sync + 'static,
{
async fn on_create(&self, config: &[u8]) -> Result<()> {
let node_base: NodeBase = serde_json::from_slice(config)?;
let mut handler = (self.creator)();
add_node_handler(node_base, handler);
Ok(())
}
}