devalang_core/core/plugin/
loader.rs

1use std::path::Path;
2use serde::Deserialize;
3
4#[derive(Debug, Deserialize, Clone)]
5pub struct PluginInfo {
6    pub name: String,
7    pub version: Option<String>,
8    pub description: Option<String>,
9    pub author: Option<String>,
10}
11
12#[derive(Debug, Deserialize, Clone)]
13pub struct PluginFile {
14    pub plugin: PluginInfo,
15}
16
17pub fn load_plugin(name: &str) -> Result<(PluginInfo, Vec<u8>), String> {
18    let root = Path::new(env!("CARGO_MANIFEST_DIR"));
19    let plugin_dir = root.join(".deva").join("plugin").join(name);
20    let toml_path = plugin_dir.join("plugin.toml");
21    let wasm_path = plugin_dir.join(format!("{}_bg.wasm", name));
22
23    if !toml_path.exists() {
24        return Err(format!("❌ Plugin file not found: {}", toml_path.display()));
25    }
26    if !wasm_path.exists() {
27        return Err(format!("❌ Plugin wasm not found: {}", wasm_path.display()));
28    }
29
30    let toml_content = std::fs::read_to_string(&toml_path)
31        .map_err(|e| format!("Failed to read '{}': {}", toml_path.display(), e))?;
32    let plugin_file: PluginFile = toml::from_str(&toml_content)
33        .map_err(|e| format!("Failed to parse '{}': {}", toml_path.display(), e))?;
34
35    let wasm_bytes = std::fs::read(&wasm_path)
36        .map_err(|e| format!("Failed to read '{}': {}", wasm_path.display(), e))?;
37
38    Ok((plugin_file.plugin, wasm_bytes))
39}
40
41pub fn load_plugin_from_uri(uri: &str) -> Result<(PluginInfo, Vec<u8>), String> {
42    if !uri.starts_with("devalang://plugin/") {
43        return Err("Invalid plugin URI".into());
44    }
45
46    let name = uri.trim_start_matches("devalang://plugin/");
47    load_plugin(name)
48}