assertables/assert_fn_err/assert_fn_err_lt.rs
1//! Assert a function Err(…) is less than another.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Err(a) ⇒ a) < (b_function(b_param) ⇒ Err(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 = 10;
18//! let b: i8 = 20;
19//! assert_fn_err_lt!(f, a, f, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
25//! * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
26//! * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
27
28/// Assert a function error is less than another.
29///
30/// * If true, return Result `Ok(a)`.
31///
32/// * Otherwise, return Result `Err(message)`.
33///
34/// This macro is useful for runtime checks, such as checking parameters,
35/// or sanitizing inputs, or handling different results in different ways.
36///
37/// # Module macros
38///
39/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
40/// * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
41/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
42///
43#[macro_export]
44macro_rules! assert_fn_err_lt_as_result {
45
46 //// Arity 1
47
48 ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {
49 match (&$a_function, &$a_param, &$b_function, &$b_param) {
50 (_a_function, a_param, _b_function, b_param) => {
51 match (
52 $a_function($a_param),
53 $b_function($b_param)
54 ) {
55 (Err(a), Err(b)) => {
56 if a < b {
57 Ok((a, b))
58 } else {
59 Err(
60 format!(
61 concat!(
62 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
63 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
64 " a_function label: `{}`,\n",
65 " a_param label: `{}`,\n",
66 " a_param debug: `{:?}`,\n",
67 " b_function label: `{}`,\n",
68 " b_param label: `{}`,\n",
69 " b_param debug: `{:?}`,\n",
70 " a: `{:?}`,\n",
71 " b: `{:?}`"
72 ),
73 stringify!($a_function),
74 stringify!($a_param),
75 a_param,
76 stringify!($b_function),
77 stringify!($b_param),
78 b_param,
79 a,
80 b
81 )
82 )
83 }
84 },
85 (a, b) => {
86 Err(
87 format!(
88 concat!(
89 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
90 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
91 " a_function label: `{}`,\n",
92 " a_param label: `{}`,\n",
93 " a_param debug: `{:?}`,\n",
94 " b_function label: `{}`,\n",
95 " b_param label: `{}`,\n",
96 " b_param debug: `{:?}`,\n",
97 " a: `{:?}`,\n",
98 " b: `{:?}`"
99 ),
100 stringify!($a_function),
101 stringify!($a_param),
102 a_param,
103 stringify!($b_function),
104 stringify!($b_param),
105 b_param,
106 a,
107 b
108 )
109 )
110 }
111 }
112 }
113 }
114 };
115
116 //// Arity 0
117
118 ($a_function:path, $b_function:path) => {
119 match (
120 $a_function(),
121 $b_function()
122 ) {
123 (Err(a), Err(b)) => {
124 if a < b {
125 Ok((a, b))
126 } else {
127 Err(
128 format!(
129 concat!(
130 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
131 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
132 " a_function label: `{}`,\n",
133 " b_function label: `{}`,\n",
134 " a: `{:?}`,\n",
135 " b: `{:?}`"
136 ),
137 stringify!($a_function),
138 stringify!($b_function),
139 a,
140 b
141 )
142 )
143 }
144 },
145 (a, b) => {
146 Err(
147 format!(
148 concat!(
149 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
150 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
151 " a_function label: `{}`,\n",
152 " b_function label: `{}`,\n",
153 " a: `{:?}`,\n",
154 " b: `{:?}`"
155 ),
156 stringify!($a_function),
157 stringify!($b_function),
158 a,
159 b
160 )
161 )
162 }
163 }
164 };
165
166}
167
168#[cfg(test)]
169mod test_assert_fn_err_lt_as_result {
170 // use std::sync::Once;
171
172 mod arity_1 {
173
174 fn f(i: i8) -> Result<i8, i8> {
175 Err(i)
176 }
177
178 fn g(i: i8) -> Result<i8, i8> {
179 Err(i)
180 }
181
182 #[test]
183 fn lt() {
184 let a: i8 = 1;
185 let b: i8 = 2;
186 for _ in 0..1 {
187 let actual = assert_fn_err_lt_as_result!(f, a, g, b);
188 assert_eq!(actual.unwrap(), (1, 2));
189 }
190 }
191
192 #[test]
193 fn eq() {
194 let a: i8 = 1;
195 let b: i8 = 1;
196 let actual = assert_fn_err_lt_as_result!(f, a, g, b);
197 let message = concat!(
198 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
199 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
200 " a_function label: `f`,\n",
201 " a_param label: `a`,\n",
202 " a_param debug: `1`,\n",
203 " b_function label: `g`,\n",
204 " b_param label: `b`,\n",
205 " b_param debug: `1`,\n",
206 " a: `1`,\n",
207 " b: `1`"
208 );
209 assert_eq!(actual.unwrap_err(), message);
210 }
211
212 #[test]
213 fn gt() {
214 let a: i8 = 2;
215 let b: i8 = 1;
216 let actual = assert_fn_err_lt_as_result!(f, a, g, b);
217 let message = concat!(
218 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
219 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
220 " a_function label: `f`,\n",
221 " a_param label: `a`,\n",
222 " a_param debug: `2`,\n",
223 " b_function label: `g`,\n",
224 " b_param label: `b`,\n",
225 " b_param debug: `1`,\n",
226 " a: `2`,\n",
227 " b: `1`"
228 );
229 assert_eq!(actual.unwrap_err(), message);
230 }
231 }
232
233 mod arity_0 {
234
235 fn f() -> Result<i8, i8> {
236 Err(1)
237 }
238
239 fn g() -> Result<i8, i8> {
240 Err(2)
241 }
242
243 #[test]
244 fn lt() {
245 for _ in 0..1 {
246 let actual = assert_fn_err_lt_as_result!(f, g);
247 assert_eq!(actual.unwrap(), (1, 2));
248 }
249 }
250
251 #[test]
252 fn eq() {
253 let actual = assert_fn_err_lt_as_result!(f, f);
254 let message = concat!(
255 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
256 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
257 " a_function label: `f`,\n",
258 " b_function label: `f`,\n",
259 " a: `1`,\n",
260 " b: `1`"
261 );
262 assert_eq!(actual.unwrap_err(), message);
263 }
264
265 #[test]
266 fn gt() {
267 let actual = assert_fn_err_lt_as_result!(g, f);
268 let message = concat!(
269 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
270 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
271 " a_function label: `g`,\n",
272 " b_function label: `f`,\n",
273 " a: `2`,\n",
274 " b: `1`"
275 );
276 assert_eq!(actual.unwrap_err(), message);
277 }
278 }
279}
280
281/// Assert a function error is less than another.
282///
283/// * If true, return `(a, b)`.
284///
285/// * Otherwise, call [`panic!`] with a message and the values of the
286/// expressions with their debug representations.
287///
288/// # Examples
289///
290/// ```rust
291/// use assertables::*;
292/// # use std::panic;
293/// fn f(i: i8) -> Result<String, String> {
294/// match i {
295/// 0..=9 => Ok(format!("{}", i)),
296/// _ => Err(format!("{:?} is out of range", i)),
297/// }
298/// }
299///
300/// # fn main() {
301/// let a: i8 = 10;
302/// let b: i8 = 20;
303/// assert_fn_err_lt!(f, a, f, b);
304///
305/// # let result = panic::catch_unwind(|| {
306/// // This will panic
307/// let a: i8 = 20;
308/// let b: i8 = 10;
309/// assert_fn_err_lt!(f, a, f, b);
310/// # });
311/// // assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`
312/// // https://docs.rs/assertables/…/assertables/macro.assert_fn_err_lt.html
313/// // a_function label: `f`,
314/// // a_param label: `a`,
315/// // a_param debug: `20`,
316/// // b_function label: `f`,
317/// // b_param label: `b`,
318/// // b_param debug: `10`,
319/// // a: `\"20 is out of range\"`,
320/// // b: `\"10 is out of range\"`
321/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
322/// # let message = concat!(
323/// # "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
324/// # "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
325/// # " a_function label: `f`,\n",
326/// # " a_param label: `a`,\n",
327/// # " a_param debug: `20`,\n",
328/// # " b_function label: `f`,\n",
329/// # " b_param label: `b`,\n",
330/// # " b_param debug: `10`,\n",
331/// # " a: `\"20 is out of range\"`,\n",
332/// # " b: `\"10 is out of range\"`"
333/// # );
334/// # assert_eq!(actual, message);
335/// # }
336/// ```
337///
338/// # Module macros
339///
340/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
341/// * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
342/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
343///
344#[macro_export]
345macro_rules! assert_fn_err_lt {
346
347 //// Arity 1
348
349 ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {
350 match $crate::assert_fn_err_lt_as_result!($a_function, $a_param, $b_function, $b_param) {
351 Ok(x) => x,
352 Err(err) => panic!("{}", err),
353 }
354 };
355
356 ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr, $($message:tt)+) => {
357 match $crate::assert_fn_err_lt_as_result!($a_function, $a_param, $b_function, $b_param) {
358 Ok(x) => x,
359 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
360 }
361 };
362
363 //// Arity 0
364
365 ($a_function:path, $b_function:path) => {
366 match $crate::assert_fn_err_lt_as_result!($a_function, $b_function) {
367 Ok(x) => x,
368 Err(err) => panic!("{}", err),
369 }
370 };
371
372 ($a_function:path, $b_function:path, $($message:tt)+) => {
373 match $crate::assert_fn_err_lt_as_result!($a_function, $b_function) {
374 Ok(x) => x,
375 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
376 }
377 };
378}
379
380#[cfg(test)]
381mod test_assert_fn_err_lt {
382 use std::panic;
383
384 mod arity_1 {
385 use super::*;
386
387 fn f(i: i8) -> Result<i8, i8> {
388 Err(i)
389 }
390
391 fn g(i: i8) -> Result<i8, i8> {
392 Err(i)
393 }
394
395 #[test]
396 fn lt() {
397 let a: i8 = 1;
398 let b: i8 = 2;
399 for _ in 0..1 {
400 let actual = assert_fn_err_lt!(f, a, g, b);
401 assert_eq!(actual, (1, 2));
402 }
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_err_lt!(f, a, g, b);
411 });
412 let message = concat!(
413 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
414 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.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 gt() {
436 let result = panic::catch_unwind(|| {
437 let a: i8 = 2;
438 let b: i8 = 1;
439 let _actual = assert_fn_err_lt!(f, a, g, b);
440 });
441 let message = concat!(
442 "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
443 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
444 " a_function label: `f`,\n",
445 " a_param label: `a`,\n",
446 " a_param debug: `2`,\n",
447 " b_function label: `g`,\n",
448 " b_param label: `b`,\n",
449 " b_param debug: `1`,\n",
450 " a: `2`,\n",
451 " b: `1`"
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 Err(1)
469 }
470
471 fn g() -> Result<i8, i8> {
472 Err(2)
473 }
474
475 #[test]
476 fn lt() {
477 for _ in 0..1 {
478 let actual = assert_fn_err_lt!(f, g);
479 assert_eq!(actual, (1, 2));
480 }
481 }
482
483 #[test]
484 fn eq() {
485 let result = panic::catch_unwind(|| {
486 let _actual = assert_fn_err_lt!(f, f);
487 });
488 let message = concat!(
489 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
490 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
491 " a_function label: `f`,\n",
492 " b_function label: `f`,\n",
493 " a: `1`,\n",
494 " b: `1`"
495 );
496 assert_eq!(
497 result
498 .unwrap_err()
499 .downcast::<String>()
500 .unwrap()
501 .to_string(),
502 message
503 );
504 }
505
506 #[test]
507 fn gt() {
508 let result = panic::catch_unwind(|| {
509 let _actual = assert_fn_err_lt!(g, f);
510 });
511 let message = concat!(
512 "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
513 "https://docs.rs/assertables/9.8.1/assertables/macro.assert_fn_err_lt.html\n",
514 " a_function label: `g`,\n",
515 " b_function label: `f`,\n",
516 " a: `2`,\n",
517 " b: `1`"
518 );
519 assert_eq!(
520 result
521 .unwrap_err()
522 .downcast::<String>()
523 .unwrap()
524 .to_string(),
525 message
526 );
527 }
528 }
529}
530
531/// Assert a function error is less than another.
532///
533/// This macro provides the same statements as [`assert_fn_err_lt`](macro.assert_fn_err_lt.html),
534/// except this macro's statements are only enabled in non-optimized
535/// builds by default. An optimized build will not execute this macro's
536/// statements unless `-C debug-assertions` is passed to the compiler.
537///
538/// This macro is useful for checks that are too expensive to be present
539/// in a release build but may be helpful during development.
540///
541/// The result of expanding this macro is always type checked.
542///
543/// An unchecked assertion allows a program in an inconsistent state to
544/// keep running, which might have unexpected consequences but does not
545/// introduce unsafety as long as this only happens in safe code. The
546/// performance cost of assertions, however, is not measurable in general.
547/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
548/// after thorough profiling, and more importantly, only in safe code!
549///
550/// This macro is intended to work in a similar way to
551/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
552///
553/// # Module macros
554///
555/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
556/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
557/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
558///
559#[macro_export]
560macro_rules! debug_assert_fn_err_lt {
561 ($($arg:tt)*) => {
562 if $crate::cfg!(debug_assertions) {
563 $crate::assert_fn_err_lt!($($arg)*);
564 }
565 };
566}