use crate::bindings;
use crate::bindings::error_setg_internal;
use std::fmt;
use std::fmt::Display;
use std::ptr;
#[derive(Debug, Default)]
pub struct Error {
msg: Option<String>,
cause: Option<Box<dyn std::error::Error>>,
location: Option<(String, u32)>,
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_deref()
}
fn description(&self) -> &str {
self.msg.as_deref().unwrap_or("error")
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut prefix = "";
if let Some((ref file, line)) = self.location {
write!(f, "{}:{}", file, line)?;
prefix = ": ";
}
if let Some(ref msg) = self.msg {
write!(f, "{}{}", prefix, msg)?;
prefix = ": ";
}
if let Some(ref cause) = self.cause {
write!(f, "{}{}", prefix, cause)?;
} else if prefix == "" {
f.write_str("error")?;
}
Ok(())
}
}
impl From<&str> for Error {
fn from(msg: &str) -> Self {
Error {
msg: Some(String::from(msg)),
cause: None,
location: None,
}
}
}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
Error {
msg: None,
cause: Some(Box::new(error)),
location: None,
}
}
}
impl Error {
fn with_error<T: std::error::Error + 'static>(msg: &str, cause: T) -> Self {
Error {
msg: Some(String::from(msg)),
cause: Some(Box::new(cause)),
location: None,
}
}
fn with_error_file_line<T: std::error::Error + 'static>(
msg: &str,
cause: T,
file: &str,
line: u32,
) -> Self {
Error {
msg: Some(String::from(msg)),
cause: Some(Box::new(cause)),
location: Some((String::from(file), line)),
}
}
fn with_file_line(msg: &str, file: &str, line: u32) -> Self {
Error {
msg: Some(String::from(msg)),
cause: None,
location: Some((String::from(file), line)),
}
}
fn to_c_error(self) -> *mut bindings::Error {
let mut x: *mut bindings::Error = ptr::null_mut();
unsafe {
error_setg_internal(
&mut x as *mut _,
ptr::null_mut(), // FIXME: null
0,
ptr::null_mut(), // FIXME: null
c"%s".as_ptr(),
format!("{}", self),
);
}
x
}
}
// qemu::Result<T>
type Result<T> = std::result::Result<T, Error>;