1use std::fmt;
8
9pub type Result<T, E = PluginError> = std::result::Result<T, E>;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum PluginError {
13 Unknown {
15 name: String,
16 available: Vec<String>,
17 },
18 Config { plugin: String, message: String },
20 Runtime { plugin: String, message: String },
22 Host(String),
24}
25
26impl PluginError {
27 pub fn unknown<S: Into<String>>(
33 name: impl Into<String>,
34 available: impl IntoIterator<Item = S>,
35 ) -> Self {
36 Self::Unknown {
37 name: name.into(),
38 available: available.into_iter().map(Into::into).collect(),
39 }
40 }
41
42 pub fn config(plugin: impl Into<String>, message: impl fmt::Display) -> Self {
44 Self::Config {
45 plugin: plugin.into(),
46 message: message.to_string(),
47 }
48 }
49
50 pub fn runtime(plugin: impl Into<String>, message: impl fmt::Display) -> Self {
52 Self::Runtime {
53 plugin: plugin.into(),
54 message: message.to_string(),
55 }
56 }
57
58 pub fn host(message: impl fmt::Display) -> Self {
60 Self::Host(message.to_string())
61 }
62
63 #[must_use]
64 pub fn plugin(&self) -> Option<&str> {
65 match self {
66 Self::Unknown { name, .. } => Some(name),
67 Self::Config { plugin, .. } | Self::Runtime { plugin, .. } => Some(plugin),
68 Self::Host(_) => None,
69 }
70 }
71}
72
73impl fmt::Display for PluginError {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Self::Unknown { name, available } => {
77 write!(f, "unknown plugin `{name}`")?;
78
79 if !available.is_empty() {
80 write!(f, " (compiled in: {})", available.join(", "))?;
81 }
82
83 Ok(())
84 }
85 Self::Config { plugin, message } => {
86 write!(f, "invalid configuration for plugin `{plugin}`: {message}")
87 }
88 Self::Runtime { plugin, message } => write!(f, "plugin `{plugin}` failed: {message}"),
89 Self::Host(message) => write!(f, "host error: {message}"),
90 }
91 }
92}
93
94impl std::error::Error for PluginError {}