assertables/assert_fn_err/
assert_fn_err_ge.rs

1//! Assert a function Err(…) is greater than or equal to another.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Err(a) ⇒ a) ≥ (b_function(b_param) ⇒ Err(b) ⇒ b)
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//! fn f(i: i8) -> Result<String, String> {
11//!     match i {
12//!         0..=9 => Ok(format!("{}", i)),
13//!         _ => Err(format!("{:?} is out of range", i)),
14//!     }
15//! }
16//!
17//! let a: i8 = 20;
18//! let b: i8 = 10;
19//! assert_fn_err_ge!(f, a, f, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_err_ge`](macro@crate::assert_fn_err_ge)
25//! * [`assert_fn_err_ge_as_result`](macro@crate::assert_fn_err_ge_as_result)
26//! * [`debug_assert_fn_err_ge`](macro@crate::debug_assert_fn_err_ge)
27
28/// Assert a function error is greater than or equal to another.
29///
30/// Pseudocode:<br>
31/// (a_function(a_param) ⇒ Err(a) ⇒ a) ≥ (b_function(b_param) ⇒ Err(b) ⇒ b)
32///
33/// * If true, return Result `Ok(a)`.
34///
35/// * Otherwise, return Result `Err(message)`.
36///
37/// This macro is useful for runtime checks, such as checking parameters,
38/// or sanitizing inputs, or handling different results in different ways.
39///
40/// # Module macros
41///
42/// * [`assert_fn_err_ge`](macro@crate::assert_fn_err_ge)
43/// * [`assert_fn_err_ge_as_result`](macro@crate::assert_fn_err_ge_as_result)
44/// * [`debug_assert_fn_err_ge`](macro@crate::debug_assert_fn_err_ge)
45///
46#[macro_export]
47macro_rules! assert_fn_err_ge_as_result {
48
49    //// Arity 1
50
51    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {{
52        match (&$a_function, &$a_param, &$b_function, &$b_param) {
53            (_a_function, a_param, _b_function, b_param) => {
54                match (
55                    $a_function($a_param),
56                    $b_function($b_param)
57                ) {
58                    (Err(a), Err(b)) => {
59                        if a >= b {
60                            Ok((a, b))
61                        } else {
62                            Err(
63                                format!(
64                                    concat!(
65                                        "assertion failed: `assert_fn_err_ge!(a_function, a_param, b_function, b_param)`\n",
66                                        "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
67                                        " a_function label: `{}`,\n",
68                                        "    a_param label: `{}`,\n",
69                                        "    a_param debug: `{:?}`,\n",
70                                        " b_function label: `{}`,\n",
71                                        "    b_param label: `{}`,\n",
72                                        "    b_param debug: `{:?}`,\n",
73                                        "                a: `{:?}`,\n",
74                                        "                b: `{:?}`"
75                                    ),
76                                    stringify!($a_function),
77                                    stringify!($a_param),
78                                    a_param,
79                                    stringify!($b_function),
80                                    stringify!($b_param),
81                                    b_param,
82                                    a,
83                                    b
84                                )
85                            )
86                        }
87                    },
88                    (a, b) => {
89                        Err(
90                            format!(
91                                concat!(
92                                    "assertion failed: `assert_fn_err_eq!(a_function, a_param, b_function, b_param)`\n",
93                                    "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_eq.html\n",
94                                    " a_function label: `{}`,\n",
95                                    "    a_param label: `{}`,\n",
96                                    "    a_param debug: `{:?}`,\n",
97                                    " b_function label: `{}`,\n",
98                                    "    b_param label: `{}`,\n",
99                                    "    b_param debug: `{:?}`,\n",
100                                    "                a: `{:?}`,\n",
101                                    "                b: `{:?}`"
102                                ),
103                                stringify!($a_function),
104                                stringify!($a_param),
105                                a_param,
106                                stringify!($b_function),
107                                stringify!($b_param),
108                                b_param,
109                                a,
110                                b
111                            )
112                        )
113                    }
114                }
115            }
116        }
117    }};
118
119    //// Arity 0
120
121    ($a_function:path, $b_function:path) => {{
122        match (
123            $a_function(),
124            $b_function()
125        ) {
126            (Err(a), Err(b)) => {
127                if a >= b {
128                    Ok((a, b))
129                } else {
130                    Err(
131                        format!(
132                            concat!(
133                                "assertion failed: `assert_fn_err_ge!(a_function, b_function)`\n",
134                                "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
135                                " a_function label: `{}`,\n",
136                                " b_function label: `{}`,\n",
137                                "                a: `{:?}`,\n",
138                                "                b: `{:?}`"
139                            ),
140                            stringify!($a_function),
141                            stringify!($b_function),
142                            a,
143                            b
144                        )
145                    )
146                }
147            },
148            (a, b) => {
149                Err(
150                    format!(
151                        concat!(
152                            "assertion failed: `assert_fn_err_eq!(a_function, b_function)`\n",
153                            "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_eq.html\n",
154                            " a_function label: `{}`,\n",
155                            " b_function label: `{}`,\n",
156                            "                a: `{:?}`,\n",
157                            "                b: `{:?}`"
158                        ),
159                        stringify!($a_function),
160                        stringify!($b_function),
161                        a,
162                        b
163                    )
164                )
165            }
166        }
167    }};
168
169}
170
171#[cfg(test)]
172mod test_assert_fn_err_ge_as_result {
173
174    mod arity_1 {
175
176        fn f(i: i8) -> Result<i8, i8> {
177            Err(i)
178        }
179
180        fn g(i: i8) -> Result<i8, i8> {
181            Err(i)
182        }
183
184        #[test]
185        fn gt() {
186            let a: i8 = 2;
187            let b: i8 = 1;
188            let actual = assert_fn_err_ge_as_result!(f, a, g, b);
189            assert_eq!(actual.unwrap(), (2, 1));
190        }
191
192        #[test]
193        fn eq() {
194            let a: i8 = 1;
195            let b: i8 = 1;
196            let actual = assert_fn_err_ge_as_result!(f, a, g, b);
197            assert_eq!(actual.unwrap(), (1, 1));
198        }
199
200        #[test]
201        fn lt() {
202            let a: i8 = 1;
203            let b: i8 = 2;
204            let actual = assert_fn_err_ge_as_result!(f, a, g, b);
205            let message = concat!(
206                "assertion failed: `assert_fn_err_ge!(a_function, a_param, b_function, b_param)`\n",
207                "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
208                " a_function label: `f`,\n",
209                "    a_param label: `a`,\n",
210                "    a_param debug: `1`,\n",
211                " b_function label: `g`,\n",
212                "    b_param label: `b`,\n",
213                "    b_param debug: `2`,\n",
214                "                a: `1`,\n",
215                "                b: `2`"
216            );
217            assert_eq!(actual.unwrap_err(), message);
218        }
219    }
220
221    mod arity_0 {
222
223        fn f() -> Result<i8, i8> {
224            Err(1)
225        }
226
227        fn g() -> Result<i8, i8> {
228            Err(2)
229        }
230
231        #[test]
232        fn gt() {
233            let actual = assert_fn_err_ge_as_result!(g, f);
234            assert_eq!(actual.unwrap(), (2, 1));
235        }
236
237        #[test]
238        fn eq() {
239            let actual = assert_fn_err_ge_as_result!(f, f);
240            assert_eq!(actual.unwrap(), (1, 1));
241        }
242
243        #[test]
244        fn lt() {
245            let actual = assert_fn_err_ge_as_result!(f, g);
246            let message = concat!(
247                "assertion failed: `assert_fn_err_ge!(a_function, b_function)`\n",
248                "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
249                " a_function label: `f`,\n",
250                " b_function label: `g`,\n",
251                "                a: `1`,\n",
252                "                b: `2`"
253            );
254            assert_eq!(actual.unwrap_err(), message);
255        }
256    }
257}
258
259/// Assert a function error is greater than or equal to another.
260///
261/// Pseudocode:<br>
262/// (a_function(a_param) ⇒ Err(a) ⇒ a) ≥ (b_function(b_param) ⇒ Err(b) ⇒ b)
263///
264/// * If true, return `(a, b)`.
265///
266/// * Otherwise, call [`panic!`] with a message and the values of the
267///   expressions with their debug representations.
268///
269/// # Examples
270///
271/// ```rust
272/// use assertables::*;
273/// # use std::panic;
274/// fn f(i: i8) -> Result<String, String> {
275///     match i {
276///         0..=9 => Ok(format!("{}", i)),
277///         _ => Err(format!("{:?} is out of range", i)),
278///     }
279/// }
280///
281/// # fn main() {
282/// let a: i8 = 20;
283/// let b: i8 = 10;
284/// assert_fn_err_ge!(f, a, f, b);
285///
286/// # let result = panic::catch_unwind(|| {
287/// // This will panic
288/// let a: i8 = 10;
289/// let b: i8 = 20;
290/// assert_fn_err_ge!(f, a, f, b);
291/// # });
292/// // assertion failed: `assert_fn_err_ge!(a_function, a_param, b_function, b_param)`
293/// // https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html
294/// //  a_function label: `f`,
295/// //     a_param label: `a`,
296/// //     a_param debug: `10`,
297/// //  b_function label: `f`,
298/// //     b_param label: `b`,
299/// //     b_param debug: `20`,
300/// //                 a: `\"10 is out of range\"`,
301/// //                 b: `\"20 is out of range\"`
302/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
303/// # let message = concat!(
304/// #     "assertion failed: `assert_fn_err_ge!(a_function, a_param, b_function, b_param)`\n",
305/// #     "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
306/// #     " a_function label: `f`,\n",
307/// #     "    a_param label: `a`,\n",
308/// #     "    a_param debug: `10`,\n",
309/// #     " b_function label: `f`,\n",
310/// #     "    b_param label: `b`,\n",
311/// #     "    b_param debug: `20`,\n",
312/// #     "                a: `\"10 is out of range\"`,\n",
313/// #     "                b: `\"20 is out of range\"`"
314/// # );
315/// # assert_eq!(actual, message);
316/// # }
317/// ```
318///
319/// # Module macros
320///
321/// * [`assert_fn_err_ge`](macro@crate::assert_fn_err_ge)
322/// * [`assert_fn_err_ge_as_result`](macro@crate::assert_fn_err_ge_as_result)
323/// * [`debug_assert_fn_err_ge`](macro@crate::debug_assert_fn_err_ge)
324///
325#[macro_export]
326macro_rules! assert_fn_err_ge {
327
328    //// Arity 1
329
330    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {{
331        match $crate::assert_fn_err_ge_as_result!($a_function, $a_param, $b_function, $b_param) {
332            Ok(x) => x,
333            Err(err) => panic!("{}", err),
334        }
335    }};
336
337    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr, $($message:tt)+) => {{
338        match $crate::assert_fn_err_ge_as_result!($a_function, $a_param, $b_function, $b_param) {
339            Ok(x) => x,
340            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
341        }
342    }};
343
344    //// Arity 0
345
346    ($a_function:path, $b_function:path) => {{
347        match $crate::assert_fn_err_ge_as_result!($a_function, $b_function) {
348            Ok(x) => x,
349            Err(err) => panic!("{}", err),
350        }
351    }};
352
353    ($a_function:path, $b_function:path, $($message:tt)+) => {{
354        match $crate::assert_fn_err_ge_as_result!($a_function, $b_function) {
355            Ok(x) => x,
356            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
357        }
358    }};
359}
360
361#[cfg(test)]
362mod test_assert_fn_err_ge {
363    use std::panic;
364
365    mod arity_1 {
366        use super::*;
367
368        fn f(i: i8) -> Result<i8, i8> {
369            Err(i)
370        }
371
372        fn g(i: i8) -> Result<i8, i8> {
373            Err(i)
374        }
375
376        #[test]
377        fn gt() {
378            let a: i8 = 2;
379            let b: i8 = 1;
380            let actual = assert_fn_err_ge!(f, a, g, b);
381            assert_eq!(actual, (2, 1));
382        }
383
384        #[test]
385        fn eq() {
386            let a: i8 = 1;
387            let b: i8 = 1;
388            let actual = assert_fn_err_ge!(f, a, g, b);
389            assert_eq!(actual, (1, 1));
390        }
391
392        #[test]
393        fn lt() {
394            let result = panic::catch_unwind(|| {
395                let a: i8 = 1;
396                let b: i8 = 2;
397                let _actual = assert_fn_err_ge!(f, a, g, b);
398            });
399            let message = concat!(
400                "assertion failed: `assert_fn_err_ge!(a_function, a_param, b_function, b_param)`\n",
401                "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
402                " a_function label: `f`,\n",
403                "    a_param label: `a`,\n",
404                "    a_param debug: `1`,\n",
405                " b_function label: `g`,\n",
406                "    b_param label: `b`,\n",
407                "    b_param debug: `2`,\n",
408                "                a: `1`,\n",
409                "                b: `2`"
410            );
411            assert_eq!(
412                result
413                    .unwrap_err()
414                    .downcast::<String>()
415                    .unwrap()
416                    .to_string(),
417                message
418            );
419        }
420    }
421
422    mod arity_0 {
423        use super::*;
424
425        fn f() -> Result<i8, i8> {
426            Err(1)
427        }
428
429        fn g() -> Result<i8, i8> {
430            Err(2)
431        }
432
433        #[test]
434        fn gt() {
435            let actual = assert_fn_err_ge!(g, f);
436            assert_eq!(actual, (2, 1));
437        }
438
439        #[test]
440        fn eq() {
441            let actual = assert_fn_err_ge!(f, f);
442            assert_eq!(actual, (1, 1));
443        }
444
445        #[test]
446        fn lt() {
447            let result = panic::catch_unwind(|| {
448                let _actual = assert_fn_err_ge!(f, g);
449            });
450            let message = concat!(
451                "assertion failed: `assert_fn_err_ge!(a_function, b_function)`\n",
452                "https://docs.rs/assertables/9.5.4/assertables/macro.assert_fn_err_ge.html\n",
453                " a_function label: `f`,\n",
454                " b_function label: `g`,\n",
455                "                a: `1`,\n",
456                "                b: `2`"
457            );
458            assert_eq!(
459                result
460                    .unwrap_err()
461                    .downcast::<String>()
462                    .unwrap()
463                    .to_string(),
464                message
465            );
466        }
467    }
468}
469
470/// Assert a function error is greater than or equal to another.
471///
472/// Pseudocode:<br>
473/// (a_function(a_param) ⇒ Err(a) ⇒ a) ≥ (b_function(b_param) ⇒ Err(b) ⇒ b)
474///
475/// This macro provides the same statements as [`assert_fn_err_ge`](macro.assert_fn_err_ge.html),
476/// except this macro's statements are only enabled in non-optimized
477/// builds by default. An optimized build will not execute this macro's
478/// statements unless `-C debug-assertions` is passed to the compiler.
479///
480/// This macro is useful for checks that are too expensive to be present
481/// in a release build but may be helpful during development.
482///
483/// The result of expanding this macro is always type checked.
484///
485/// An unchecked assertion allows a program in an inconsistent state to
486/// keep running, which might have unexpected consequences but does not
487/// introduce unsafety as long as this only happens in safe code. The
488/// performance cost of assertions, however, is not measurable in general.
489/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
490/// after thorough profiling, and more importantly, only in safe code!
491///
492/// This macro is intended to work in a similar way to
493/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
494///
495/// # Module macros
496///
497/// * [`assert_fn_err_ge`](macro@crate::assert_fn_err_ge)
498/// * [`assert_fn_err_ge`](macro@crate::assert_fn_err_ge)
499/// * [`debug_assert_fn_err_ge`](macro@crate::debug_assert_fn_err_ge)
500///
501#[macro_export]
502macro_rules! debug_assert_fn_err_ge {
503    ($($arg:tt)*) => {
504        if $crate::cfg!(debug_assertions) {
505            $crate::assert_fn_err_ge!($($arg)*);
506        }
507    };
508}