1use std::path::PathBuf;
4
5pub type Result<T> = std::result::Result<T, PluginError>;
7
8#[derive(Debug, thiserror::Error)]
10pub enum PluginError {
11 #[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 #[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 #[error("plugin {plugin} timed out during {event}")]
31 Timeout { plugin: String, event: String },
32
33 #[error("API error in {function}: {message}")]
35 ApiError { function: String, message: String },
36
37 #[error("plugin not found: {path}")]
39 NotFound { path: PathBuf },
40
41 #[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 #[error("unknown command: {name}")]
51 UnknownCommand { name: String },
52
53 #[error("I/O error: {message}")]
55 Io {
56 message: String,
57 #[source]
58 source: std::io::Error,
59 },
60}
61
62impl PluginError {
63 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 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 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 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 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 pub fn not_found(path: impl Into<PathBuf>) -> Self {
112 PluginError::NotFound { path: path.into() }
113 }
114
115 pub fn config(message: impl Into<String>) -> Self {
117 PluginError::ConfigError {
118 message: message.into(),
119 source: None,
120 }
121 }
122
123 pub fn unknown_command(name: impl Into<String>) -> Self {
125 PluginError::UnknownCommand { name: name.into() }
126 }
127
128 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 pub fn is_recoverable(&self) -> bool {
138 matches!(
139 self,
140 PluginError::RuntimeError { .. } | PluginError::Timeout { .. }
141 )
142 }
143}