molt_ng/macros.rs
1//! Convenience Macros
2//!
3//! This module contains macros for use by command authors.
4
5/// Returns an `Ok` `MoltResult`.
6///
7/// If called with no arguments, returns an empty value as the `Ok` result.
8/// If called with one argument, returns the argument as the `Ok` result, converting it
9/// to a value automatically.
10/// If called with two or more arguments, computes the `Ok` result using
11/// `format!()`; the first argument is naturally the format string.
12///
13/// # Examples
14///
15/// ```
16/// use molt::*;
17///
18/// // Return the empty result
19/// fn func1() -> MoltResult {
20/// // ...
21/// molt_ok!()
22/// }
23///
24/// assert_eq!(func1(), Ok(Value::empty()));
25///
26/// // Return an arbitrary value
27/// fn func2() -> MoltResult {
28/// // ...
29/// molt_ok!(17)
30/// }
31///
32/// assert_eq!(func2(), Ok(17.into()));
33///
34/// // Return a formatted value
35/// fn func3() -> MoltResult {
36/// // ...
37/// molt_ok!("The answer is {}", 17)
38/// }
39///
40/// assert_eq!(func3(), Ok("The answer is 17".into()));
41/// ```
42#[macro_export]
43macro_rules! molt_ok {
44 () => (
45 Ok($crate::Value::empty())
46 );
47 ($arg:expr) => (
48 Ok($crate::Value::from($arg))
49 );
50 ($($arg:tt)*) => (
51 Ok($crate::Value::from(format!($($arg)*)))
52 )
53}
54
55/// Returns an `Error` `MoltResult`. The error message is formatted
56/// as with `format!()`.
57///
58/// If called with one argument, the single argument is used as the error message.
59/// If called with more than one argument, the first is a `format!()` format string,
60/// and the remainder are the values to format.
61///
62/// This macro wraps the [`Exception::molt_err`](types/struct.Exception.html#method.molt_err)
63/// method.
64///
65/// # Examples
66///
67/// ```
68/// use molt::*;
69///
70/// // Return a simple error message
71/// fn err1() -> MoltResult {
72/// // ...
73/// molt_err!("error message")
74/// }
75///
76/// let result = err1();
77/// assert!(result.is_err());
78///
79/// let exception = result.err().unwrap();
80/// assert!(exception.is_error());
81/// assert_eq!(exception.value(), "error message".into());
82///
83/// // Return a formatted error
84/// fn err2() -> MoltResult {
85/// // ...
86/// molt_err!("invalid value: {}", 17)
87/// }
88///
89/// let result = err2();
90/// assert!(result.is_err());
91///
92/// let exception = result.err().unwrap();
93/// assert!(exception.is_error());
94/// assert_eq!(exception.value(), "invalid value: 17".into());
95/// ```
96#[macro_export]
97macro_rules! molt_err {
98 ($arg:expr) => (
99 Err($crate::Exception::molt_err($crate::Value::from($arg)))
100 );
101 ($($arg:tt)*) => (
102 Err($crate::Exception::molt_err($crate::Value::from(format!($($arg)*))))
103 )
104}
105
106/// Returns an `Error` `MoltResult` with a specific error code. The error message is formatted
107/// as with `format!()`.
108///
109/// The macro requires two or more arguments. The first argument is always the error code.
110/// If called with two arguments, the second is the error message.
111/// If called with more than two arguments, the second is a `format!()` format string and
112/// the remainder are the values to format.
113///
114/// This macro wraps
115/// the [`Exception::molt_err2`](types/struct.Exception.html#method.molt_err2)
116/// method.
117///
118/// # Examples
119///
120/// ```
121/// use molt::*;
122///
123/// // Throw a simple error
124/// fn throw1() -> MoltResult {
125/// // ...
126/// molt_throw!("MYCODE", "error message")
127/// }
128///
129/// let result = throw1();
130/// assert!(result.is_err());
131///
132/// let exception = result.err().unwrap();
133/// assert!(exception.is_error());
134/// assert_eq!(exception.value(), "error message".into());
135/// assert_eq!(exception.error_code(), "MYCODE".into());
136///
137/// // Return a formatted error
138/// fn throw2() -> MoltResult {
139/// // ...
140/// molt_throw!("MYCODE", "invalid value: {}", 17)
141/// }
142///
143/// let result = throw2();
144/// assert!(result.is_err());
145///
146/// let exception = result.err().unwrap();
147/// assert!(exception.is_error());
148/// assert_eq!(exception.value(), "invalid value: 17".into());
149/// assert_eq!(exception.error_code(), "MYCODE".into());
150/// ```
151#[macro_export]
152macro_rules! molt_throw {
153 ($code:expr, $msg:expr) => (
154 Err($crate::Exception::molt_err2($crate::Value::from($code), $crate::Value::from($msg)))
155 );
156 ($code:expr, $($arg:tt)*) => (
157 Err($crate::Exception::molt_err2($crate::Value::from($code), $crate::Value::from(format!($($arg)*))))
158 )
159}
160
161#[cfg(test)]
162mod tests {
163 use crate::*;
164
165 #[test]
166 fn test_molt_ok() {
167 let result: MoltResult = molt_ok!();
168 assert_eq!(Ok(Value::empty()), result);
169
170 let result: MoltResult = molt_ok!(5);
171 assert_eq!(Ok(Value::from(5)), result);
172
173 let result: MoltResult = molt_ok!("Five");
174 assert_eq!(Ok(Value::from("Five")), result);
175
176 let result: MoltResult = molt_ok!("The answer is {}.", 5);
177 assert_eq!(Ok(Value::from("The answer is 5.")), result);
178 }
179
180 #[test]
181 fn test_molt_err() {
182 check_err(molt_err!("error message"), "error message");
183 check_err(molt_err!("error {}", 5), "error 5");
184 }
185
186 #[test]
187 fn test_molt_throw() {
188 check_throw(
189 molt_throw!("MYERR", "error message"),
190 "MYERR",
191 "error message",
192 );
193 check_throw(molt_throw!("MYERR", "error {}", 5), "MYERR", "error 5");
194 }
195
196 fn check_err(result: MoltResult, msg: &str) -> bool {
197 match result {
198 Err(exception) => exception.is_error() && exception.value() == msg.into(),
199 _ => false,
200 }
201 }
202
203 fn check_throw(result: MoltResult, code: &str, msg: &str) -> bool {
204 match result {
205 Err(exception) => {
206 exception.is_error()
207 && exception.value() == msg.into()
208 && exception.error_code() == code.into()
209 }
210 _ => false,
211 }
212 }
213}