Skip to main content

clack_common/
extensions.rs

1//! Traits and associated utilities to handle and implement CLAP extensions.
2//!
3//! See the documentation of the `extensions` module in the `clack-plugin` and `clack-host` crates
4//! for implementation examples.
5
6use std::ffi::CStr;
7
8mod raw;
9pub use raw::{RawExtension, RawExtensionImplementation};
10
11/// A marker struct that represents extensions to be implemented by the plugin side.
12///
13/// See [`Extension::ExtensionSide`].
14#[derive(Copy, Clone)]
15pub struct PluginExtensionSide;
16
17/// A marker struct that represents extensions to be implemented by the host side.
18///
19/// See [`Extension::ExtensionSide`].
20#[derive(Copy, Clone)]
21pub struct HostExtensionSide;
22
23/// An extension side marker: either [`PluginExtensionSide`] or [`HostExtensionSide`].
24///
25/// See [`Extension::ExtensionSide`].
26pub trait ExtensionSide: private::Sealed + Copy + Sized {}
27impl ExtensionSide for PluginExtensionSide {}
28impl ExtensionSide for HostExtensionSide {}
29
30mod private {
31    use super::*;
32
33    pub trait Sealed {}
34    impl Sealed for PluginExtensionSide {}
35    impl Sealed for HostExtensionSide {}
36}
37
38/// A type representing a CLAP extension pointer.
39///
40/// The role of this trait is to tie a type to a standard CLAP extension identifier.
41/// This is then used by the Clack APIs to always match the correct extension type from its
42/// identifier.
43///
44/// This trait also defines how an extension pointer should be transformed to a reference to the
45/// extension type.
46///
47/// # Safety
48///
49/// The [`IDENTIFIER`](Extension::IDENTIFIERS) **must** match the official identifier for the given
50/// extension, otherwise the extension data could be misinterpreted, leading to Undefined Behavior.
51pub unsafe trait Extension: Copy + Sized + Send + Sync + 'static {
52    /// The standard identifier for this extension.
53    const IDENTIFIERS: &'static [&'static CStr];
54    /// Whether this is a host extension or a plugin extension
55    type ExtensionSide: ExtensionSide;
56
57    /// Returns an instance of the extension from a given extension pointer.
58    ///
59    /// # Safety
60    /// Callers must ensure the extension pointer points to the extension type that matches
61    /// [`Self::IDENTIFIERS`].
62    unsafe fn from_raw(raw: RawExtension<Self::ExtensionSide>) -> Self;
63}
64
65/// Provides an implementation of this extension for a given type `I` (typically either a host or
66/// plugin structure).
67///
68/// # Safety
69///
70/// Implementors MUST ensure the value of the [`IMPLEMENTATION`](Self::IMPLEMENTATION) pointer
71/// is correct: it must point to a type that is `#[repr(C)]` *and* ABI-compatible with the
72/// CLAP extension struct.
73pub unsafe trait ExtensionImplementation<I>: Extension {
74    /// The implementation of the extension.
75    const IMPLEMENTATION: RawExtensionImplementation;
76}