use alloc::string::String;
use core::fmt;
use onerom_config::fw::FirmwareVersion;
use crate::plugin::{PluginType, PluginVersion};
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum PluginError {
#[error("a {0} plugin has already been specified")]
DuplicatePlugin(PluginType),
#[error("a user plugin requires a system plugin, but none was specified")]
UserPluginWithoutSystem,
#[error("plugin binary is {0} bytes, which exceeds the maximum of {1} bytes")]
TooLarge(usize, usize),
#[error("plugin '{0}' was not found in the plugins manifest")]
NotFound(String),
#[error("plugin '{0}' has no release with version {1}")]
VersionNotFound(String, PluginVersion),
#[error(
"plugin '{name}' version {version} requires firmware {min_fw} or later (selected firmware is {fw})"
)]
Incompatible {
name: String,
version: PluginVersion,
min_fw: FirmwareVersion,
fw: FirmwareVersion,
},
#[error(
"plugin '{name}' version {version} is not compatible with firmware {from} or later (selected firmware is {fw})"
)]
IncompatibleNewer {
name: String,
version: PluginVersion,
from: FirmwareVersion,
fw: FirmwareVersion,
},
#[error(
"plugin binary from '{0}' is {1} bytes, too small for a valid header (minimum {2} bytes)"
)]
BinaryTooSmall(String, usize, usize),
#[error("plugin binary from '{0}' has invalid header magic {1:#010x} (expected {2:#010x})")]
InvalidMagic(String, u32, u32),
#[error("plugin '{0}' type mismatch: manifest says {1}, binary header says {2}")]
TypeMismatch(String, PluginType, PluginType),
#[error("plugin '{0}' version mismatch: manifest says {1}, binary header says {2}")]
VersionMismatch(String, PluginVersion, PluginVersion),
#[error("SHA-256 mismatch for plugin binary '{binary}' (expected {expected}, got {got})")]
Sha256Mismatch {
binary: String,
expected: String,
got: String,
},
#[error("plugin binary from '{0}' is a PIO plugin, which is not currently supported")]
PioNotSupported(String),
#[error("plugin binary from '{0}' has an unrecognised type value: {1}")]
UnknownBinaryType(String, u8),
#[error("plugin '{0}' has an unrecognised type '{1}' in the manifest")]
UnknownManifestType(String, String),
#[error("invalid plugin specification: {0}")]
SpecSyntax(String),
#[error("failed to parse manifest JSON from '{0}': {1}")]
ManifestJson(String, String),
}
#[derive(Debug)]
pub enum Error<E> {
Plugin(PluginError),
Fetch {
source: String,
error: E,
},
}
impl<E> From<PluginError> for Error<E> {
fn from(e: PluginError) -> Self {
Error::Plugin(e)
}
}
impl<E> Error<E> {
pub fn fetch(source: impl Into<String>, error: E) -> Self {
Error::Fetch {
source: source.into(),
error,
}
}
}
impl<E: fmt::Display> fmt::Display for Error<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Plugin(e) => write!(f, "{e}"),
Error::Fetch { source, error } => {
write!(f, "failed to fetch '{source}': {error}")
}
}
}
}
impl<E: fmt::Display + fmt::Debug> core::error::Error for Error<E> {}