solverforge_core/domain/supply/
mod.rs1mod anchor;
16mod inverse;
17mod list_state;
18
19pub use anchor::{AnchorVariableDemand, AnchorVariableSupply, ExternalizedAnchorVariableSupply};
20pub use inverse::{
21 ExternalizedSingletonInverseVariableSupply, SingletonInverseVariableDemand,
22 SingletonInverseVariableSupply,
23};
24pub use list_state::{
25 ElementPosition, IndexVariableSupply, InverseVariableSupply, ListVariableStateDemand,
26 ListVariableStateSupply,
27};
28
29use std::any::{Any, TypeId};
30use std::collections::HashMap;
31use std::sync::Arc;
32
33pub trait Supply: Send + Sync + 'static {
44 fn supply_type_id(&self) -> TypeId {
46 TypeId::of::<Self>()
47 }
48}
49
50pub trait SupplyDemand: Send + Sync + 'static {
55 type Output: Supply;
57
58 fn demand_key(&self) -> DemandKey;
62
63 fn create_supply(&self) -> Self::Output;
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct DemandKey {
73 pub supply_type: TypeId,
75 pub variable_name: String,
77 pub discriminator: Option<String>,
79}
80
81impl DemandKey {
82 pub fn new<S: Supply>(variable_name: impl Into<String>) -> Self {
84 Self {
85 supply_type: TypeId::of::<S>(),
86 variable_name: variable_name.into(),
87 discriminator: None,
88 }
89 }
90
91 pub fn with_discriminator<S: Supply>(
93 variable_name: impl Into<String>,
94 discriminator: impl Into<String>,
95 ) -> Self {
96 Self {
97 supply_type: TypeId::of::<S>(),
98 variable_name: variable_name.into(),
99 discriminator: Some(discriminator.into()),
100 }
101 }
102}
103
104#[derive(Default)]
114pub struct SupplyManager {
115 supplies: HashMap<DemandKey, Arc<dyn Any + Send + Sync>>,
117}
118
119impl SupplyManager {
120 pub fn new() -> Self {
122 Self {
123 supplies: HashMap::new(),
124 }
125 }
126
127 pub fn demand<D: SupplyDemand>(&mut self, demand: &D) -> Arc<D::Output> {
132 let key = demand.demand_key();
133
134 if let Some(supply) = self.supplies.get(&key) {
135 supply
137 .clone()
138 .downcast::<D::Output>()
139 .expect("Supply type mismatch")
140 } else {
141 let supply = Arc::new(demand.create_supply());
142 self.supplies
143 .insert(key, supply.clone() as Arc<dyn Any + Send + Sync>);
144 supply
145 }
146 }
147
148 pub fn register<S: Supply>(&mut self, key: DemandKey, supply: Arc<S>) {
153 self.supplies
154 .insert(key, supply as Arc<dyn Any + Send + Sync>);
155 }
156
157 pub fn get<S: Supply>(&self, key: &DemandKey) -> Option<Arc<S>> {
161 self.supplies
162 .get(key)
163 .and_then(|s| s.clone().downcast::<S>().ok())
164 }
165
166 pub fn remove(&mut self, key: &DemandKey) -> bool {
168 self.supplies.remove(key).is_some()
169 }
170
171 pub fn clear(&mut self) {
173 self.supplies.clear();
174 }
175
176 pub fn len(&self) -> usize {
178 self.supplies.len()
179 }
180
181 pub fn is_empty(&self) -> bool {
183 self.supplies.is_empty()
184 }
185}
186
187impl std::fmt::Debug for SupplyManager {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 f.debug_struct("SupplyManager")
190 .field("supply_count", &self.supplies.len())
191 .finish()
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 struct TestSupply {
201 value: i32,
202 }
203
204 impl Supply for TestSupply {}
205
206 struct TestDemand {
208 variable_name: String,
209 initial_value: i32,
210 }
211
212 impl SupplyDemand for TestDemand {
213 type Output = TestSupply;
214
215 fn demand_key(&self) -> DemandKey {
216 DemandKey::new::<TestSupply>(&self.variable_name)
217 }
218
219 fn create_supply(&self) -> TestSupply {
220 TestSupply {
221 value: self.initial_value,
222 }
223 }
224 }
225
226 #[test]
227 fn test_supply_manager_demand_creates_supply() {
228 let mut manager = SupplyManager::new();
229 let demand = TestDemand {
230 variable_name: "test_var".to_string(),
231 initial_value: 42,
232 };
233
234 let supply = manager.demand(&demand);
235 assert_eq!(supply.value, 42);
236 }
237
238 #[test]
239 fn test_supply_manager_demand_returns_cached() {
240 let mut manager = SupplyManager::new();
241 let demand = TestDemand {
242 variable_name: "test_var".to_string(),
243 initial_value: 42,
244 };
245
246 let supply1 = manager.demand(&demand);
247 let supply2 = manager.demand(&demand);
248
249 assert!(Arc::ptr_eq(&supply1, &supply2));
251 }
252
253 #[test]
254 fn test_supply_manager_different_variables() {
255 let mut manager = SupplyManager::new();
256
257 let demand1 = TestDemand {
258 variable_name: "var1".to_string(),
259 initial_value: 1,
260 };
261 let demand2 = TestDemand {
262 variable_name: "var2".to_string(),
263 initial_value: 2,
264 };
265
266 let supply1 = manager.demand(&demand1);
267 let supply2 = manager.demand(&demand2);
268
269 assert_eq!(supply1.value, 1);
270 assert_eq!(supply2.value, 2);
271 assert!(!Arc::ptr_eq(&supply1, &supply2));
272 }
273
274 #[test]
275 fn test_supply_manager_register() {
276 let mut manager = SupplyManager::new();
277 let key = DemandKey::new::<TestSupply>("registered_var");
278 let supply = Arc::new(TestSupply { value: 100 });
279
280 manager.register(key.clone(), supply);
281
282 let retrieved = manager.get::<TestSupply>(&key);
283 assert!(retrieved.is_some());
284 assert_eq!(retrieved.unwrap().value, 100);
285 }
286
287 #[test]
288 fn test_supply_manager_remove() {
289 let mut manager = SupplyManager::new();
290 let demand = TestDemand {
291 variable_name: "to_remove".to_string(),
292 initial_value: 1,
293 };
294
295 let _ = manager.demand(&demand);
296 assert_eq!(manager.len(), 1);
297
298 let key = demand.demand_key();
299 assert!(manager.remove(&key));
300 assert_eq!(manager.len(), 0);
301 }
302
303 #[test]
304 fn test_supply_manager_clear() {
305 let mut manager = SupplyManager::new();
306
307 let demand1 = TestDemand {
308 variable_name: "var1".to_string(),
309 initial_value: 1,
310 };
311 let demand2 = TestDemand {
312 variable_name: "var2".to_string(),
313 initial_value: 2,
314 };
315
316 let _ = manager.demand(&demand1);
317 let _ = manager.demand(&demand2);
318 assert_eq!(manager.len(), 2);
319
320 manager.clear();
321 assert!(manager.is_empty());
322 }
323
324 #[test]
325 fn test_demand_key_with_discriminator() {
326 let key1 = DemandKey::new::<TestSupply>("var");
327 let key2 = DemandKey::with_discriminator::<TestSupply>("var", "disc");
328
329 assert_ne!(key1, key2);
330 assert!(key1.discriminator.is_none());
331 assert_eq!(key2.discriminator, Some("disc".to_string()));
332 }
333}