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