use std::fmt;
pub type Result<T, E = PluginError> = std::result::Result<T, E>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PluginError {
Unknown {
name: String,
available: Vec<String>,
},
Config { plugin: String, message: String },
Runtime { plugin: String, message: String },
Host(String),
}
impl PluginError {
pub fn unknown<S: Into<String>>(
name: impl Into<String>,
available: impl IntoIterator<Item = S>,
) -> Self {
Self::Unknown {
name: name.into(),
available: available.into_iter().map(Into::into).collect(),
}
}
pub fn config(plugin: impl Into<String>, message: impl fmt::Display) -> Self {
Self::Config {
plugin: plugin.into(),
message: message.to_string(),
}
}
pub fn runtime(plugin: impl Into<String>, message: impl fmt::Display) -> Self {
Self::Runtime {
plugin: plugin.into(),
message: message.to_string(),
}
}
pub fn host(message: impl fmt::Display) -> Self {
Self::Host(message.to_string())
}
#[must_use]
pub fn plugin(&self) -> Option<&str> {
match self {
Self::Unknown { name, .. } => Some(name),
Self::Config { plugin, .. } | Self::Runtime { plugin, .. } => Some(plugin),
Self::Host(_) => None,
}
}
}
impl fmt::Display for PluginError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unknown { name, available } => {
write!(f, "unknown plugin `{name}`")?;
if !available.is_empty() {
write!(f, " (compiled in: {})", available.join(", "))?;
}
Ok(())
}
Self::Config { plugin, message } => {
write!(f, "invalid configuration for plugin `{plugin}`: {message}")
}
Self::Runtime { plugin, message } => write!(f, "plugin `{plugin}` failed: {message}"),
Self::Host(message) => write!(f, "host error: {message}"),
}
}
}
impl std::error::Error for PluginError {}