use async_trait::async_trait;
use std::sync::Arc;
use super::state::{State, StateConfig};
use super::transaction::Transaction;
#[async_trait]
pub trait PluginTrait: Send + Sync + Debug {
async fn append_transaction(
&self,
_: &[Transaction],
_: &State,
_: &State,
) -> Option<Transaction> {
None
}
async fn filter_transaction(
&self,
_: &Transaction,
_: &State,
) -> bool {
true
}
}
#[async_trait]
pub trait StateField: Send + Sync + Debug {
async fn init(
&self,
config: &StateConfig,
instance: Option<&State>,
) -> PluginState;
async fn apply(
&self,
tr: &Transaction,
value: PluginState,
old_state: &State,
new_state: &State,
) -> PluginState;
fn serialize(
&self,
_value: PluginState,
) -> Option<Vec<u8>> {
None
}
fn deserialize(
&self,
_value: &Vec<u8>,
) -> Option<PluginState> {
None
}
}
#[derive(Clone, Debug)]
pub struct PluginSpec {
pub state: Option<Arc<dyn StateField>>,
pub key: PluginKey,
pub tr: Option<Arc<dyn PluginTrait>>,
pub priority: i32,
}
unsafe impl Send for PluginSpec {}
unsafe impl Sync for PluginSpec {}
impl PluginSpec {
async fn filter_transaction(
&self,
tr: &Transaction,
state: &State,
) -> bool {
match &self.tr {
Some(filter) => filter.filter_transaction(tr, state).await,
None => false,
}
}
async fn append_transaction<'a>(
&self,
trs: &'a [Transaction],
old_state: &State,
new_state: &State,
) -> Option<Transaction> {
match &self.tr {
Some(transaction) => {
transaction.append_transaction(trs, old_state, new_state).await
},
None => None,
}
}
}
#[derive(Clone, Debug)]
pub struct Plugin {
pub spec: PluginSpec,
pub key: String,
}
unsafe impl Send for Plugin {}
unsafe impl Sync for Plugin {}
impl Plugin {
pub fn new(spec: PluginSpec) -> Self {
let key = spec.key.0.clone();
Plugin { spec, key }
}
pub fn get_state(
&self,
state: &State,
) -> Option<PluginState> {
state.get_field(&self.key)
}
pub async fn apply_filter_transaction(
&self,
tr: &Transaction,
state: &State,
) -> bool {
self.spec.filter_transaction(tr, state).await
}
pub async fn apply_append_transaction(
&self,
trs: &[Transaction],
old_state: &State,
new_state: &State,
) -> Option<Transaction> {
self.spec.append_transaction(trs, old_state, new_state).await
}
}
pub type PluginState = Arc<dyn std::any::Any + Send + Sync>;
use std::fmt::Debug;
pub type PluginKey = (String, String);