Skip to main content

mdbook_plotly/
macros.rs

1/// Used to send critical errors.
2/// Will exit directly with exit code `1`.
3///
4/// NOTE: This macro is only useful after Rust version `1.79`.
5#[macro_export]
6macro_rules! fatal {
7    ($($arg:tt)*) => {{
8        // This line only compiles smoothly after version `1.79`.
9        // Compiling with older versions may result in temporary value errors.
10        //
11        // If you need some information, here it is:
12        // Issue: [#92698](https://github.com/rust-lang/rust/issues/92698)
13        // Tracing issues with RFC66: [#15023](https://github.com/rust-lang/rust/issues/15023)
14        // The std doc about `Arguments`: [`std::fmt::Arguments`](https://doc.rust-lang.org/stable/std/fmt/struct.Arguments.html)
15        let msg = format_args!($($arg)*);
16
17        log::error!("Critical error: {}", msg);
18        #[cfg(debug_assertions)]
19        {
20            log::debug!("Backtrace: {:?}", std::backtrace::Backtrace::capture());
21        }
22        std::process::exit(1);
23    }};
24}
25
26/// Used to translate `serde_json::Value` into `DataPack<T>`.
27/// This macro avoids writing a lot of duplicate code.
28#[macro_export]
29macro_rules! translate {
30    ($target:expr, $value:expr, $map:expr, $(($method:ident, $ty:ty)),* $(,)?) => {{
31        $crate::translate_with_config!($target, $value, $map, &$crate::preprocessor::config::MapEvalConfig::default(), $(($method, $ty)),*)
32    }};
33    ($target:expr, $value:expr, $map:expr, $map_eval:expr, $(($method:ident, $ty:ty)),* $(,)?) => {{
34        $crate::translate_with_config!($target, $value, $map, $map_eval, $(($method, $ty)),*)
35    }};
36}
37
38#[macro_export]
39macro_rules! translate_with_config {
40    ($target:expr, $value:expr, $map:expr, $map_eval:expr, $(($method:ident, $ty:ty)),* $(,)?) => {{
41        use $crate::code_handler::until::DataPack;
42        let target = $target;
43        $(
44            let target = if let Some(v) = $value.get_mut(stringify!($method)) {
45                let data = serde_json::from_value::<DataPack<$ty>>(v.take())
46                    .map_err(|e| ::anyhow::anyhow!("Failed to deserialize field '{}': {}", stringify!($method), e))?;
47                target.$method(data.unwrap($map, $map_eval)
48                    .map_err(|e| ::anyhow::anyhow!("Failed to unwrap DataPack for field '{}': {}", stringify!($method), e))?)
49            } else {
50                target
51            };
52        )*
53        anyhow::Ok(target)
54    }};
55}
56
57/// Used to translate string values in `serde_json::Value` into enum variants
58/// via `DataPack<String>`, avoiding a lot of duplicate match-and-build code.
59#[macro_export]
60macro_rules! translate_enum {
61    ($target:expr, $value:expr, $map:expr, $(
62        ($method:ident, { $($str_val:literal => $variant:expr),* $(,)? })
63    ),* $(,)?) => {{
64        $crate::translate_enum_with_config!($target, $value, $map, &$crate::preprocessor::config::MapEvalConfig::default(), $(($method, { $($str_val => $variant),* })),*)
65    }};
66    ($target:expr, $value:expr, $map:expr, $map_eval:expr, $(
67        ($method:ident, { $($str_val:literal => $variant:expr),* $(,)? })
68    ),* $(,)?) => {{
69        $crate::translate_enum_with_config!($target, $value, $map, $map_eval, $(($method, { $($str_val => $variant),* })),*)
70    }};
71}
72
73#[macro_export]
74macro_rules! translate_enum_with_config {
75    ($target:expr, $value:expr, $map:expr, $map_eval:expr, $(
76        ($method:ident, { $($str_val:literal => $variant:expr),* $(,)? })
77    ),* $(,)?) => {{
78        use $crate::code_handler::until::DataPack;
79        let target = $target;
80        $(
81            let target = if let Some(v) = $value.get_mut(stringify!($method)) {
82                let data = serde_json::from_value::<DataPack<String>>(v.take())
83                    .map_err(|e| ::anyhow::anyhow!("Failed to deserialize field '{}': {}", stringify!($method), e))?;
84                let s = data.unwrap($map, $map_eval)
85                    .map_err(|e| ::anyhow::anyhow!("Failed to unwrap DataPack for field '{}': {}", stringify!($method), e))?;
86                match s.as_str() {
87                    $($str_val => target.$method($variant),)*
88                    unexpected => {
89                        return Err(::anyhow::anyhow!(
90                            "\"{}\" is not a valid value for `{}`",
91                            unexpected,
92                            stringify!($method),
93                        ))
94                    }
95                }
96            } else {
97                target
98            };
99        )*
100        anyhow::Ok(target)
101    }};
102}