use crate::entry::PluginEntryError;
use crate::entry::entry_provider::EntryProvider;
use clack_common::entry::EntryDescriptor;
use clack_common::utils::ClapVersion;
use std::ffi::CStr;
use std::ptr::NonNull;
pub struct LoadedEntry<E: EntryProvider>(E);
#[inline]
fn get_entry(e: &impl EntryProvider) -> EntryDescriptor {
unsafe { e.entry_pointer().read() }
}
impl<E: EntryProvider> LoadedEntry<E> {
pub fn load(entry_provider: E, bundle_path: &CStr) -> Result<Self, PluginEntryError> {
let entry = get_entry(&entry_provider);
let plugin_version = ClapVersion::from_raw(entry.clap_version);
if !plugin_version.is_compatible() {
return Err(PluginEntryError::IncompatibleClapVersion { plugin_version });
}
let Some(init) = entry.init else {
return Err(PluginEntryError::IncompatibleClapVersion { plugin_version });
};
let result = unsafe { init(bundle_path.as_ptr()) };
if !result {
return Err(PluginEntryError::EntryInitFailed);
}
Ok(Self(entry_provider))
}
}
impl<E: EntryProvider> Drop for LoadedEntry<E> {
fn drop(&mut self) {
let entry = get_entry(&self.0);
if let Some(deinit) = entry.deinit {
unsafe { deinit() };
}
}
}
pub unsafe trait LoadedEntryDyn: Send + Sync + Send + 'static {
fn entry_pointer(&self) -> NonNull<EntryDescriptor>;
}
unsafe impl<E: EntryProvider> LoadedEntryDyn for LoadedEntry<E> {
#[inline]
fn entry_pointer(&self) -> NonNull<EntryDescriptor> {
self.0.entry_pointer()
}
}