Features/Rust/Error

From QEMU
Revision as of 19:30, 14 June 2024 by Paolo Bonzini (talk | contribs) (Created page with "<pre> 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_...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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>;