1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
use std::any::Any;
use std::collections::HashMap;
use crate::errors::PluginError;
/// A runner function, which takes action data and plugin data, returning a
/// `Result<R, Box<dyn Error>>`.
// A: some stuff the specific action gets
// dyn Any + Send: the plugin options
// R: the return type
pub type Runner<A, R> = Box<
dyn Fn(&A, &(dyn Any + Send + Sync)) -> Result<R, Box<dyn std::error::Error + Send + Sync>>
+ Send
+ Sync,
>;
/// A trait for the interface for a plugin action, which abstracts whether it's
/// a functional or a control action.
///
/// `R2` here denotes the return type of the entire plugin series. For instance,
/// functional plugins return a `HashMap` of the results of each plugin.
pub trait PluginAction<A, R, R2>: Send + Sync {
/// Runs the action. This takes data that the action should expect, along
/// with a map of plugins to their data.
///
/// If any of the underlying plugins whose runners are executed by this
/// function return an error, the first error will be returned
/// immediately, and further execution will be aborted. Since
/// execution may happen in an arbitrary order, there is no guarantee that
/// the same error will be thrown each time if multiple plugins are
/// being used.
fn run(
&self,
action_data: A,
plugin_data: &HashMap<String, Box<dyn Any + Send + Sync>>,
) -> Result<R2, PluginError>;
/// Registers a plugin that takes this action.
///
/// # Panics
/// If the action type can only be taken by one plugin, and one has already
/// been set, this may panic (e.g. for control actions), as this is a
/// critical, unrecoverable error that Perseus doesn't need to do anything
/// after. If a plugin registration fails, we have to assume that all
/// work in the engine may be not what the user intended.
fn register_plugin(
&mut self,
name: &str,
runner: impl Fn(&A, &(dyn Any + Send + Sync)) -> Result<R, Box<dyn std::error::Error + Send + Sync>>
+ Send
+ Sync
+ 'static,
);
/// Same as `.register_plugin()`, but takes a prepared runner in a `Box`.
fn register_plugin_box(&mut self, name: &str, runner: Runner<A, R>);
}