assertables/assert_fn_ok/
assert_fn_ok_gt.rs

1//! Assert a function Ok(…) is greater than another.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Ok(a) ⇒ a) > (b_function(b_param) ⇒ Ok(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 = 2;
18//! let b: i8 = 1;
19//! assert_fn_ok_gt!(f, a, f, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_ok_gt`](macro@crate::assert_fn_ok_gt)
25//! * [`assert_fn_ok_gt_as_result`](macro@crate::assert_fn_ok_gt_as_result)
26//! * [`debug_assert_fn_ok_gt`](macro@crate::debug_assert_fn_ok_gt)
27
28/// Assert a function Ok(…) is greater than another.
29///
30/// Pseudocode:<br>
31/// (a_function(a_param) ⇒ Ok(a) ⇒ a) > (b_function(b_param) ⇒ Ok(b) ⇒ b)
32///
33/// * If true, return Result `Ok(a, b)`.
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_ok_gt`](macro@crate::assert_fn_ok_gt)
43/// * [`assert_fn_ok_gt_as_result`](macro@crate::assert_fn_ok_gt_as_result)
44/// * [`debug_assert_fn_ok_gt`](macro@crate::debug_assert_fn_ok_gt)
45///
46#[macro_export]
47macro_rules! assert_fn_ok_gt_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                    (Ok(a), Ok(b)) => {
59                        if a > b {
60                            Ok((a, b))
61                        } else {
62                            Err(
63                                format!(
64                                    concat!(
65                                        "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
66                                        "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.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_gt!(a_function, a_param, b_function, b_param)`\n",
93                                    "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_err_gt.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            (Ok(a), Ok(b)) => {
127                if a > b {
128                    Ok((a, b))
129                } else {
130                    Err(
131                        format!(
132                            concat!(
133                                "assertion failed: `assert_fn_ok_gt!(a_function, b_function)`\n",
134                                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.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_gt!(a_function, b_function)`\n",
153                            "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_err_gt.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_ok_gt_as_result {
173    use std::sync::Once;
174
175    mod arity_1 {
176
177        fn f(i: i8) -> Result<i8, i8> {
178            return Ok(i);
179        }
180
181        fn g(i: i8) -> Result<i8, i8> {
182            return Ok(i);
183        }
184
185        #[test]
186        fn gt() {
187            let a: i8 = 2;
188            let b: i8 = 1;
189            let actual = assert_fn_ok_gt_as_result!(f, a, g, b);
190            assert_eq!(actual.unwrap(), (2, 1));
191        }
192
193        #[test]
194        fn eq() {
195            let a: i8 = 1;
196            let b: i8 = 1;
197            let actual = assert_fn_ok_gt_as_result!(f, a, g, b);
198            let message = concat!(
199                "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
200                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
201                " a_function label: `f`,\n",
202                "    a_param label: `a`,\n",
203                "    a_param debug: `1`,\n",
204                " b_function label: `g`,\n",
205                "    b_param label: `b`,\n",
206                "    b_param debug: `1`,\n",
207                "                a: `1`,\n",
208                "                b: `1`"
209            );
210            assert_eq!(actual.unwrap_err(), message);
211        }
212
213        #[test]
214        fn lt() {
215            let a: i8 = 1;
216            let b: i8 = 2;
217            let actual = assert_fn_ok_gt_as_result!(f, a, g, b);
218            let message = concat!(
219                "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
220                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
221                " a_function label: `f`,\n",
222                "    a_param label: `a`,\n",
223                "    a_param debug: `1`,\n",
224                " b_function label: `g`,\n",
225                "    b_param label: `b`,\n",
226                "    b_param debug: `2`,\n",
227                "                a: `1`,\n",
228                "                b: `2`"
229            );
230            assert_eq!(actual.unwrap_err(), message);
231        }
232    }
233
234    mod arity_0 {
235
236        fn f() -> Result<i8, i8> {
237            return Ok(1);
238        }
239
240        fn g() -> Result<i8, i8> {
241            return Ok(2);
242        }
243
244        #[test]
245        fn gt() {
246            let actual = assert_fn_ok_gt_as_result!(g, f);
247            assert_eq!(actual.unwrap(), (2, 1));
248        }
249
250        #[test]
251        fn eq() {
252            let actual = assert_fn_ok_gt_as_result!(f, f);
253            let message = concat!(
254                "assertion failed: `assert_fn_ok_gt!(a_function, b_function)`\n",
255                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
256                " a_function label: `f`,\n",
257                " b_function label: `f`,\n",
258                "                a: `1`,\n",
259                "                b: `1`"
260            );
261            assert_eq!(actual.unwrap_err(), message);
262        }
263
264        #[test]
265        fn lt() {
266            let actual = assert_fn_ok_gt_as_result!(f, g);
267            let message = concat!(
268                "assertion failed: `assert_fn_ok_gt!(a_function, b_function)`\n",
269                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
270                " a_function label: `f`,\n",
271                " b_function label: `g`,\n",
272                "                a: `1`,\n",
273                "                b: `2`"
274            );
275            assert_eq!(actual.unwrap_err(), message);
276        }
277    }
278}
279
280/// Assert a function Ok(…) is greater than another.
281///
282/// Pseudocode:<br>
283/// (a_function(a_param) ⇒ Ok(a) ⇒ a) > (b_function(b_param) ⇒ Ok(b) ⇒ b)
284///
285/// * If true, return `(a, b)`.
286///
287/// * Otherwise, call [`panic!`] with a message and the values of the
288///   expressions with their debug representations.
289///
290/// # Examples
291///
292/// ```rust
293/// use assertables::*;
294/// # use std::panic;
295/// fn f(i: i8) -> Result<String, String> {
296///     match i {
297///         0..=9 => Ok(format!("{}", i)),
298///         _ => Err(format!("{:?} is out of range", i)),
299///     }
300/// }
301///
302/// # fn main() {
303/// let a: i8 = 2;
304/// let b: i8 = 1;
305/// assert_fn_ok_gt!(f, a, f, b);
306///
307/// # let result = panic::catch_unwind(|| {
308/// // This will panic
309/// let a: i8 = 1;
310/// let b: i8 = 2;
311/// assert_fn_ok_gt!(f, a, f, b);
312/// # });
313/// // assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`
314/// // https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html
315/// //  a_function label: `f`,
316/// //     a_param label: `a`,
317/// //     a_param debug: `1`,
318/// //  b_function label: `f`,
319/// //     b_param label: `b`,
320/// //     b_param debug: `2`,
321/// //                 a: `\"1\"`,
322/// //                 b: `\"2\"`
323/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
324/// # let message = concat!(
325/// #     "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
326/// #     "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
327/// #     " a_function label: `f`,\n",
328/// #     "    a_param label: `a`,\n",
329/// #     "    a_param debug: `1`,\n",
330/// #     " b_function label: `f`,\n",
331/// #     "    b_param label: `b`,\n",
332/// #     "    b_param debug: `2`,\n",
333/// #     "                a: `\"1\"`,\n",
334/// #     "                b: `\"2\"`"
335/// # );
336/// # assert_eq!(actual, message);
337/// # }
338/// ```
339///
340/// # Module macros
341///
342/// * [`assert_fn_ok_gt`](macro@crate::assert_fn_ok_gt)
343/// * [`assert_fn_ok_gt_as_result`](macro@crate::assert_fn_ok_gt_as_result)
344/// * [`debug_assert_fn_ok_gt`](macro@crate::debug_assert_fn_ok_gt)
345///
346#[macro_export]
347macro_rules! assert_fn_ok_gt {
348
349    //// Arity 1
350
351    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {
352        match $crate::assert_fn_ok_gt_as_result!($a_function, $a_param, $b_function, $b_param) {
353            Ok(x) => x,
354            Err(err) => panic!("{}", err),
355        }
356    };
357
358    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr, $($message:tt)+) => {
359        match $crate::assert_fn_ok_gt_as_result!($a_function, $a_param, $b_function, $b_param) {
360            Ok(x) => x,
361            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
362        }
363    };
364
365    //// Arity 0
366
367    ($a_function:path, $b_function:path) => {
368        match $crate::assert_fn_ok_gt_as_result!($a_function, $b_function) {
369            Ok(x) => x,
370            Err(err) => panic!("{}", err),
371        }
372    };
373
374    ($a_function:path, $b_function:path, $($message:tt)+) => {
375        match $crate::assert_fn_ok_gt_as_result!($a_function, $b_function) {
376            Ok(x) => x,
377            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
378        }
379    };
380}
381
382#[cfg(test)]
383mod test_assert_fn_ok_gt {
384    use std::panic;
385
386    mod arity_1 {
387        use super::*;
388
389        fn f(i: i8) -> Result<i8, i8> {
390            return Ok(i);
391        }
392
393        fn g(i: i8) -> Result<i8, i8> {
394            return Ok(i);
395        }
396
397        #[test]
398        fn gt() {
399            let a: i8 = 2;
400            let b: i8 = 1;
401            let actual = assert_fn_ok_gt!(f, a, g, b);
402            assert_eq!(actual, (2, 1));
403        }
404
405        #[test]
406        fn eq() {
407            let result = panic::catch_unwind(|| {
408                let a: i8 = 1;
409                let b: i8 = 1;
410                let _actual = assert_fn_ok_gt!(f, a, g, b);
411            });
412            let message = concat!(
413                "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
414                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
415                " a_function label: `f`,\n",
416                "    a_param label: `a`,\n",
417                "    a_param debug: `1`,\n",
418                " b_function label: `g`,\n",
419                "    b_param label: `b`,\n",
420                "    b_param debug: `1`,\n",
421                "                a: `1`,\n",
422                "                b: `1`"
423            );
424            assert_eq!(
425                result
426                    .unwrap_err()
427                    .downcast::<String>()
428                    .unwrap()
429                    .to_string(),
430                message
431            );
432        }
433
434        #[test]
435        fn lt() {
436            let result = panic::catch_unwind(|| {
437                let a: i8 = 1;
438                let b: i8 = 2;
439                let _actual = assert_fn_ok_gt!(f, a, g, b);
440            });
441            let message = concat!(
442                "assertion failed: `assert_fn_ok_gt!(a_function, a_param, b_function, b_param)`\n",
443                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
444                " a_function label: `f`,\n",
445                "    a_param label: `a`,\n",
446                "    a_param debug: `1`,\n",
447                " b_function label: `g`,\n",
448                "    b_param label: `b`,\n",
449                "    b_param debug: `2`,\n",
450                "                a: `1`,\n",
451                "                b: `2`"
452            );
453            assert_eq!(
454                result
455                    .unwrap_err()
456                    .downcast::<String>()
457                    .unwrap()
458                    .to_string(),
459                message
460            );
461        }
462    }
463
464    mod arity_0 {
465        use super::*;
466
467        fn f() -> Result<i8, i8> {
468            return Ok(1);
469        }
470
471        fn g() -> Result<i8, i8> {
472            return Ok(2);
473        }
474
475        #[test]
476        fn gt() {
477            let actual = assert_fn_ok_gt!(g, f);
478            assert_eq!(actual, (2, 1));
479        }
480
481        #[test]
482        fn eq() {
483            let result = panic::catch_unwind(|| {
484                let _actual = assert_fn_ok_gt!(f, f);
485            });
486            let message = concat!(
487                "assertion failed: `assert_fn_ok_gt!(a_function, b_function)`\n",
488                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
489                " a_function label: `f`,\n",
490                " b_function label: `f`,\n",
491                "                a: `1`,\n",
492                "                b: `1`"
493            );
494            assert_eq!(
495                result
496                    .unwrap_err()
497                    .downcast::<String>()
498                    .unwrap()
499                    .to_string(),
500                message
501            );
502        }
503
504        #[test]
505        fn lt() {
506            let result = panic::catch_unwind(|| {
507                let _actual = assert_fn_ok_gt!(f, g);
508            });
509            let message = concat!(
510                "assertion failed: `assert_fn_ok_gt!(a_function, b_function)`\n",
511                "https://docs.rs/assertables/9.6.0/assertables/macro.assert_fn_ok_gt.html\n",
512                " a_function label: `f`,\n",
513                " b_function label: `g`,\n",
514                "                a: `1`,\n",
515                "                b: `2`"
516            );
517            assert_eq!(
518                result
519                    .unwrap_err()
520                    .downcast::<String>()
521                    .unwrap()
522                    .to_string(),
523                message
524            );
525        }
526    }
527}
528
529/// Assert a function Ok(…) is greater than another.
530///
531/// Pseudocode:<br>
532/// (a_function(a_param) ⇒ Ok(a) ⇒ a) > (b_function(b_param) ⇒ Ok(b) ⇒ b)
533///
534/// This macro provides the same statements as [`assert_fn_ok_gt`](macro.assert_fn_ok_gt.html),
535/// except this macro's statements are only enabled in non-optimized
536/// builds by default. An optimized build will not execute this macro's
537/// statements unless `-C debug-assertions` is passed to the compiler.
538///
539/// This macro is useful for checks that are too expensive to be present
540/// in a release build but may be helpful during development.
541///
542/// The result of expanding this macro is always type checked.
543///
544/// An unchecked assertion allows a program in an inconsistent state to
545/// keep running, which might have unexpected consequences but does not
546/// introduce unsafety as long as this only happens in safe code. The
547/// performance cost of assertions, however, is not measurable in general.
548/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
549/// after thorough profiling, and more importantly, only in safe code!
550///
551/// This macro is intended to work in a similar way to
552/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
553///
554/// # Module macros
555///
556/// * [`assert_fn_ok_gt`](macro@crate::assert_fn_ok_gt)
557/// * [`assert_fn_ok_gt`](macro@crate::assert_fn_ok_gt)
558/// * [`debug_assert_fn_ok_gt`](macro@crate::debug_assert_fn_ok_gt)
559///
560#[macro_export]
561macro_rules! debug_assert_fn_ok_gt {
562    ($($arg:tt)*) => {
563        if $crate::cfg!(debug_assertions) {
564            $crate::assert_fn_ok_gt!($($arg)*);
565        }
566    };
567}