Skip to main content

floria_plugin_sdk/
plugin.rs

1use super::{data::*, utils::*};
2
3use std::sync::*;
4
5/// Dispatch error.
6///
7/// Can contain depiction markup.
8pub type DispatchError = String;
9
10/// Dispatch result.
11pub type DispatchResult = Result<Option<Expression>, DispatchError>;
12
13type Static<StaticT> = LazyLock<Mutex<Option<StaticT>>>;
14
15type Dispatcher = fn(name: String, arguments: Vec<Expression>, call_site: CallSite) -> DispatchResult;
16
17static DISPATCHER_PLUGIN: Static<(String, Dispatcher)> = Static::new(|| Default::default());
18
19/// Register dispatcher plugin.
20pub fn register_dispatcher_plugin(name: String, dispatcher: Dispatcher) -> Result<(), DispatchError> {
21    *DISPATCHER_PLUGIN.lock().map_escape_depiction_error()? = Some((name, dispatcher));
22    Ok(())
23}
24
25/// Get registered dispatcher plugin.
26pub fn registered_dispatcher_plugin() -> Result<(String, Dispatcher), DispatchError> {
27    match DISPATCHER_PLUGIN.lock().map_escape_depiction_error()?.clone() {
28        Some(plugin) => Ok(plugin),
29        None => Err("plugin not registered".into()),
30    }
31}
32
33/// Implement dispatcher plugin.
34#[macro_export]
35macro_rules! impl_dispatcher {
36    ( $plugin_name:expr, $arguments:ident, $call_site:ident, { $( $match:tt )* } ) => {
37        /// Dispatcher.
38        pub struct Dispatcher;
39
40        $crate::export_dispatcher!(Dispatcher);
41
42        impl $crate::dispatch_bindings::Guest for Dispatcher {
43            type ListResource = $crate::data::List;
44            type MapResource = $crate::data::Map;
45            type CustomResource = $crate::data::Custom;
46            type CallResource = $crate::data::Call;
47
48            fn initialize() -> ::std::result::Result<(), $crate::DispatchError> {
49                $crate::register_dispatcher_plugin($plugin_name.into(), Self::dispatch)
50            }
51
52            fn dispatch(
53                name: ::std::string::String,
54                $arguments: ::std::vec::Vec<$crate::data::Expression>,
55                $call_site: $crate::data::CallSite
56            ) -> $crate::DispatchResult {
57                match name.as_str() {
58                    $( $match )*
59                    _ => ::std::result::Result::Err("unsupported function".into()),
60                }
61            }
62        }
63    }
64}
65
66#[allow(unused_imports)]
67pub use impl_dispatcher;