1use std::collections::HashMap;
7use aether_core::node::DspNode;
8use crate::ParamDef;
9
10pub type NodeFactory = fn() -> Box<dyn DspNode>;
12
13#[derive(Clone)]
15pub struct NodeEntry {
16 pub type_name: &'static str,
17 pub param_defs: &'static [ParamDef],
18 pub factory: NodeFactory,
19}
20
21pub struct NodeRegistry {
23 entries: HashMap<&'static str, NodeEntry>,
24}
25
26impl NodeRegistry {
27 pub fn new() -> Self {
28 Self { entries: HashMap::new() }
29 }
30
31 pub fn register(&mut self, entry: NodeEntry) {
33 self.entries.insert(entry.type_name, entry);
34 }
35
36 pub fn create(&self, type_name: &str) -> Option<Box<dyn DspNode>> {
38 self.entries.get(type_name).map(|e| (e.factory)())
39 }
40
41 pub fn list(&self) -> Vec<&'static str> {
43 let mut names: Vec<_> = self.entries.keys().copied().collect();
44 names.sort_unstable();
45 names
46 }
47
48 pub fn param_defs(&self, type_name: &str) -> Option<&[ParamDef]> {
50 self.entries.get(type_name).map(|e| e.param_defs)
51 }
52
53 pub fn len(&self) -> usize { self.entries.len() }
54 pub fn is_empty(&self) -> bool { self.entries.is_empty() }
55}
56
57impl Default for NodeRegistry {
58 fn default() -> Self { Self::new() }
59}
60
61#[macro_export]
68macro_rules! register_node {
69 ($registry:expr, $ty:ty) => {{
70 use $crate::{AetherNodeMeta, DspProcess, into_node};
71 $registry.register($crate::node::NodeEntry {
72 type_name: <$ty as AetherNodeMeta>::type_name(),
73 param_defs: <$ty as AetherNodeMeta>::param_defs(),
74 factory: || {
75 let node = <$ty as Default>::default();
76 into_node(node)
77 },
78 });
79 }};
80}