reactive_graph_behaviour_model_api/
function.rs1use 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
19pub 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}