use alloc::string::String;
use core::fmt;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
Config {
at: String,
message: String,
},
UnknownClass(String),
Property(String),
Bus(BusError),
State(String),
Unimplemented(&'static str),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BusError {
Unassigned,
BadAccess,
Retry,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Config { at, message } => write!(f, "{at}: {message}"),
Error::UnknownClass(name) => {
write!(f, "unknown device class `{name}` (is its feature enabled?)")
}
Error::Property(message) => f.write_str(message),
Error::Bus(e) => write!(f, "bus error: {e}"),
Error::State(message) => write!(f, "snapshot error: {message}"),
Error::Unimplemented(what) => write!(f, "not implemented yet: {what}"),
}
}
}
impl fmt::Display for BusError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
BusError::Unassigned => "nothing mapped at this address",
BusError::BadAccess => "access width or alignment not permitted",
BusError::Retry => "target busy, retry",
};
f.write_str(s)
}
}
impl From<BusError> for Error {
fn from(e: BusError) -> Self {
Error::Bus(e)
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
#[cfg(test)]
mod tests {
use super::*;
use alloc::string::ToString;
#[test]
fn unknown_class_hints_at_the_likely_cause() {
let e = Error::UnknownClass("pci.nvme".to_string());
let text = e.to_string();
assert!(text.contains("pci.nvme"));
assert!(text.contains("feature"));
}
#[test]
fn config_errors_lead_with_their_location() {
let e = Error::Config {
at: "nes.machine:12:5".to_string(),
message: "unknown property `clok`".to_string(),
};
assert!(e.to_string().starts_with("nes.machine:12:5: "));
}
#[test]
fn bus_errors_convert() {
let e: Error = BusError::Unassigned.into();
assert_eq!(e, Error::Bus(BusError::Unassigned));
}
}