Skip to main content

ruc/err/
macros.rs

1//!
2//! # Macros
3//!
4//! Useful macros for chained error managements.
5//!
6
7/// Print information only
8#[macro_export]
9macro_rules! info {
10    ($ops: expr, $fmt: expr, $($arg:tt)*) => {{
11        $ops.c($crate::d!($fmt, $($arg)*)).map_err(|e| {
12            if "INFO" == $crate::LOG_LEVEL.as_str() {
13                e.print(Some("INFO"));
14            }
15            e
16        })
17    }};
18    ($ops: expr, $msg: expr) => {{
19        $crate::info!($ops, "{}", $msg)
20    }};
21    ($ops: expr) => {{
22        $crate::info!($ops, "")
23    }};
24}
25
26/// omit the result without printing any message
27#[macro_export]
28macro_rules! omit {
29    ($ops: expr) => {{
30        let _ = $ops;
31    }};
32}
33
34/// Drop the result after printing the message
35#[macro_export]
36macro_rules! info_omit {
37    ($ops: expr, $fmt: expr, $($arg:tt)*) => {{
38        $crate::omit!($crate::info!($ops, $fmt, $($arg)*));
39    }};
40    ($ops: expr, $msg: expr) => {{
41        $crate::info_omit!($ops, "{}", $msg)
42    }};
43    ($ops: expr) => {{
44        $crate::info_omit!($ops, "")
45    }};
46}
47
48/// Generate debug info, e.g., file path, line number, column number
49#[macro_export]
50macro_rules! d {
51    ($fmt: expr, $($arg:tt)*) => {{
52        $crate::err::SimpleMsg::new(format!($fmt, $($arg)*), file!(), line!(), column!())
53    }};
54    ($err: expr) => {{
55        $crate::d!("{}", $err)
56    }};
57    () => {{
58        $crate::err::SimpleMsg::new(String::new(), file!(), line!(), column!())
59    }};
60}
61
62/// print custom msg
63#[macro_export]
64macro_rules! print_msg {
65    ($fmt: expr, $($arg:tt)*) => {{
66        println!("\n{}", $crate::d!($fmt, $($arg)*));
67    }};
68    ($msg: expr) => {{
69        $crate::print_msg!("{}", $msg)
70    }};
71}
72
73/// eprint custom msg
74#[macro_export]
75macro_rules! eprint_msg {
76    ($fmt: expr, $($arg:tt)*) => {{
77        eprintln!("\n{}", $crate::d!($fmt, $($arg)*));
78    }};
79    ($msg: expr) => {{
80        $crate::eprint_msg!("{}", $msg)
81    }};
82}
83
84/// Just a panic
85#[macro_export]
86macro_rules! die {
87    ($fmt: expr, $($arg:tt)*) => {{
88        $crate::print_msg!($fmt, $($arg)*);
89        panic!();
90    }};
91    ($msg: expr) => {{
92        $crate::die!("{}", $msg)
93    }};
94    () => {{
95        $crate::die!("")
96    }};
97}
98
99/// Print log, and panic
100#[macro_export]
101macro_rules! pnk {
102    ($ops: expr, $fmt: expr, $($arg:tt)*) => {{
103        $ops.c($crate::d!($fmt, $($arg)*)).unwrap_or_else(|e| e.print_die())
104    }};
105    ($ops: expr, $msg: expr) => {{
106        $crate::pnk!($ops, "{}", $msg)
107    }};
108    ($ops: expr) => {{
109        $crate::pnk!($ops, "")
110    }};
111}
112
113/// Generate error with debug info
114#[macro_export]
115macro_rules! eg {
116    ($fmt: expr, $($arg:tt)*) => {{
117        Box::new($crate::err::SimpleError::new($crate::d!($fmt, $($arg)*), None))
118            as Box<dyn $crate::err::RucError>
119    }};
120    ($err: expr) => {{
121        $crate::eg!("{}", $err)
122    }};
123    () => {{
124        $crate::eg!("")
125    }};
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::*;
131
132    fn display_style_inner() -> Result<()> {
133        #[derive(Debug, Eq, PartialEq)]
134        struct CustomErr(i32);
135
136        let l1 = || -> Result<()> { Err(eg!("The final error message!")) };
137        let l2 = || -> Result<()> { l1().c(d!()).or_else(|e| l1().c(d!(e))) };
138        let l3 = || -> Result<()> { l2().c(d!("A custom message!")) };
139        let l4 = || -> Result<()> { l3().c(d!("ERR_UNKNOWN")) };
140        let l5 = || -> Result<()> { l4().c(d!("{:?}", CustomErr(-1))) };
141
142        l5().c(d!())
143    }
144
145    #[test]
146    #[should_panic]
147    fn t_display_style() {
148        pnk!(display_style_inner());
149    }
150
151    #[test]
152    fn t_macros() {
153        let s1 = map! {1 => 2, 2 => 4};
154        let s2 = map! {B 1 => 2, 2 => 4};
155        assert_eq!(s1.len(), s2.len());
156        for (idx, (k, v)) in s2.into_iter().enumerate() {
157            assert_eq!(1 + idx, k);
158            assert_eq!(2 * k, v);
159        }
160
161        let _ = info!(Err::<u8, _>(eg!()));
162        omit!(Err::<u8, _>(eg!()));
163        info_omit!(Err::<u8, _>(eg!()));
164        print_msg!("{:?}", ts!());
165        eprint_msg!("{:?}", ts!());
166    }
167}