use super::data::Data; use crate::errors::DataError; use abi_stable::{ library::{lib_header_from_path, LibrarySuffix, RawLibrary}, std_types::{RBox, ROk, RStr}, }; use core_extensions::*; use radarg_plugin_interface::{DataLoaderPlugin_TO, PluginId, PluginMod_Ref}; use std::{ collections::HashMap, io, path::{Path, PathBuf}, }; fn compute_plugin_path(base_dir: &Path, base_name: &str) -> io::Result { let debug_dir = base_dir.join("target/debug"); let release_dir = base_dir.join("target/release"); // let debug_dir = "./loaders/target/debug" // .as_ref_::() // .into_::(); // let release_dir = "./loaders/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_dir: &Path, base_name: impl AsRef, ) -> Result<(PluginId, DataLoaderPlugin_TO<'static, RBox<()>>), DataError> { let library_path: PathBuf = compute_plugin_path(base_dir, base_name.as_ref())?; let res = (|| { let header = lib_header_from_path(&library_path)?; header.init_root_module::() })() .unwrap(); 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>(plugin_dir: P) -> Result { let mut this = Self { registered_plugins: HashMap::new(), }; let (id, plugin) = init_plugin(plugin_dir.as_ref(), "etws_loader")?; this.registered_plugins.insert(id, plugin); Ok(this) } pub fn get_plugin(&self, id: &PluginId) -> Option<&DataLoaderPlugin_TO<'static, RBox<()>>> { self.registered_plugins.get(id) } pub fn get_plugin_by_name( &self, name: &str, ) -> Option<&DataLoaderPlugin_TO<'static, RBox<()>>> { self.registered_plugins .iter() .find(|(id, _)| id.named == name) .map(|(_, p)| p) } pub fn try_load_data>(&self, path: P) -> Result, DataError> { let path: &Path = path.as_ref(); let path_rstr = RStr::from(path.to_str().unwrap()); for plugin in self.registered_plugins.values() { if let ROk(result) = plugin.load(path_rstr) { return Ok(result.into_iter().map(|v| v.into()).collect()); } } Err(DataError::FormatError) } pub fn supported_extensions(&self) -> Vec<&str> { let strs = self .registered_plugins .values() .flat_map(|p| p.supported_extensions()) .collect::>(); strs.into_iter().map(|s| s.as_str()).collect() } }