Skip to main content

clack_common/factory/
plugin.rs

1//! The plugin factory type, which is the entry point for hosts to discover and instantiate plugins.
2//!
3//! In CLAP, the Plugin Factory is the main factory type (and at the time of writing, the only
4//! stable standard one). Its purpose is to expose to the host a list of all the plugin types
5//! included in this file, and to allow the host to instantiate them.
6//!
7//! See the [`factory` module documentation](crate::factory) to learn more about factories.
8
9use crate::factory::{Factory, RawFactoryPointer};
10use crate::plugin::PluginDescriptor;
11use clap_sys::factory::plugin_factory::{CLAP_PLUGIN_FACTORY_ID, clap_plugin_factory};
12use std::ffi::CStr;
13use std::iter::FusedIterator;
14
15/// A Plugin Factory.
16///
17/// See the [module documentation](self) to learn more about the role of a Plugin Factory.
18#[derive(Copy, Clone)]
19#[allow(dead_code)]
20pub struct PluginFactory<'a>(RawFactoryPointer<'a, clap_plugin_factory>);
21
22// SAFETY: clap_plugin_factory is the type matching the CLAP_PLUGIN_FACTORY_ID factory ID.
23unsafe impl<'a> Factory<'a> for PluginFactory<'a> {
24    const IDENTIFIERS: &'static [&'static CStr] = &[CLAP_PLUGIN_FACTORY_ID];
25    type Raw = clap_plugin_factory;
26
27    #[inline]
28    unsafe fn from_raw(raw: RawFactoryPointer<'a, Self::Raw>) -> Self {
29        Self(raw)
30    }
31}
32
33impl<'a> PluginFactory<'a> {
34    /// Returns this factory as a raw pointer to its C-FFI compatible raw CLAP structure
35    #[inline]
36    pub const fn raw(&self) -> RawFactoryPointer<'a, clap_plugin_factory> {
37        self.0
38    }
39
40    /// Returns the number of plugin descriptors exposed by this plugin factory.
41    #[inline]
42    pub fn plugin_count(&self) -> u32 {
43        match self.0.get().get_plugin_count {
44            None => 0,
45            // SAFETY: this type ensures the function pointer is valid
46            Some(count) => unsafe { count(self.0.as_ptr()) },
47        }
48    }
49
50    /// Returns the [`PluginDescriptor`s](PluginDescriptor) exposed by this plugin
51    /// factory at a given index, or `None` if there is no plugin descriptor at the given index.
52    ///
53    /// Implementations on the plugin-side *should* return a descriptor for any index strictly less
54    /// than [`plugin_count`](PluginFactory::plugin_count), but this is not a guarantee.
55    ///
56    /// See also the [`plugin_descriptors`](PluginFactory::plugin_descriptors) method for a
57    /// convenient iterator of all the plugin descriptors exposed by this factory.
58    #[inline]
59    pub fn plugin_descriptor(&self, index: u32) -> Option<&'a PluginDescriptor> {
60        let get_plugin_descriptor = self.0.get().get_plugin_descriptor?;
61        // SAFETY: descriptor is guaranteed not to outlive the entry
62        unsafe { get_plugin_descriptor(self.0.as_ptr(), index).as_ref() }
63            // SAFETY: this descriptor is guaranteed to be valid by the spec
64            .map(|d| unsafe { PluginDescriptor::from_raw(d) })
65    }
66
67    /// Returns an iterator of all the [`PluginDescriptor`s](PluginDescriptor) exposed by this
68    /// plugin factory.
69    ///
70    /// For convenience, the [`&PluginFactory`](PluginFactory) type implements the
71    /// [`IntoIterator`] trait, which also returns this iterator.
72    ///
73    /// See also the [`plugin_descriptor`](PluginFactory::plugin_descriptor) method to retrieve
74    /// a plugin descriptor at a specific index.
75    #[inline]
76    pub fn plugin_descriptors(&self) -> PluginDescriptorsIter<'a> {
77        PluginDescriptorsIter {
78            factory: *self,
79            range: 0..self.plugin_count(),
80        }
81    }
82}
83
84/// Returns an iterator of all the [`PluginDescriptor`s](PluginDescriptor) exposed by this plugin
85/// factory.
86impl<'a> IntoIterator for PluginFactory<'a> {
87    type Item = &'a PluginDescriptor;
88    type IntoIter = PluginDescriptorsIter<'a>;
89
90    #[inline]
91    fn into_iter(self) -> Self::IntoIter {
92        self.plugin_descriptors()
93    }
94}
95
96/// An [`Iterator`] over all the [`PluginDescriptor`s](PluginDescriptor) exposed by a
97/// plugin factory.
98///
99/// See the [`PluginFactory::plugin_descriptors`] method that produces this iterator.
100pub struct PluginDescriptorsIter<'a> {
101    factory: PluginFactory<'a>,
102    range: core::ops::Range<u32>,
103}
104
105impl<'a> Iterator for PluginDescriptorsIter<'a> {
106    type Item = &'a PluginDescriptor;
107
108    #[inline]
109    fn next(&mut self) -> Option<Self::Item> {
110        loop {
111            let next = self.range.next()?;
112
113            if let Some(descriptor) = self.factory.plugin_descriptor(next) {
114                return Some(descriptor);
115            }
116        }
117    }
118
119    #[inline]
120    fn size_hint(&self) -> (usize, Option<usize>) {
121        self.range.size_hint()
122    }
123}
124
125impl ExactSizeIterator for PluginDescriptorsIter<'_> {
126    #[inline]
127    fn len(&self) -> usize {
128        self.range.len()
129    }
130}
131
132impl FusedIterator for PluginDescriptorsIter<'_> {}
133
134impl DoubleEndedIterator for PluginDescriptorsIter<'_> {
135    #[inline]
136    fn next_back(&mut self) -> Option<Self::Item> {
137        loop {
138            let next = self.range.next_back()?;
139
140            if let Some(descriptor) = self.factory.plugin_descriptor(next) {
141                return Some(descriptor);
142            }
143        }
144    }
145}