use crate::extensions::wrapper::handle_panic;
use crate::factory::error::FactoryWrapperError;
use clack_common::factory::RawFactoryPointer;
use std::panic::AssertUnwindSafe;
use std::ptr::NonNull;
#[repr(C)]
pub struct FactoryWrapper<Raw, F> {
raw: Raw,
inner: F,
}
impl<Raw, F> FactoryWrapper<Raw, F> {
#[inline]
pub const fn new(raw: Raw, inner: F) -> Self {
Self { raw, inner }
}
#[inline]
pub fn as_raw(&self) -> RawFactoryPointer<'_, Raw> {
let self_ptr: NonNull<Self> = self.into();
unsafe { RawFactoryPointer::from_raw(self_ptr.cast()) }
}
#[inline]
pub fn as_raw_ptr(&self) -> *const Raw {
self.as_raw().as_raw().as_ptr()
}
#[inline]
pub const fn factory(&self) -> &F {
&self.inner
}
#[must_use]
pub unsafe fn handle<T>(
raw: *const Raw,
handler: impl FnOnce(&F) -> Result<T, FactoryWrapperError>,
) -> Option<T> {
let factory = unsafe { raw.cast::<Self>().as_ref() };
let result = factory.ok_or(FactoryWrapperError::NullFactoryInstance);
let result = result.and_then(|f| f.handle_panic(handler));
Self::handle_result(result)
}
#[inline]
fn handle_panic<T>(
&self,
handler: impl FnOnce(&F) -> Result<T, FactoryWrapperError>,
) -> Result<T, FactoryWrapperError> {
match handle_panic(AssertUnwindSafe(|| handler(&self.inner))) {
Err(_) => Err(FactoryWrapperError::Panic),
Ok(Err(e)) => Err(e),
Ok(Ok(val)) => Ok(val),
}
}
#[inline]
fn handle_result<T>(result: Result<T, FactoryWrapperError>) -> Option<T> {
match result {
Ok(value) => Some(value),
Err(e) => {
eprintln!("[CLAP_PLUGIN_FACTORY_ERROR] {e}");
None
}
}
}
}