1use std::{collections::HashMap, sync::Arc};
13
14use super::{
15 BspContext, condition::ConditionFn, def::NodeDef, error::BspError, merge::Merger,
16 node::BspNode, value::BspValue,
17};
18
19pub type NodeFactory<S> =
22 Box<dyn Fn(&NodeDef, &BspContext) -> Result<Box<dyn BspNode<S>>, BspError> + Send + Sync>;
23
24pub type ValueFactory = Arc<dyn Fn(&serde_json::Value) -> BspValue + Send + Sync>;
27
28pub fn default_value_factory(value: &serde_json::Value) -> BspValue {
36 match value {
37 serde_json::Value::Bool(b) => BspValue::new(*b),
38 serde_json::Value::Number(n) => {
39 if let Some(i) = n.as_i64() {
40 BspValue::new(i)
41 } else if let Some(u) = n.as_u64() {
42 BspValue::new(u)
43 } else {
44 BspValue::new(n.as_f64().unwrap_or_default())
45 }
46 }
47 serde_json::Value::String(s) => BspValue::new(s.clone()),
48 other => BspValue::new(other.clone()),
49 }
50}
51
52pub struct NodeRegistry<S = ()> {
58 pub(crate) factories: HashMap<String, NodeFactory<S>>,
60 pub(crate) conditions: HashMap<String, ConditionFn<S>>,
62 pub(crate) mergers: HashMap<String, Arc<dyn Merger<S>>>,
64 pub(crate) value_factory: ValueFactory,
66}
67
68impl<S> Default for NodeRegistry<S> {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl<S> NodeRegistry<S> {
75 #[must_use]
77 pub fn new() -> Self {
78 Self {
79 factories: HashMap::new(),
80 conditions: HashMap::new(),
81 mergers: HashMap::new(),
82 value_factory: Arc::new(default_value_factory),
83 }
84 }
85
86 pub fn register_node(
88 &mut self,
89 type_name: impl Into<String>,
90 factory: impl Fn(&NodeDef, &BspContext) -> Result<Box<dyn BspNode<S>>, BspError>
91 + Send
92 + Sync
93 + 'static,
94 ) {
95 self.factories.insert(type_name.into(), Box::new(factory));
96 }
97
98 pub fn register_condition(
100 &mut self,
101 name: impl Into<String>,
102 f: impl Fn(&S, &super::run::ValueStore) -> bool + Send + Sync + 'static,
103 ) {
104 self.conditions.insert(name.into(), Arc::new(f));
105 }
106
107 pub fn register_merger<M: Merger<S> + 'static>(&mut self, name: impl Into<String>, merger: M) {
109 self.mergers.insert(name.into(), Arc::new(merger));
110 }
111
112 pub fn register_value_factory(
120 &mut self,
121 factory: impl Fn(&serde_json::Value) -> BspValue + Send + Sync + 'static,
122 ) {
123 self.value_factory = Arc::new(factory);
124 }
125
126 #[must_use]
128 pub fn contains_node(&self, type_name: &str) -> bool {
129 self.factories.contains_key(type_name)
130 }
131
132 #[must_use]
134 pub fn contains_condition(&self, name: &str) -> bool {
135 self.conditions.contains_key(name)
136 }
137
138 #[must_use]
140 pub fn contains_merger(&self, name: &str) -> bool {
141 self.mergers.contains_key(name)
142 }
143
144 #[must_use]
146 pub fn node_type_names(&self) -> Vec<&str> {
147 self.factories.keys().map(String::as_str).collect()
148 }
149
150 #[must_use]
151 fn with_mut(mut self, f: impl FnOnce(&mut Self)) -> Self {
152 f(&mut self);
153 self
154 }
155
156 #[must_use]
158 pub fn with_node(
159 self,
160 type_name: impl Into<String>,
161 factory: impl Fn(&NodeDef, &BspContext) -> Result<Box<dyn BspNode<S>>, BspError>
162 + Send
163 + Sync
164 + 'static,
165 ) -> Self {
166 self.with_mut(|r| r.register_node(type_name, factory))
167 }
168
169 #[must_use]
171 pub fn with_condition(
172 self,
173 name: impl Into<String>,
174 f: impl Fn(&S, &super::run::ValueStore) -> bool + Send + Sync + 'static,
175 ) -> Self {
176 self.with_mut(|r| r.register_condition(name, f))
177 }
178
179 #[must_use]
181 pub fn with_merger<M: Merger<S> + 'static>(self, name: impl Into<String>, merger: M) -> Self {
182 self.with_mut(|r| r.register_merger(name, merger))
183 }
184
185 #[must_use]
187 pub fn with_value_factory(
188 self,
189 factory: impl Fn(&serde_json::Value) -> BspValue + Send + Sync + 'static,
190 ) -> Self {
191 self.with_mut(|r| r.register_value_factory(factory))
192 }
193}