reactive_graph_behaviour_model_api/
factory.rs

1use 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    /// Creates a new behaviour in the given reactive instance and returns the created state machine.
14    fn create(&self, reactive_instance: T) -> Result<Arc<dyn BehaviourFsm<ID, T> + Send + Sync>, BehaviourCreationError>;
15
16    /// Returns the behaviour type of the behaviour factory.
17    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// impl<ID: Clone, T: ReactiveInstance<ID>> IntoIterator for BehaviourFactories<ID, T> {
59//     type Item = (BehaviourTypeId, Arc<dyn BehaviourFactory<ID, T> + Send + Sync>);
60//     type IntoIter = OwningIter<BehaviourTypeId, Arc<dyn BehaviourFactory<ID, T> + Send + Sync>>;
61//
62//     fn into_iter(self) -> Self::IntoIter {
63//         self.0.iter().map(|factory| (factory.key().clone(), factory.value().clone())).collect();
64//     }
65// }
66
67// impl<ID: Clone, T: ReactiveInstance<ID>> FromIterator<BehaviourFunctionsReadOnlyView<ID, T, FnType>> for BehaviourFactories<ID, T> {
68//     fn from_iter<T: IntoIterator<Item = (BehaviourTypeId, FnType)>>(iter: T) -> Self {
69//         let factories = BehaviourFactories::new();
70//         factories
71//     }
72// }
73//
74// impl<ID: Clone, T: ReactiveInstance<ID>, F> From<BehaviourFunctionsReadOnlyView<F>> for BehaviourFactories<ID, T> {
75//     fn from(fns: BehaviourFunctionsReadOnlyView<F>) -> Self {
76//         let mut factories = BehaviourFactories::new();
77//         // let x = F::new();
78//         fns.iter().map(|(ty, f)| {
79//             let a = Arc::new();
80//             factories.push()
81//             let x = Arc::new(T::new(behaviour_ty.clone(), *f));
82//             BehaviourFactory<ID, T>
83//         }).collect()
84//         for f in fns.iter() {
85//             factories.
86//         }
87//         factories
88//     }
89// }
90
91#[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                // Prevent that the same behaviour can be applied twice / multiple times.
122                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}