use std::path::PathBuf;
pub type Result<T> = std::result::Result<T, PluginError>;
#[derive(Debug, thiserror::Error)]
pub enum PluginError {
#[error("failed to load plugin at {path}: {message}")]
LoadError {
path: PathBuf,
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("plugin runtime error in {plugin}: {message}")]
RuntimeError {
plugin: String,
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("plugin {plugin} timed out during {event}")]
Timeout { plugin: String, event: String },
#[error("API error in {function}: {message}")]
ApiError { function: String, message: String },
#[error("plugin not found: {path}")]
NotFound { path: PathBuf },
#[error("plugin configuration error: {message}")]
ConfigError {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("unknown command: {name}")]
UnknownCommand { name: String },
#[error("I/O error: {message}")]
Io {
message: String,
#[source]
source: std::io::Error,
},
}
impl PluginError {
pub fn load(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
PluginError::LoadError {
path: path.into(),
message: message.into(),
source: None,
}
}
pub fn load_with_source(
path: impl Into<PathBuf>,
message: impl Into<String>,
source: impl std::error::Error + Send + Sync + 'static,
) -> Self {
PluginError::LoadError {
path: path.into(),
message: message.into(),
source: Some(Box::new(source)),
}
}
pub fn runtime(plugin: impl Into<String>, message: impl Into<String>) -> Self {
PluginError::RuntimeError {
plugin: plugin.into(),
message: message.into(),
source: None,
}
}
pub fn timeout(plugin: impl Into<String>, event: impl Into<String>) -> Self {
PluginError::Timeout {
plugin: plugin.into(),
event: event.into(),
}
}
pub fn api(function: impl Into<String>, message: impl Into<String>) -> Self {
PluginError::ApiError {
function: function.into(),
message: message.into(),
}
}
pub fn not_found(path: impl Into<PathBuf>) -> Self {
PluginError::NotFound { path: path.into() }
}
pub fn config(message: impl Into<String>) -> Self {
PluginError::ConfigError {
message: message.into(),
source: None,
}
}
pub fn unknown_command(name: impl Into<String>) -> Self {
PluginError::UnknownCommand { name: name.into() }
}
pub fn io(message: impl Into<String>, source: std::io::Error) -> Self {
PluginError::Io {
message: message.into(),
source,
}
}
pub fn is_recoverable(&self) -> bool {
matches!(
self,
PluginError::RuntimeError { .. } | PluginError::Timeout { .. }
)
}
}