mod utils; use crate::{config::Config, errors::PluginError}; use abi_stable::{ external_types::crossbeam_channel::{self, RReceiver, RSender}, library::{lib_header_from_path, LibraryError, LibrarySuffix, RawLibrary}, sabi_trait::prelude::TD_Opaque, std_types::{RBox, RErr, ROk, RResult, RSome, RStr, RString, RVec}, }; use core_extensions::*; use radarg_plugin_interface::{Plugin, PluginId, PluginMod_Ref, Plugin_TO}; use std::{ collections::{HashMap, VecDeque}, io, mem, path::{Path, PathBuf}, sync::{Arc, Mutex}, }; fn compute_plugin_path(base_name: &str) -> io::Result { let debug_dir = "./etws_loader/target/debug" .as_ref_::() .into_::(); let release_dir = "./etws_loader/target/release" .as_ref_::() .into_::(); let debug_path = RawLibrary::path_in_directory(&debug_dir, base_name, LibrarySuffix::NoSuffix); let release_path = RawLibrary::path_in_directory(&release_dir, base_name, LibrarySuffix::NoSuffix); match (debug_path.exists(), release_path.exists()) { (false, false) => debug_path, (true, false) => debug_path, (false, true) => release_path, (true, true) => { if debug_path.metadata()?.modified()? < release_path.metadata()?.modified()? { release_path } else { debug_path } } } .piped(Ok) } pub fn init_plugin( base_name: impl AsRef, ) -> Result<(PluginId, Plugin_TO<'static, RBox<()>>), PluginError> { let library_path: PathBuf = compute_plugin_path(base_name.as_ref())?; let res = (|| { let header = lib_header_from_path(&library_path)?; header.init_root_module::() })()?; let plugin_constructor = res.new(); let new_id = PluginId { named: base_name.as_ref().to_owned().into(), instance: 0, }; let plugin = plugin_constructor(new_id.clone()).unwrap(); Ok((new_id, plugin)) } pub struct PluginManager { registered_plugins: HashMap>>, } impl PluginManager { pub fn new() -> Result { use crate::CONFIG; let mut this = Self { registered_plugins: HashMap::new(), }; for (plugin_name, config) in CONFIG.lock().unwrap().plugins.iter() { if let Ok((id, p)) = init_plugin(plugin_name.to_owned()) { println!("Loaded plugin: {}", plugin_name); this.registered_plugins.insert(id, p); } } Ok(this) } pub fn get_plugin(&self, id: &PluginId) -> Option<&Plugin_TO<'static, RBox<()>>> { self.registered_plugins.get(id) } pub fn get_plugin_by_name(&self, name: &str) -> Option<&Plugin_TO<'static, RBox<()>>> { self.registered_plugins .iter() .find(|(id, _)| id.named == name) .map(|(_, p)| p) } }