ffx_command_error/
macros.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// Utility macro for constructing an [`Error`] that represents an unexpected failure
6/// condition (a bug).
7#[macro_export]
8macro_rules! bug {
9    ($error_message: expr) => {{
10        $crate::Error::Unexpected($crate::macro_deps::anyhow::anyhow!($error_message))
11    }};
12    ($fmt:expr, $($arg:tt)*) => {
13        $crate::bug!(format!($fmt, $($arg)*))
14    };
15}
16
17/// Utility macro for an early exit from a function returnng an [`Error`] that
18/// represents an unexpected failure condition (a bug).
19#[macro_export]
20macro_rules! return_bug {
21    ($error_message: expr) => {{
22        return Err($crate::bug!($error_message))
23    }};
24    ($fmt:expr, $($arg:tt)*) => {
25        return Err($crate::bug!($fmt, $($arg)*))
26    };
27}
28
29/// Utility macro for constructing an [`Error`] that represents a user-actionable
30/// failure condition.
31#[macro_export]
32macro_rules! user_error {
33    ($error_message: expr) => {{
34        $crate::Error::User($crate::macro_deps::anyhow::anyhow!($error_message))
35    }};
36    ($fmt:expr, $($arg:tt)*) => {
37        $crate::user_error!(format!($fmt, $($arg)*))
38    };
39}
40
41/// Utility macro for an early exit from a function returnng an [`Error`] that
42/// represents a user-actionable failure condition.
43#[macro_export]
44macro_rules! return_user_error {
45    ($error_message: expr) => {{
46        return Err($crate::user_error!($error_message))
47    }};
48    ($fmt:expr, $($arg:tt)*) => {
49        return Err($crate::user_error!($fmt, $($arg)*))
50    };
51}
52
53/// Utility macro for an early exit from a function returning an [`Error`] that
54/// represents an exit with a specific error code but no output.
55#[macro_export]
56macro_rules! exit_with_code {
57    ($code: expr) => {{
58        return Err($crate::Error::ExitWithCode($code));
59    }};
60}
61
62#[cfg(test)]
63mod tests {
64    use crate::Error;
65    use assert_matches::assert_matches;
66
67    /// to ease type inference around blocks used to test the `return_` variants
68    fn run(f: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
69        f()
70    }
71
72    #[test]
73    fn test_bug_macro() {
74        assert_matches!(bug!("A bug!"), Error::Unexpected(err) if format!("{err}") == "A bug!");
75        assert_matches!(bug!("A bug with a substitution {}!", 1), Error::Unexpected(err) if format!("{err}") == "A bug with a substitution 1!");
76    }
77
78    #[test]
79    fn test_return_bug_macro() {
80        assert_matches!(run(|| { return_bug!("A bug!") }), Err(Error::Unexpected(err)) if format!("{err}") == "A bug!");
81        assert_matches!(run(|| { return_bug!("A bug with a substitution {}!", 1) }), Err(Error::Unexpected(err)) if format!("{err}") == "A bug with a substitution 1!");
82    }
83
84    #[test]
85    fn test_user_error_macro() {
86        assert_matches!(user_error!("A user error!"), Error::User(err) if format!("{err}") == "A user error!");
87        assert_matches!(user_error!("A user error with a substitution {}!", 1), Error::User(err) if format!("{err}") == "A user error with a substitution 1!");
88    }
89
90    #[test]
91    fn test_return_user_error_macro() {
92        assert_matches!(run(|| { return_user_error!("A user error!") }), Err(Error::User(err)) if format!("{err}") == "A user error!");
93        assert_matches!(run(|| { return_user_error!("A user error with a substitution {}!", 1) }), Err(Error::User(err)) if format!("{err}") == "A user error with a substitution 1!");
94    }
95}