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