use std::sync::{Mutex, MutexGuard};
use wit::{PluginInput, PluginOutput};
pub mod http_client;
pub type Result<T, E = String> = core::result::Result<T, E>;
pub trait Plugin: Send + Sync {
fn new() -> Self
where
Self: Sized;
fn run_plugin(&self, input: PluginInput) -> Result<PluginOutput, String>;
}
static PLUGIN: Mutex<Option<Box<dyn Plugin>>> = Mutex::new(None);
#[allow(dead_code)]
#[doc(hidden)]
const WORKOSS_API_VERSION: &[u8] = {
let version = concat!(env!("CARGO_PKG_VERSION"));
version.as_bytes()
};
#[cfg(all(target_os = "wasi", target_env = "p2"))]
#[unsafe(link_section = "workoss:api-version")]
#[doc(hidden)]
pub static WORKOSS_API_VERSION_SECTION: [u8; WORKOSS_API_VERSION.len()] = {
let mut arr = [0u8; WORKOSS_API_VERSION.len()];
let mut i = 0;
while i < WORKOSS_API_VERSION.len() {
arr[i] = WORKOSS_API_VERSION[i];
i += 1;
}
arr
};
#[macro_export]
macro_rules! register_plugin {
($plugin_type:ty) => {
#[doc(hidden)]
const WORKOSS_API_SCHEMA: &[u8] = {
let schema = concat!(
"id::",
env!("CARGO_PKG_NAME"),
"\nname::",
env!("CARGO_PKG_NAME"),
"\nversion::",
env!("CARGO_PKG_VERSION"),
"\ndescription::",
env!("CARGO_PKG_DESCRIPTION"),
"\nrepository::",
env!("CARGO_PKG_REPOSITORY"),
"\nauthors::",
env!("CARGO_PKG_AUTHORS"),
);
schema.as_bytes()
};
#[cfg(all(target_os = "wasi", target_env = "p2"))]
#[unsafe(link_section = "workoss:api-schema")]
#[doc(hidden)]
pub static WORKOSS_API_SCHEMA_SECTION: [u8; WORKOSS_API_SCHEMA.len()] = {
let mut arr = [0u8; WORKOSS_API_SCHEMA.len()];
let mut i = 0;
while i < WORKOSS_API_SCHEMA.len() {
arr[i] = WORKOSS_API_SCHEMA[i];
i += 1;
}
arr
};
#[unsafe(export_name = "init-plugin")]
pub extern "C" fn __init_plugin() {
let load_result = extension_api::load_plugin(|| {
Box::new(<$plugin_type as extension_api::Plugin>::new())
});
if load_result.is_err() {
panic!("{}", load_result.unwrap_err());
}
}
};
}
pub fn load_plugin(build_plugin: fn() -> Box<dyn Plugin>) -> Result<(), String> {
let mut binding = PLUGIN.lock();
let plugin = binding.as_mut();
if let Ok(p) = plugin {
**p = Some((build_plugin)());
} else {
return Err("Fail to register plugin".to_string());
}
Ok(())
}
fn plugin<'a>() -> Result<MutexGuard<'a, Option<Box<dyn Plugin>>>, String> {
let plugin = PLUGIN.lock();
if let Ok(p) = plugin {
Ok(p)
} else {
Err("Failed to get plugin".to_string())
}
}
pub mod wit {
wit_bindgen::generate!({
path: "./wit",
world: "extension",
skip: ["init-plugin"],
});
use super::Component;
export!(Component);
}
struct Component;
impl wit::Guest for Component {
#[doc = " 执行扩展"]
fn run_plugin(input: PluginInput) -> Result<PluginOutput, String> {
let plugin = plugin();
if let Ok(p) = plugin {
return p.as_ref().unwrap().run_plugin(input);
}
Err("get plugin error".to_string())
}
}