nydus_error/
error.rs

1// Copyright 2020 Ant Group. All rights reserved.
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use std::env;
6use std::fmt::Debug;
7
8use backtrace::Backtrace;
9use serde_json::Error as SerdeError;
10
11/// Display error messages with line number, file path and optional backtrace.
12pub fn make_error(err: std::io::Error, raw: impl Debug, file: &str, line: u32) -> std::io::Error {
13    if cfg!(debug_assertions) {
14        if let Ok(val) = env::var("RUST_BACKTRACE") {
15            if val.trim() != "0" {
16                error!("Stack:\n{:?}", Backtrace::new());
17                error!("Error:\n\t{:?}\n\tat {}:{}", raw, file, line);
18                return err;
19            }
20        }
21    }
22    error!(
23        "Error:\n\t{:?}\n\tat {}:{}\n\tnote: enable `RUST_BACKTRACE=1` env to display a backtrace",
24        raw, file, line
25    );
26    err
27}
28
29/// Define error macro like `x!()` or `x!(err)`.
30/// Note: The `x!()` macro will convert any origin error (Os, Simple, Custom) to Custom error.
31macro_rules! define_error_macro {
32    ($fn:ident, $err:expr) => {
33        #[macro_export]
34        macro_rules! $fn {
35            () => {
36                std::io::Error::new($err.kind(), format!("{}: {}:{}", $err, file!(), line!()))
37            };
38            ($raw:expr) => {
39                $crate::error::make_error($err, &$raw, file!(), line!())
40            };
41        }
42    };
43}
44
45/// Define error macro for libc error codes
46macro_rules! define_libc_error_macro {
47    ($fn:ident, $code:ident) => {
48        define_error_macro!($fn, std::io::Error::from_raw_os_error(libc::$code));
49    };
50}
51
52// TODO: Add format string support
53// Add more libc error macro here if necessary
54define_libc_error_macro!(einval, EINVAL);
55define_libc_error_macro!(enoent, ENOENT);
56define_libc_error_macro!(ebadf, EBADF);
57define_libc_error_macro!(eacces, EACCES);
58define_libc_error_macro!(enotdir, ENOTDIR);
59define_libc_error_macro!(eisdir, EISDIR);
60define_libc_error_macro!(ealready, EALREADY);
61define_libc_error_macro!(enosys, ENOSYS);
62define_libc_error_macro!(epipe, EPIPE);
63define_libc_error_macro!(eio, EIO);
64
65/// Return EINVAL error with formatted error message.
66#[macro_export]
67macro_rules! bail_einval {
68    ($($arg:tt)*) => {{
69        return Err(einval!(format!($($arg)*)))
70    }}
71}
72
73/// Return EIO error with formatted error message.
74#[macro_export]
75macro_rules! bail_eio {
76    ($($arg:tt)*) => {{
77        return Err(eio!(format!($($arg)*)))
78    }}
79}
80
81// Add more custom error macro here if necessary
82define_error_macro!(last_error, std::io::Error::last_os_error());
83define_error_macro!(eother, std::io::Error::new(std::io::ErrorKind::Other, ""));
84
85/// Errors related to Metrics.
86#[derive(Debug)]
87pub enum MetricsError {
88    /// Non-exist counter.
89    NoCounter,
90    /// Failed to serialize message.
91    Serialize(SerdeError),
92}
93
94#[cfg(test)]
95mod tests {
96    fn check_size(size: usize) -> std::io::Result<()> {
97        if size > 0x1000 {
98            return Err(einval!());
99        }
100
101        Ok(())
102    }
103
104    #[test]
105    fn test_einval() {
106        assert_eq!(
107            check_size(0x2000).unwrap_err().kind(),
108            std::io::Error::from_raw_os_error(libc::EINVAL).kind()
109        );
110    }
111}