Skip to main content

clack_plugin/factory/
error.rs

1use clap_sys::ext::log::{
2    CLAP_LOG_ERROR, CLAP_LOG_HOST_MISBEHAVING, CLAP_LOG_PLUGIN_MISBEHAVING, clap_log_severity,
3};
4use std::error::Error;
5use std::fmt::{Display, Formatter};
6
7/// Errors raised by a [`FactoryWrapper`](super::wrapper::FactoryWrapper).
8#[derive(Debug)]
9#[non_exhaustive]
10pub enum FactoryWrapperError {
11    /// The factory raw pointer was null.
12    NullFactoryInstance,
13    /// An unexpectedly null raw pointer was encountered.
14    ///
15    /// The given string may contain more information about which pointer was found to be null.
16    NulPtr(&'static str),
17    /// The plugin factory panicked during a function call.
18    Panic,
19    /// A generic or custom error of a given severity.
20    Error(clap_log_severity, Box<dyn Error>),
21}
22
23impl FactoryWrapperError {
24    /// Returns the severity of this error.
25    ///
26    /// This is mainly useful for logging.
27    ///
28    /// # Example
29    ///
30    /// ```
31    /// use clap_sys::ext::log::CLAP_LOG_PLUGIN_MISBEHAVING;
32    /// use clack_plugin::extensions::wrapper::PluginWrapperError;
33    /// let error = PluginWrapperError::Panic;
34    ///
35    /// assert_eq!(error.severity(), CLAP_LOG_PLUGIN_MISBEHAVING);
36    /// ```
37    pub fn severity(&self) -> clap_log_severity {
38        match self {
39            FactoryWrapperError::Panic => CLAP_LOG_PLUGIN_MISBEHAVING,
40            FactoryWrapperError::Error(s, _) => *s,
41            _ => CLAP_LOG_HOST_MISBEHAVING,
42        }
43    }
44
45    /// Returns a closure that maps an error to a [`FactoryWrapperError::Error`] error of a given
46    /// severity.
47    ///
48    /// This is a useful helper method when paired with [`Result::map_err`].
49    ///
50    /// # Example
51    /// ```
52    /// use clap_sys::ext::log::CLAP_LOG_PLUGIN_MISBEHAVING;
53    /// use clack_plugin::extensions::wrapper::PluginWrapperError;
54    ///
55    /// let x: Result<(), _> = Err(std::env::VarError::NotPresent); // Some random error type
56    /// let clap_error = x.map_err(PluginWrapperError::with_severity(CLAP_LOG_PLUGIN_MISBEHAVING));
57    ///
58    /// assert_eq!(clap_error.unwrap_err().severity(), CLAP_LOG_PLUGIN_MISBEHAVING);
59    /// ```
60    #[inline]
61    pub fn with_severity<E: 'static + Error>(
62        severity: clap_log_severity,
63    ) -> impl Fn(E) -> FactoryWrapperError {
64        move |e| FactoryWrapperError::Error(severity, Box::new(e))
65    }
66}
67
68impl Display for FactoryWrapperError {
69    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70        use FactoryWrapperError::*;
71        match self {
72            NullFactoryInstance => f.write_str(
73                "Plugin factory method was called with null clap_plugin_factory pointer",
74            ),
75            NulPtr(ptr_name) => {
76                write!(
77                    f,
78                    "Plugin factory method was called with null {ptr_name} pointer"
79                )
80            }
81            Error(_, e) => std::fmt::Display::fmt(e, f),
82            Panic => f.write_str("Plugin factory panicked"),
83        }
84    }
85}
86
87impl<E: Error + 'static> From<E> for FactoryWrapperError {
88    fn from(value: E) -> Self {
89        Self::Error(CLAP_LOG_ERROR, Box::new(value))
90    }
91}