assertables/assert_fn_ok/assert_fn_ok_lt_x.rs
1//! Assert a function Ok(…) is less than an expression.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Ok(a) ⇒ a) < expr
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 = 1;
18//! let b = String::from("2");
19//! assert_fn_ok_lt_x!(f, a, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_ok_lt_x`](macro@crate::assert_fn_ok_lt_x)
25//! * [`assert_fn_ok_lt_x_as_result`](macro@crate::assert_fn_ok_lt_x_as_result)
26//! * [`debug_assert_fn_ok_lt_x`](macro@crate::debug_assert_fn_ok_lt_x)
27
28/// Assert a function Ok(…) is less than an expression.
29///
30/// Pseudocode:<br>
31/// (a_function(a_param) ⇒ Ok(a) ⇒ a) < expr
32///
33/// * If true, return Result `Ok(a)`.
34///
35/// * Otherwise, return Result `Err(message)`.
36///
37/// # Examples
38///
39/// This macro is useful for runtime checks, such as checking parameters,
40/// or sanitizing inputs, or handling different results in different ways.
41///
42/// # Module macros
43///
44/// * [`assert_fn_ok_lt_x`](macro@crate::assert_fn_ok_lt_x)
45/// * [`assert_fn_ok_lt_x_as_result`](macro@crate::assert_fn_ok_lt_x_as_result)
46/// * [`debug_assert_fn_ok_lt_x`](macro@crate::debug_assert_fn_ok_lt_x)
47///
48#[macro_export]
49macro_rules! assert_fn_ok_lt_x_as_result {
50
51 //// Arity 1
52
53 ($a_function:path, $a_param:expr, $b_expr:expr $(,)?) => {{
54 match (&$a_function, &$a_param, &$b_expr) {
55 (_a_function, a_param, b_expr) => {
56 match ($a_function($a_param)) {
57 Ok(a) => {
58 if a < $b_expr {
59 Ok(a)
60 } else {
61 Err(
62 format!(
63 concat!(
64 "assertion failed: `assert_fn_ok_lt_x!(a_function, a_param, b_expr)`\n",
65 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
66 " a_function label: `{}`,\n",
67 " a_param label: `{}`,\n",
68 " a_param debug: `{:?}`,\n",
69 " b_expr label: `{}`,\n",
70 " b_expr debug: `{:?}`,\n",
71 " a: `{:?}`,\n",
72 " b: `{:?}`",
73 ),
74 stringify!($a_function),
75 stringify!($a_param),
76 a_param,
77 stringify!($b_expr),
78 b_expr,
79 a,
80 $b_expr
81 )
82 )
83 }
84 },
85 Err(a) => {
86 Err(
87 format!(
88 concat!(
89 "assertion failed: `assert_fn_ok_le_x!(a_function, a_param, b_expr)`\n",
90 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_le_x.html\n",
91 " a_function label: `{}`,\n",
92 " a_param label: `{}`,\n",
93 " a_param debug: `{:?}`,\n",
94 " b_expr label: `{}`,\n",
95 " b_expr debug: `{:?}`,\n",
96 " a: `{:?}`",
97 ),
98 stringify!($a_function),
99 stringify!($a_param),
100 a_param,
101 stringify!($b_expr),
102 b_expr,
103 a
104 )
105 )
106 }
107 }
108 }
109 }
110 }};
111
112 //// Arity 0
113
114 ($a_function:path, $b_expr:expr $(,)?) => {{
115 match (&$a_function, &$b_expr) {
116 (_a_function, b_expr) => {
117 match ($a_function()) {
118 Ok(a) => {
119 if a < $b_expr {
120 Ok(a)
121 } else {
122 Err(
123 format!(
124 concat!(
125 "assertion failed: `assert_fn_ok_lt_x!(a_function, b_expr)`\n",
126 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
127 " a_function label: `{}`,\n",
128 " b_expr label: `{}`,\n",
129 " b_expr debug: `{:?}`,\n",
130 " a: `{:?}`,\n",
131 " b: `{:?}`",
132 ),
133 stringify!($a_function),
134 stringify!($b_expr),
135 b_expr,
136 a,
137 $b_expr
138 )
139 )
140 }
141 },
142 a => {
143 Err(
144 format!(
145 concat!(
146 "assertion failed: `assert_fn_ok_le_x!(a_function, b_expr)`\n",
147 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_le_x.html\n",
148 " a_function label: `{}`,\n",
149 " b_expr label: `{}`,\n",
150 " b_expr debug: `{:?}`,\n",
151 " a result: `{:?}`",
152 ),
153 stringify!($a_function),
154 stringify!($b_expr),
155 b_expr,
156 a
157 )
158 )
159 }
160 }
161 }
162 }
163 }};
164
165}
166
167#[cfg(test)]
168mod test_assert_fn_ok_lt_x_as_result {
169
170 mod arity_1 {
171
172 fn f(i: i8) -> Result<i8, i8> {
173 return Ok(i);
174 }
175
176 #[test]
177 fn lt() {
178 let a: i8 = 1;
179 let b: i8 = 2;
180 let actual = assert_fn_ok_lt_x_as_result!(f, a, b);
181 assert_eq!(actual.unwrap(), 1);
182 }
183
184 #[test]
185 fn eq() {
186 let a: i8 = 1;
187 let b: i8 = 1;
188 let actual = assert_fn_ok_lt_x_as_result!(f, a, b);
189 let message = concat!(
190 "assertion failed: `assert_fn_ok_lt_x!(a_function, a_param, b_expr)`\n",
191 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
192 " a_function label: `f`,\n",
193 " a_param label: `a`,\n",
194 " a_param debug: `1`,\n",
195 " b_expr label: `b`,\n",
196 " b_expr debug: `1`,\n",
197 " a: `1`,\n",
198 " b: `1`"
199 );
200 assert_eq!(actual.unwrap_err(), message);
201 }
202 }
203
204 mod arity_0 {
205
206 fn f() -> Result<i8, i8> {
207 return Ok(1);
208 }
209
210 #[test]
211 fn lt() {
212 let b: i8 = 2;
213 let actual = assert_fn_ok_lt_x_as_result!(f, b);
214 assert_eq!(actual.unwrap(), 1);
215 }
216
217 #[test]
218 fn eq() {
219 let b: i8 = 1;
220 let actual = assert_fn_ok_lt_x_as_result!(f, b);
221 let message = concat!(
222 "assertion failed: `assert_fn_ok_lt_x!(a_function, b_expr)`\n",
223 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
224 " a_function label: `f`,\n",
225 " b_expr label: `b`,\n",
226 " b_expr debug: `1`,\n",
227 " a: `1`,\n",
228 " b: `1`"
229 );
230 assert_eq!(actual.unwrap_err(), message);
231 }
232 }
233}
234
235/// Assert a function Ok(…) is less than an expression.
236///
237/// Pseudocode:<br>
238/// (a_function(a_param) ⇒ Ok(a) ⇒ a) < expr
239///
240/// * If true, return `a`.
241///
242/// * Otherwise, call [`panic!`] with a message and the values of the
243/// expressions with their debug representations.
244///
245/// # Examples
246///
247/// ```rust
248/// use assertables::*;
249/// # use std::panic;
250/// fn f(i: i8) -> Result<String, String> {
251/// match i {
252/// 0..=9 => Ok(format!("{}", i)),
253/// _ => Err(format!("{:?} is out of range", i)),
254/// }
255/// }
256///
257/// # fn main() {
258/// let a: i8 = 1;
259/// let b = String::from("2");
260/// assert_fn_ok_lt_x!(f, a, b);
261///
262/// # let result = panic::catch_unwind(|| {
263/// // This will panic
264/// let a: i8 = 2;
265/// let b = String::from("1");
266/// assert_fn_ok_lt_x!(f, a, b);
267/// # });
268/// // assertion failed: `assert_fn_ok_lt_x!(a_function, a_param, b_expr)`
269/// // https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html
270/// // a_function label: `f`,
271/// // a_param label: `a`,
272/// // a_param debug: `2`,
273/// // b_expr label: `b`,
274/// // b_expr debug: `\"1\"`,
275/// // a: `\"2\"`,
276/// // b: `\"1\"`
277/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
278/// # let message = concat!(
279/// # "assertion failed: `assert_fn_ok_lt_x!(a_function, a_param, b_expr)`\n",
280/// # "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
281/// # " a_function label: `f`,\n",
282/// # " a_param label: `a`,\n",
283/// # " a_param debug: `2`,\n",
284/// # " b_expr label: `b`,\n",
285/// # " b_expr debug: `\"1\"`,\n",
286/// # " a: `\"2\"`,\n",
287/// # " b: `\"1\"`"
288/// # );
289/// # assert_eq!(actual, message);
290/// # }
291/// ```
292///
293/// # Module macros
294///
295/// * [`assert_fn_ok_lt_x`](macro@crate::assert_fn_ok_lt_x)
296/// * [`assert_fn_ok_lt_x_as_result`](macro@crate::assert_fn_ok_lt_x_as_result)
297/// * [`debug_assert_fn_ok_lt_x`](macro@crate::debug_assert_fn_ok_lt_x)
298///
299#[macro_export]
300macro_rules! assert_fn_ok_lt_x {
301
302 //// Arity 1
303
304 ($a_function:path, $a_param:expr, $b_expr:expr $(,)?) => {{
305 match $crate::assert_fn_ok_lt_x_as_result!($a_function, $a_param, $b_expr) {
306 Ok(x) => x,
307 Err(err) => panic!("{}", err),
308 }
309 }};
310
311 ($a_function:path, $a_param:expr, $b_expr:expr, $($message:tt)+) => {{
312 match $crate::assert_fn_ok_lt_x_as_result!($a_function, $a_param, $b_expr) {
313 Ok(x) => x,
314 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
315 }
316 }};
317
318 //// Arity 0
319
320 ($a_function:path, $b_expr:expr $(,)?) => {{
321 match $crate::assert_fn_ok_lt_x_as_result!($a_function, $b_expr) {
322 Ok(x) => x,
323 Err(err) => panic!("{}", err),
324 }
325 }};
326
327 ($a_function:path, $b_expr:expr, $($message:tt)+) => {{
328 match $crate::assert_fn_ok_lt_x_as_result!($a_function, $b_expr) {
329 Ok(x) => x,
330 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
331 }
332 }};
333}
334
335#[cfg(test)]
336mod test_assert_fn_ok_lt_x {
337 use std::panic;
338
339 mod arity_1 {
340 use super::*;
341
342 fn f(i: i8) -> Result<i8, i8> {
343 return Ok(i);
344 }
345
346 #[test]
347 fn lt() {
348 let a: i8 = 1;
349 let b: i8 = 2;
350 let actual = assert_fn_ok_lt_x!(f, a, b);
351 assert_eq!(actual, 1);
352 }
353
354 #[test]
355 fn eq() {
356 let result = panic::catch_unwind(|| {
357 let a: i8 = 1;
358 let b: i8 = 1;
359 let _actual = assert_fn_ok_lt_x!(f, a, b);
360 });
361 let message = concat!(
362 "assertion failed: `assert_fn_ok_lt_x!(a_function, a_param, b_expr)`\n",
363 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
364 " a_function label: `f`,\n",
365 " a_param label: `a`,\n",
366 " a_param debug: `1`,\n",
367 " b_expr label: `b`,\n",
368 " b_expr debug: `1`,\n",
369 " a: `1`,\n",
370 " b: `1`"
371 );
372 assert_eq!(
373 result
374 .unwrap_err()
375 .downcast::<String>()
376 .unwrap()
377 .to_string(),
378 message
379 );
380 }
381 }
382
383 mod arity_0 {
384 use super::*;
385
386 fn f() -> Result<i8, i8> {
387 return Ok(1);
388 }
389
390 #[test]
391 fn lt() {
392 let b: i8 = 2;
393 let actual = assert_fn_ok_lt_x!(f, b);
394 assert_eq!(actual, 1);
395 }
396
397 #[test]
398 fn eq() {
399 let result = panic::catch_unwind(|| {
400 let b: i8 = 1;
401 let _actual = assert_fn_ok_lt_x!(f, b);
402 });
403 let message = concat!(
404 "assertion failed: `assert_fn_ok_lt_x!(a_function, b_expr)`\n",
405 "https://docs.rs/assertables/9.5.0/assertables/macro.assert_fn_ok_lt_x.html\n",
406 " a_function label: `f`,\n",
407 " b_expr label: `b`,\n",
408 " b_expr debug: `1`,\n",
409 " a: `1`,\n",
410 " b: `1`"
411 );
412 assert_eq!(
413 result
414 .unwrap_err()
415 .downcast::<String>()
416 .unwrap()
417 .to_string(),
418 message
419 );
420 }
421 }
422}
423
424/// Assert a function Ok(…) is less than an expression.
425///
426/// Pseudocode:<br>
427/// (a_function(a_param) ⇒ Ok(a) ⇒ a) < expr
428///
429/// This macro provides the same statements as [`assert_fn_ok_lt_x`](macro.assert_fn_ok_lt_x.html),
430/// except this macro's statements are only enabled in non-optimized
431/// builds by default. An optimized build will not execute this macro's
432/// statements unless `-C debug-assertions` is passed to the compiler.
433///
434/// This macro is useful for checks that are too expensive to be present
435/// in a release build but may be helpful during development.
436///
437/// The result of expanding this macro is always type checked.
438///
439/// An unchecked assertion allows a program in an inconsistent state to
440/// keep running, which might have unexpected consequences but does not
441/// introduce unsafety as long as this only happens in safe code. The
442/// performance cost of assertions, however, is not measurable in general.
443/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
444/// after thorough profiling, and more importantly, only in safe code!
445///
446/// This macro is intended to work in a similar way to
447/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
448///
449/// # Module macros
450///
451/// * [`assert_fn_ok_lt_x`](macro@crate::assert_fn_ok_lt_x)
452/// * [`assert_fn_ok_lt_x`](macro@crate::assert_fn_ok_lt_x)
453/// * [`debug_assert_fn_ok_lt_x`](macro@crate::debug_assert_fn_ok_lt_x)
454///
455#[macro_export]
456macro_rules! debug_assert_fn_ok_lt_x {
457 ($($arg:tt)*) => {
458 if $crate::cfg!(debug_assertions) {
459 $crate::assert_fn_ok_lt_x!($($arg)*);
460 }
461 };
462}