use std::{fs, ops::Deref, path::PathBuf};
use dlopen2::wrapper::Container;
pub mod errors;
pub use dlopen2::wrapper::WrapperApi;
pub use errors::LoaderError;
pub struct Loader<T: WrapperApi> {
container: Container<T>,
_temp_dir: Option<tempfile::TempDir>,
}
impl<T: WrapperApi> Loader<T> {
pub fn load(path: impl Into<PathBuf>) -> Result<Self, LoaderError> {
let path = path.into();
if !path.exists() {
return Err(LoaderError::LibraryNotFound { path });
}
let container = unsafe { Container::load(&path) }
.map_err(|error| LoaderError::from_open_error(path, error))?;
Ok(Self {
container,
_temp_dir: None,
})
}
pub fn load_from_bytes(bytes: &[u8], file_name: &str) -> Result<Self, LoaderError> {
let temp_dir =
tempfile::tempdir().map_err(|source| LoaderError::CreateTempDir { source })?;
let path = temp_dir.path().join(file_name);
fs::write(&path, bytes).map_err(|source| LoaderError::WriteTempLibrary {
path: path.clone(),
source,
})?;
let container = unsafe { Container::<T>::load(&path) }
.map_err(|error| LoaderError::from_open_error(path, error))?;
Ok(Self {
container,
_temp_dir: Some(temp_dir),
})
}
pub fn api(&self) -> &T {
&self.container
}
}
impl<T: WrapperApi> Deref for Loader<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.container
}
}