1use std::fmt::Debug;
6
7pub fn make_error(
9 err: std::io::Error,
10 _raw: impl Debug,
11 _file: &str,
12 _line: u32,
13) -> std::io::Error {
14 #[cfg(feature = "error-backtrace")]
15 {
16 if let Ok(val) = std::env::var("RUST_BACKTRACE") {
17 if val.trim() != "0" {
18 error!("Stack:\n{:?}", backtrace::Backtrace::new());
19 error!("Error:\n\t{:?}\n\tat {}:{}", _raw, _file, _line);
20 return err;
21 }
22 }
23 error!(
24 "Error:\n\t{:?}\n\tat {}:{}\n\tnote: enable `RUST_BACKTRACE=1` env to display a backtrace",
25 _raw, _file, _line
26 );
27 }
28 err
29}
30
31macro_rules! define_error_macro {
34 ($fn:ident, $err:expr) => {
35 #[macro_export]
36 macro_rules! $fn {
37 () => {
38 std::io::Error::new($err.kind(), format!("{}: {}:{}", $err, file!(), line!()))
39 };
40 ($raw:expr) => {
41 $crate::error::make_error($err, &$raw, file!(), line!())
42 };
43 }
44 };
45}
46
47macro_rules! define_libc_error_macro {
49 ($fn:ident, $code:ident) => {
50 define_error_macro!($fn, std::io::Error::from_raw_os_error(libc::$code));
51 };
52}
53
54define_libc_error_macro!(einval, EINVAL);
57define_libc_error_macro!(enoent, ENOENT);
58define_libc_error_macro!(ebadf, EBADF);
59define_libc_error_macro!(eacces, EACCES);
60define_libc_error_macro!(enotdir, ENOTDIR);
61define_libc_error_macro!(eisdir, EISDIR);
62define_libc_error_macro!(ealready, EALREADY);
63define_libc_error_macro!(enosys, ENOSYS);
64define_libc_error_macro!(epipe, EPIPE);
65define_libc_error_macro!(eio, EIO);
66
67#[macro_export]
69macro_rules! bail_einval {
70 ($($arg:tt)*) => {{
71 return Err(einval!(format!($($arg)*)))
72 }}
73}
74
75#[macro_export]
77macro_rules! bail_eio {
78 ($($arg:tt)*) => {{
79 return Err(eio!(format!($($arg)*)))
80 }}
81}
82
83define_error_macro!(last_error, std::io::Error::last_os_error());
85define_error_macro!(eother, std::io::Error::new(std::io::ErrorKind::Other, ""));
86
87#[cfg(test)]
88mod tests {
89 fn check_size(size: usize) -> std::io::Result<()> {
90 if size > 0x1000 {
91 return Err(einval!());
92 }
93
94 Ok(())
95 }
96
97 #[test]
98 fn test_einval() {
99 assert_eq!(
100 check_size(0x2000).unwrap_err().kind(),
101 std::io::Error::from_raw_os_error(libc::EINVAL).kind()
102 );
103 }
104}