reactive_graph_behaviour_model_api/
function.rs

1use std::ops::Deref;
2use std::sync::Arc;
3
4use dashmap::DashMap;
5use dashmap::ReadOnlyView;
6
7use reactive_graph_reactive_model_api::ReactiveInstance;
8
9use crate::BehaviourFactories;
10use crate::BehaviourFactory;
11use crate::BehaviourTypeId;
12use crate::ComponentBehaviourTypeId;
13use crate::ComponentBehaviourTypeIds;
14use crate::EntityBehaviourTypeId;
15use crate::EntityBehaviourTypeIds;
16use crate::RelationBehaviourTypeId;
17use crate::RelationBehaviourTypeIds;
18
19// pub type BehaviourFunction = fn(Value) -> Result<(), BehaviourFunctionError>;
20
21pub type BehaviourFactoryCreator<ID, T, FnType> = fn(&BehaviourTypeId, FnType) -> Arc<dyn BehaviourFactory<ID, T> + Send + Sync + 'static>;
22
23pub struct BehaviourFunctions<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone>(DashMap<BehaviourTypeId, FnType>, BehaviourFactoryCreator<ID, T, FnType>);
24
25impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> BehaviourFunctions<ID, T, FnType> {
26    pub fn new(factory_creator: BehaviourFactoryCreator<ID, T, FnType>) -> Self {
27        Self(DashMap::new(), factory_creator)
28    }
29
30    pub fn with_namespace<N: Into<String>>(
31        namespace: N,
32        factory_creator: BehaviourFactoryCreator<ID, T, FnType>,
33    ) -> NamespacedBehaviourFunctions<ID, T, FnType> {
34        NamespacedBehaviourFunctions::new(namespace, factory_creator)
35    }
36
37    pub fn behaviour_from_ty<B: Into<BehaviourTypeId>>(self, ty: B, f: FnType) -> Self {
38        self.0.insert(ty.into(), f);
39        self
40    }
41    pub fn behaviour<N: Into<String>, TN: Into<String>>(self, namespace: N, type_name: TN, f: FnType) -> Self {
42        self.0.insert(BehaviourTypeId::new_from_type(namespace, type_name), f);
43        self
44    }
45
46    pub fn get(&self) -> BehaviourFunctionsReadOnlyView<ID, T, FnType> {
47        self.into()
48    }
49}
50
51pub struct BehaviourFunctionsReadOnlyView<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone>(
52    ReadOnlyView<BehaviourTypeId, FnType>,
53    BehaviourFactoryCreator<ID, T, FnType>,
54);
55
56impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> BehaviourFunctionsReadOnlyView<ID, T, FnType> {
57    pub fn to_component_behaviour_tys(&self) -> ComponentBehaviourTypeIds {
58        self.keys().map(ComponentBehaviourTypeId::from).collect()
59    }
60
61    pub fn to_entity_behaviour_tys(&self) -> EntityBehaviourTypeIds {
62        self.keys().map(EntityBehaviourTypeId::from).collect()
63    }
64
65    pub fn to_relation_behaviour_tys(&self) -> RelationBehaviourTypeIds {
66        self.keys().map(RelationBehaviourTypeId::from).collect()
67    }
68
69    pub fn get_factories(&self) -> BehaviourFactories<ID, T> {
70        self.0
71            .iter()
72            .fold(BehaviourFactories::new(), |factories, (ty, f)| factories.factory(self.1(ty, f.clone())))
73    }
74}
75
76impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> Deref for BehaviourFunctionsReadOnlyView<ID, T, FnType> {
77    type Target = ReadOnlyView<BehaviourTypeId, FnType>;
78
79    fn deref(&self) -> &Self::Target {
80        &self.0
81    }
82}
83
84impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> From<&BehaviourFunctions<ID, T, FnType>> for BehaviourFunctionsReadOnlyView<ID, T, FnType> {
85    fn from(bf: &BehaviourFunctions<ID, T, FnType>) -> Self {
86        Self(bf.0.clone().into_read_only(), bf.1)
87    }
88}
89
90pub struct NamespacedBehaviourFunctions<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone>(String, BehaviourFunctions<ID, T, FnType>);
91
92impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> NamespacedBehaviourFunctions<ID, T, FnType> {
93    pub fn new<N: Into<String>>(namespace: N, factory_creator: BehaviourFactoryCreator<ID, T, FnType>) -> Self {
94        Self(namespace.into(), BehaviourFunctions::new(factory_creator))
95    }
96
97    pub fn behaviour<TN: Into<String>>(self, type_name: TN, f: FnType) -> Self {
98        self.1.0.insert(BehaviourTypeId::new_from_type(self.0.clone(), type_name), f);
99        self
100    }
101
102    pub fn get(&self) -> BehaviourFunctionsReadOnlyView<ID, T, FnType> {
103        self.1.get()
104    }
105}
106
107impl<ID: Clone, T: ReactiveInstance<ID>, FnType: Clone> From<NamespacedBehaviourFunctions<ID, T, FnType>> for BehaviourFunctions<ID, T, FnType> {
108    fn from(f: NamespacedBehaviourFunctions<ID, T, FnType>) -> Self {
109        f.1
110    }
111}
112
113#[macro_export]
114macro_rules! entity_behaviour_functions {
115    ($ident: ident, $fn_type: ty, $constructor: expr) => {
116        pub static $ident: std::sync::LazyLock<$crate::BehaviourFunctionsReadOnlyView<Uuid, reactive_graph_reactive_model_impl::ReactiveEntity, $fn_type>> =
117            std::sync::LazyLock::new($constructor);
118    };
119}
120
121#[macro_export]
122macro_rules! relation_behaviour_functions {
123    ($ident: ident, $fn_type: ty, $constructor: expr) => {
124        pub static $ident: std::sync::LazyLock<
125            $crate::BehaviourFunctionsReadOnlyView<reactive_graph_graph::RelationTypeId, reactive_graph_reactive_model_impl::ReactiveRelation, $fn_type>,
126        > = std::sync::LazyLock::new($constructor);
127    };
128}