1use async_trait::async_trait;
2use std::sync::Arc;
3
4use super::state::{State, StateConfig};
5use super::transaction::Transaction;
6
7#[async_trait]
10pub trait PluginTrait: Send + Sync + Debug {
11 async fn append_transaction(
14 &self,
15 _: &Transaction,
16 _: &State,
17 _: &State,
18 ) -> Option<Transaction> {
19 None
20 }
21 async fn filter_transaction(
24 &self,
25 _: &Transaction,
26 _: &State,
27 ) -> bool {
28 true
29 }
30
31 async fn before_apply_transaction(
33 &self,
34 _tr: &mut Transaction,
35 _state: &State,
36 ) -> Result<(), Box<dyn std::error::Error>> {
37 Ok(())
38 }
39
40 async fn after_apply_transaction(
42 &self,
43 _new_state: &State,
44 _tr: &mut Transaction,
45 _old_state: &State,
46 ) -> Result<(), Box<dyn std::error::Error>> {
47 Ok(())
48 }
49}
50#[async_trait]
53pub trait StateField: Send + Sync + Debug {
54 async fn init(
56 &self,
57 config: &StateConfig,
58 instance: Option<&State>,
59 ) -> PluginState;
60 async fn apply(
63 &self,
64 tr: &Transaction,
65 value: PluginState,
66 old_state: &State,
67 new_state: &State,
68 ) -> PluginState;
69 fn serialize(
71 &self,
72 _value: PluginState,
73 ) -> Option<Vec<u8>> {
74 None
75 }
76 fn deserialize(
78 &self,
79 _value: &Vec<u8>,
80 ) -> Option<PluginState> {
81 None
82 }
83}
84#[derive(Clone, Debug)]
87pub struct PluginSpec {
88 pub state: Option<Arc<dyn StateField>>,
89 pub key: PluginKey,
90 pub tr: Option<Arc<dyn PluginTrait>>,
91}
92
93unsafe impl Send for PluginSpec {}
94unsafe impl Sync for PluginSpec {}
95
96impl PluginSpec {
97 async fn filter_transaction(
99 &self,
100 tr: &Transaction,
101 state: &State,
102 ) -> bool {
103 match &self.tr {
104 Some(filter) => filter.filter_transaction(tr, state).await,
105 None => false,
106 }
107 }
108 async fn append_transaction<'a>(
110 &self,
111 trs: &Transaction,
112 old_state: &State,
113 new_state: &State,
114 ) -> Option<Transaction> {
115 match &self.tr {
116 Some(transaction) => transaction.append_transaction(trs, old_state, new_state).await,
117 None => None,
118 }
119 }
120 pub async fn before_apply_transaction(
121 &self,
122 tr: &mut Transaction,
123 state: &State,
124 ) -> Result<(), Box<dyn std::error::Error>> {
125 if let Some(transaction) = &self.tr {
127 transaction.before_apply_transaction(tr, state).await?;
128 }
129 Ok(())
130 }
131
132 pub async fn after_apply_transaction(
134 &self,
135 new_state: &State,
136 tr: &mut Transaction,
137 old_state: &State,
138 ) -> Result<(), Box<dyn std::error::Error>> {
139 if let Some(transaction) = &self.tr {
141 transaction.after_apply_transaction(new_state, tr, old_state).await?;
142 }
143 Ok(())
144 }
145}
146#[derive(Clone, Debug)]
149pub struct Plugin {
150 pub spec: PluginSpec,
151 pub key: String,
152}
153
154unsafe impl Send for Plugin {}
155unsafe impl Sync for Plugin {}
156
157impl Plugin {
158 pub fn new(spec: PluginSpec) -> Self {
160 let key = spec.key.0.clone();
161
162 Plugin { spec, key }
163 }
164
165 pub fn get_state(
167 &self,
168 state: &State,
169 ) -> Option<PluginState> {
170 state.get_field(&self.key)
171 }
172 pub async fn apply_filter_transaction(
174 &self,
175 tr: &Transaction,
176 state: &State,
177 ) -> bool {
178 self.spec.filter_transaction(tr, state).await
179 }
180
181 pub async fn before_apply_transaction(
183 &self,
184 tr: &mut Transaction,
185 state: &State,
186 ) -> Result<(), Box<dyn std::error::Error>> {
187 self.spec.before_apply_transaction(tr, state).await?;
189 Ok(())
190 }
191
192 pub async fn after_apply_transaction(
194 &self,
195 new_state: &State,
196 tr: &mut Transaction,
197 old_state: &State,
198 ) -> Result<(), Box<dyn std::error::Error>> {
199 self.spec.after_apply_transaction(new_state, tr, old_state).await?;
201 Ok(())
202 }
203
204 pub async fn apply_append_transaction(
206 &self,
207 trs: &Transaction,
208 old_state: &State,
209 new_state: &State,
210 ) -> Option<Transaction> {
211 self.spec.append_transaction(trs, old_state, new_state).await
212 }
213}
214
215pub type PluginState = Arc<dyn std::any::Any + Send + Sync>;
218
219use std::fmt::Debug;
220
221pub type PluginKey = (String, String);