Skip to main content

hx_plugins/
error.rs

1//! Error types for the plugin system.
2
3use std::path::PathBuf;
4
5/// Result type alias for plugin operations.
6pub type Result<T> = std::result::Result<T, PluginError>;
7
8/// Errors that can occur during plugin operations.
9#[derive(Debug, thiserror::Error)]
10pub enum PluginError {
11    /// Failed to load a plugin file.
12    #[error("failed to load plugin at {path}: {message}")]
13    LoadError {
14        path: PathBuf,
15        message: String,
16        #[source]
17        source: Option<Box<dyn std::error::Error + Send + Sync>>,
18    },
19
20    /// Plugin execution failed at runtime.
21    #[error("plugin runtime error in {plugin}: {message}")]
22    RuntimeError {
23        plugin: String,
24        message: String,
25        #[source]
26        source: Option<Box<dyn std::error::Error + Send + Sync>>,
27    },
28
29    /// Plugin execution timed out.
30    #[error("plugin {plugin} timed out during {event}")]
31    Timeout { plugin: String, event: String },
32
33    /// Error calling a plugin API function.
34    #[error("API error in {function}: {message}")]
35    ApiError { function: String, message: String },
36
37    /// Plugin file not found.
38    #[error("plugin not found: {path}")]
39    NotFound { path: PathBuf },
40
41    /// Invalid plugin configuration.
42    #[error("plugin configuration error: {message}")]
43    ConfigError {
44        message: String,
45        #[source]
46        source: Option<Box<dyn std::error::Error + Send + Sync>>,
47    },
48
49    /// Command not found in registered plugins.
50    #[error("unknown command: {name}")]
51    UnknownCommand { name: String },
52
53    /// I/O error during plugin operations.
54    #[error("I/O error: {message}")]
55    Io {
56        message: String,
57        #[source]
58        source: std::io::Error,
59    },
60}
61
62impl PluginError {
63    /// Create a load error.
64    pub fn load(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
65        PluginError::LoadError {
66            path: path.into(),
67            message: message.into(),
68            source: None,
69        }
70    }
71
72    /// Create a load error with a source.
73    pub fn load_with_source(
74        path: impl Into<PathBuf>,
75        message: impl Into<String>,
76        source: impl std::error::Error + Send + Sync + 'static,
77    ) -> Self {
78        PluginError::LoadError {
79            path: path.into(),
80            message: message.into(),
81            source: Some(Box::new(source)),
82        }
83    }
84
85    /// Create a runtime error.
86    pub fn runtime(plugin: impl Into<String>, message: impl Into<String>) -> Self {
87        PluginError::RuntimeError {
88            plugin: plugin.into(),
89            message: message.into(),
90            source: None,
91        }
92    }
93
94    /// Create a timeout error.
95    pub fn timeout(plugin: impl Into<String>, event: impl Into<String>) -> Self {
96        PluginError::Timeout {
97            plugin: plugin.into(),
98            event: event.into(),
99        }
100    }
101
102    /// Create an API error.
103    pub fn api(function: impl Into<String>, message: impl Into<String>) -> Self {
104        PluginError::ApiError {
105            function: function.into(),
106            message: message.into(),
107        }
108    }
109
110    /// Create a not found error.
111    pub fn not_found(path: impl Into<PathBuf>) -> Self {
112        PluginError::NotFound { path: path.into() }
113    }
114
115    /// Create a config error.
116    pub fn config(message: impl Into<String>) -> Self {
117        PluginError::ConfigError {
118            message: message.into(),
119            source: None,
120        }
121    }
122
123    /// Create an unknown command error.
124    pub fn unknown_command(name: impl Into<String>) -> Self {
125        PluginError::UnknownCommand { name: name.into() }
126    }
127
128    /// Create an I/O error.
129    pub fn io(message: impl Into<String>, source: std::io::Error) -> Self {
130        PluginError::Io {
131            message: message.into(),
132            source,
133        }
134    }
135
136    /// Check if this error is recoverable (shouldn't stop the build).
137    pub fn is_recoverable(&self) -> bool {
138        matches!(
139            self,
140            PluginError::RuntimeError { .. } | PluginError::Timeout { .. }
141        )
142    }
143}