reactive_graph_behaviour_model_api/
factory.rs1use std::ops::Deref;
2use std::sync::Arc;
3
4use dashmap::DashMap;
5
6use reactive_graph_reactive_model_api::ReactiveInstance;
7
8use crate::BehaviourCreationError;
9use crate::BehaviourFsm;
10use crate::BehaviourTypeId;
11
12pub trait BehaviourFactory<ID: Clone, T: ReactiveInstance<ID>> {
13 fn create(&self, reactive_instance: T) -> Result<Arc<dyn BehaviourFsm<ID, T> + Send + Sync>, BehaviourCreationError>;
15
16 fn behaviour_ty(&self) -> &BehaviourTypeId;
18}
19
20pub struct BehaviourFactories<ID: Clone, T: ReactiveInstance<ID>>(DashMap<BehaviourTypeId, Arc<dyn BehaviourFactory<ID, T> + Send + Sync>>);
21
22impl<ID: Clone, T: ReactiveInstance<ID>> BehaviourFactories<ID, T> {
23 pub fn new() -> Self {
24 Self(DashMap::new())
25 }
26
27 pub fn factory(self, factory: Arc<dyn BehaviourFactory<ID, T> + Send + Sync>) -> Self {
28 self.0.insert(factory.behaviour_ty().clone(), factory);
29 self
30 }
31
32 pub fn push(&self, factory: Arc<dyn BehaviourFactory<ID, T> + Send + Sync>) {
33 self.0.insert(factory.behaviour_ty().clone(), factory);
34 }
35}
36
37impl<ID: Clone, T: ReactiveInstance<ID>> Deref for BehaviourFactories<ID, T> {
38 type Target = DashMap<BehaviourTypeId, Arc<dyn BehaviourFactory<ID, T> + Send + Sync>>;
39
40 fn deref(&self) -> &Self::Target {
41 &self.0
42 }
43}
44
45impl<ID: Clone, T: ReactiveInstance<ID>> Clone for BehaviourFactories<ID, T> {
46 fn clone(&self) -> Self {
47 let factories = self.0.iter().map(|factory| (factory.key().clone(), factory.value().clone())).collect();
48 Self(factories)
49 }
50}
51
52impl<ID: Clone, T: ReactiveInstance<ID>> Default for BehaviourFactories<ID, T> {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58#[macro_export]
92macro_rules! behaviour_factory {
93 (
94 $factory: ident,
95 $behaviour: ty,
96 $id: ty,
97 $reactive_instance: ty
98 $(, $fn_name:ident, $fn_ident: ident)*
99 ) => {
100 use $crate::BehaviourTypesContainer as ModelBehaviourTypesContainer;
101
102 pub struct $factory {
103 pub ty: $crate::BehaviourTypeId,
104 $(pub $fn_name: $fn_ident,)*
105 }
106
107 impl $factory {
108 pub fn new(ty: $crate::BehaviourTypeId, $($fn_name: $fn_ident)*) -> Self {
109 $factory {
110 ty,
111 $($fn_name,)*
112 }
113 }
114 }
115
116 impl $crate::BehaviourFactory<$id, $reactive_instance> for $factory {
117 fn create(
118 &self,
119 reactive_instance: $reactive_instance,
120 ) -> Result<std::sync::Arc<dyn $crate::BehaviourFsm<$id, $reactive_instance> + Send + Sync>, $crate::BehaviourCreationError> {
121 if reactive_instance.behaves_as(&self.ty) {
123 return Err($crate::BehaviourCreationError::BehaviourAlreadyApplied(self.ty.clone()));
124 }
125 match <$behaviour>::new(reactive_instance, self.ty.clone() $(, self.$fn_name)*) {
126 Ok(state) => {
127 let state = state as std::sync::Arc<dyn $crate::BehaviourFsm<$id, $reactive_instance> + Send + Sync>;
128 Ok(state)
129 }
130 Err(e) => Err(e),
131 }
132 }
133
134 fn behaviour_ty(&self) -> &$crate::BehaviourTypeId {
135 &self.ty
136 }
137 }
138 };
139}