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}