indradb_plugin_host/
decl.rs

1use std::collections::HashMap;
2use std::fmt;
3
4use crate::errors::Error;
5
6/// Represents the rustc compiler version and the plugin interface version.
7/// When a plugin is loaded, the `VersionInfo` of the server is
8/// cross-referenced against the `VersionInfo` exported by the plugin. If they
9/// don't match, the plugin fails.
10///
11/// The rustc version must match exactly because rust doesn't expose a stable
12/// ABI, and there is a risk of it changing in any version. The plugin
13/// interface version is also exposed to allow for changes to the interface in
14/// the future. If the interface is changed, this value should be incremented.
15#[derive(Debug, Eq, PartialEq)]
16pub struct VersionInfo {
17    /// The version of rustc used to compile. This must match because rust
18    /// doesn't expose a stable ABI, and there is a risk of it changing in any
19    /// version.
20    pub rustc: String,
21    /// The plugin interface version is also exposed to allow for changes to
22    /// the interface in the future.
23    pub plugin_interface: u8,
24}
25
26impl Default for VersionInfo {
27    fn default() -> Self {
28        Self {
29            rustc: env!("RUSTC_VERSION").to_string(),
30            // If the interface is changed, this value should be incremented.
31            plugin_interface: 1,
32        }
33    }
34}
35
36impl fmt::Display for VersionInfo {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        write!(f, "rustc={}, plugin_interface={}", self.rustc, self.plugin_interface)
39    }
40}
41
42/// Plugins should implement this trait.
43pub trait Plugin: Send + Sync + 'static {
44    /// Executes the plugin. Returns JSON that will be sent back to the
45    /// calling client.
46    ///
47    /// # Arguments
48    /// * `txn`: An IndraDB datastore transaction.
49    /// * `arg`: The argument from the calling client.
50    fn call<'a>(
51        &self,
52        txn: &mut (dyn indradb::Transaction<'a> + 'a),
53        arg: indradb::Json,
54    ) -> Result<indradb::Json, Error>;
55}
56
57/// A declaration of a plugin.
58pub struct PluginDeclaration {
59    pub version_info: VersionInfo,
60    pub entries: HashMap<String, Box<dyn Plugin>>,
61}
62
63/// Libraries use this macro to register their plugins.
64#[macro_export]
65macro_rules! register_plugins {
66    ( $indradb_interface_version:expr, $( $name:expr, $t:expr ),* ) => {
67        #[doc(hidden)]
68        #[no_mangle]
69        pub unsafe extern "C" fn register() -> $crate::PluginDeclaration {
70            use std::collections::HashMap;
71            let mut entries = HashMap::new();
72            $(
73                {
74                    let t: Box<dyn $crate::Plugin> = $t();
75                    entries.insert($name.to_string(), t);
76                }
77            )*
78            $crate::PluginDeclaration {
79                version_info: $crate::VersionInfo::default(),
80                entries,
81            }
82        }
83    };
84}