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