Skip to main content

clack_common/
factory.rs

1//! Factory types and associated utilities.
2//!
3//! In CLAP, factories are singleton objects exposed by the plugin file's
4//! [entry point](crate::entry), which can in turn expose various functionalities.
5//!
6//! Each factory type has a standard, unique [identifier](Factory::IDENTIFIERS), which allows hosts
7//! to query plugins for known factory type implementations.
8//!
9//! In Clack, factory implementations are represented by the [`Factory`] trait.
10//!
11//! The main factory type is the [`PluginFactory`](plugin::PluginFactory), which enables hosts to
12//! list all the plugin implementations present in a CLAP file, and then instantiate on of them.
13//!
14
15use core::ffi::CStr;
16
17mod raw;
18pub use raw::RawFactoryPointer;
19
20pub mod plugin;
21
22/// A CLAP factory pointer type.
23///
24/// The role of this trait is to tie a Rust type to a standard CLAP factory identifier and its
25/// matching raw C ABI type.
26/// This is then used by the Clack APIs to always match the correct extension type from its
27/// identifier.
28///
29/// This trait also defines how a factory pointer should be transformed to a reference to the
30/// factory type.
31///
32/// # Safety
33///
34/// The [`IDENTIFIERS`](Factory::IDENTIFIERS) **must** match the official identifier for the given
35/// factory, otherwise the factory data could be misinterpreted, leading to Undefined Behavior.
36///
37/// # Example
38///
39/// This example is a shortened snippet of the implementation of the [`PluginFactory`](plugin::PluginFactory) type.
40///
41/// ```
42/// use clack_common::factory::{Factory, RawFactoryPointer};
43/// use clap_sys::factory::plugin_factory::{clap_plugin_factory, CLAP_PLUGIN_FACTORY_ID};
44/// use core::ffi::CStr;
45///
46/// #[derive(Copy, Clone)]
47/// pub struct PluginFactory<'a>(RawFactoryPointer<'a, clap_plugin_factory>);
48///
49/// // SAFETY: We have checked and ensured that CLAP_PLUGIN_FACTORY_ID is indeed the standard
50/// // identifier for the clap_plugin_factory type.
51/// unsafe impl<'a> Factory<'a> for PluginFactory<'a> {
52///     const IDENTIFIERS: &'static [&'static CStr] = &[CLAP_PLUGIN_FACTORY_ID];
53///     type Raw = clap_plugin_factory;
54///
55///     #[inline]
56///     unsafe fn from_raw(raw: RawFactoryPointer<'a, Self::Raw>) -> Self {
57///         Self(raw)
58///     }
59/// }
60///
61/// impl<'a> PluginFactory<'a> {
62///     pub fn plugin_count(&self) -> u32 {
63///         let Some(get_plugin_count) = self.0.get().get_plugin_count else {
64///             return 0;
65///         };
66///
67///         // SAFETY: this type can only get constructed from a plugin-provided pointer, so the
68///         // CLAP spec enforces that this function pointer is actually valid to call.
69///         unsafe { get_plugin_count(self.0.as_ptr()) }
70///     }
71/// }
72///
73/// ```
74pub unsafe trait Factory<'a>: Copy + Sized + Send + Sync + 'a {
75    /// The standard identifier(s) for this factory type.
76    const IDENTIFIERS: &'static [&'static CStr];
77    /// The type of the raw, C-FFI compatible representation of this factory type.
78    type Raw: Copy + Sized + Send + Sync + 'static;
79
80    /// Returns a handle to the factory from a given factory pointer.
81    ///
82    /// # Safety
83    ///
84    /// The caller must ensure that not only is the factory structure the `raw` pointer points
85    /// to is valid, but also each of its contained fields is also valid for this factory type
86    /// to be usable safely.
87    unsafe fn from_raw(raw: RawFactoryPointer<'a, Self::Raw>) -> Self;
88}