assertables/
assert_infix.rs

1//! Assert a infix operator, such as assert_infix!(a == b).
2//!
3//! Pseudocode:<br>
4//! a infix b
5//!
6//! Compare values via infix value operator:
7//!
8//! * `assert_infix!(a == b)` ≈ a == b
9//!
10//! * `assert_infix!(a != b)` ≈ a ≠ b
11//!
12//! * `assert_infix!(a < b)` ≈ a < b
13//!
14//! * `assert_infix!(a <= b)` ≈ a ≤ b
15//!
16//! * `assert_infix!(a > b)` ≈ a > b
17//!
18//! * `assert_infix!(a >= b)` ≈ a ≥ b
19//!
20//! Relate values via infix logical operator:
21//!
22//! * `assert_infix!(a & b)` ≈ a ∧ b ≈ a AND b
23//!
24//! * `assert_infix!(a | b)` ≈ a ∨ b ≈ a OR b
25//!
26//! * `assert_infix!(a ^ b)` ≈ a ⊻ b ≈ a XOR b
27//!
28//! * `assert_infix!(a && b)` ≈ a …∧ b ≈ a lazy AND b
29//!
30//! * `assert_infix!(a || b)` ≈ a …∨ b ≈ a lazy OR b
31//!
32//! # Example
33//!
34//! ```rust
35//! use assertables::*;
36//!
37//! let a = 1;
38//! let b = 1;
39//! assert_infix!(a == b);
40//! ```
41//!
42//! # Infix operators
43//!
44//! For values:
45//!
46//! * `==`  equal
47//! * `!=`  not equal
48//! * `<`	less than
49//! * `<=`	less than or equal to
50//! * `>`	greater than
51//! * `>=`	greater than or equal to
52//!
53//! For booleans:
54//!
55//! * `^`	logical XOR
56//! * `!`	logical NOT
57//! * `&`	logical AND
58//! * `|`	logical OR
59//! * `&&`	logical lazy AND
60//! * `||`	logical lazy OR
61//!
62//! # Module macros
63//!
64//! * [`assert_infix`](macro@crate::assert_infix)
65//! * [`assert_infix_as_result`](macro@crate::assert_infix_as_result)
66//! * [`debug_assert_infix`](macro@crate::debug_assert_infix)
67
68/// Assert a infix operator, such as assert_infix!(a == b).
69///
70/// Pseudocode:<br>
71/// a infix b
72///
73/// * If true, return Result `Ok(())`.
74///
75/// * Otherwise, return Result `Err(message)`.
76///
77/// This macro is useful for runtime checks, such as checking parameters,
78/// or sanitizing inputs, or handling different results in different ways.
79///
80/// # Module macros
81///
82/// * [`assert_infix`](macro@crate::assert_infix)
83/// * [`assert_infix_as_result`](macro@crate::assert_infix_as_result)
84/// * [`debug_assert_infix`](macro@crate::debug_assert_infix)
85///
86#[macro_export]
87macro_rules! assert_infix_as_result {
88    ($a:tt $infix:tt $b:tt) => {
89        if $a $infix $b {
90            Ok(())
91        } else {
92            Err(
93                format!(
94                    concat!(
95                        "assertion failed: `assert_infix!(a {} b)`\n",
96                        "https://docs.rs/assertables/9.8.2/assertables/macro.assert_infix.html\n",
97                        " a label: `{}`,\n",
98                        " a debug: `{:?}`,\n",
99                        " b label: `{}`,\n",
100                        " b debug: `{:?}`",
101                    ),
102                    stringify!($infix),
103                    stringify!($a),
104                    $a,
105                    stringify!($b),
106                    $b,
107                )
108            )
109        }
110    };
111}
112
113#[cfg(test)]
114mod test_assert_infix_as_result {
115    // use std::sync::Once;
116
117    #[test]
118    fn success() {
119        let a: i8 = 1;
120        let b: i8 = 1;
121        for _ in 0..1 {
122            let actual = assert_infix_as_result!(a == b);
123            assert_eq!(actual.unwrap(), ());
124        }
125    }
126
127    #[test]
128    fn failure() {
129        let a: i8 = 1;
130        let b: i8 = 2;
131        let actual = assert_infix_as_result!(a == b);
132        let message = concat!(
133            "assertion failed: `assert_infix!(a == b)`\n",
134            "https://docs.rs/assertables/9.8.2/assertables/macro.assert_infix.html\n",
135            " a label: `a`,\n",
136            " a debug: `1`,\n",
137            " b label: `b`,\n",
138            " b debug: `2`",
139        );
140        assert_eq!(actual.unwrap_err(), message);
141    }
142}
143
144/// Assert a infix operator, such as assert_infix!(a == b).
145///
146/// Pseudocode:<br>
147/// a infix b
148///
149/// * If true, return `()`.
150///
151/// * Otherwise, call [`panic!`] with a message and the values of the
152///   expressions with their debug representations.
153///
154/// # Examples
155///
156/// ```rust
157/// use assertables::*;
158/// # use std::panic;
159///
160/// # fn main() {
161/// let a = 1;
162/// let b = 1;
163/// assert_infix!(a == b);
164///
165/// # let result = panic::catch_unwind(|| {
166/// // This will panic
167/// let a = 1;
168/// let b = 2;
169/// assert_infix!(a == b);
170/// # });
171/// // assertion failed: `assert_infix!(a == b)`
172/// // https://docs.rs/assertables/…/assertables/macro.assert_infix.html
173/// //  a label: `a`,
174/// //  a debug: `1`,
175/// //  b label: `b`,
176/// //  b debug: `2`
177/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
178/// # let message = concat!(
179/// #     "assertion failed: `assert_infix!(a == b)`\n",
180/// #     "https://docs.rs/assertables/9.8.2/assertables/macro.assert_infix.html\n",
181/// #     " a label: `a`,\n",
182/// #     " a debug: `1`,\n",
183/// #     " b label: `b`,\n",
184/// #     " b debug: `2`",
185/// # );
186/// # assert_eq!(actual, message);
187/// # }
188/// ```
189///
190/// # Infix operators
191///
192/// For values:
193///
194/// * `==`  equal
195/// * `!=`  not equal
196/// * `<`	less than
197/// * `<=`	less than or equal to
198/// * `>`	greater than
199/// * `>=`	greater than or equal to
200///
201/// For booleans:
202///
203/// * `^`	logical XOR
204/// * `!`	logical NOT
205/// * `&`	logical AND
206/// * `|`	logical OR
207/// * `&&`	logical lazy AND
208/// * `||`	logical lazy OR
209///
210/// # Module macros
211///
212/// * [`assert_infix`](macro@crate::assert_infix)
213/// * [`assert_infix_as_result`](macro@crate::assert_infix_as_result)
214/// * [`debug_assert_infix`](macro@crate::debug_assert_infix)
215///
216#[macro_export]
217macro_rules! assert_infix {
218    ($a:tt $infix:tt $b:tt) => {
219        match $crate::assert_infix_as_result!($a $infix $b) {
220            Ok(()) => (),
221            Err(err) => panic!("{}", err),
222        }
223    };
224    ($a:tt $infix:tt $b:tt, $($message:tt)+) => {
225        match $crate::assert_infix_as_result!($a $infix $b) {
226            Ok(()) => (),
227            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
228        }
229    };
230}
231
232#[cfg(test)]
233mod test_assert_infix {
234    use std::panic;
235
236    #[test]
237    fn success() {
238        let a: i8 = 1;
239        let b: i8 = 1;
240        for _ in 0..1 {
241            let actual = assert_infix!(a == b);
242            assert_eq!(actual, ());
243        }
244    }
245
246    #[test]
247    fn failure() {
248        let a: i8 = 1;
249        let b: i8 = 2;
250        let result = panic::catch_unwind(|| {
251            let _actual = assert_infix!(a == b);
252        });
253        let message = concat!(
254            "assertion failed: `assert_infix!(a == b)`\n",
255            "https://docs.rs/assertables/9.8.2/assertables/macro.assert_infix.html\n",
256            " a label: `a`,\n",
257            " a debug: `1`,\n",
258            " b label: `b`,\n",
259            " b debug: `2`",
260        );
261        assert_eq!(
262            result
263                .unwrap_err()
264                .downcast::<String>()
265                .unwrap()
266                .to_string(),
267            message
268        );
269    }
270}
271
272/// Assert a infix operator, such as assert_infix!(a == b).
273///
274/// Pseudocode:<br>
275/// a infix b
276///
277/// This macro provides the same statements as [`assert_infix`](macro.assert_infix.html),
278/// except this macro's statements are only enabled in non-optimized
279/// builds by default. An optimized build will not execute this macro's
280/// statements unless `-C debug-assertions` is passed to the compiler.
281///
282/// This macro is useful for checks that are too expensive to be present
283/// in a release build but may be helpful during development.
284///
285/// The result of expanding this macro is always type checked.
286///
287/// An unchecked assertion allows a program in an inconsistent state to
288/// keep running, which might have unexpected consequences but does not
289/// introduce unsafety as long as this only happens in safe code. The
290/// performance cost of assertions, however, is not measurable in general.
291/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
292/// after thorough profiling, and more importantly, only in safe code!
293///
294/// This macro is intended to work in a similar way to
295/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
296///
297/// # Module macros
298///
299/// * [`assert_infix`](macro@crate::assert_infix)
300/// * [`assert_infix`](macro@crate::assert_infix)
301/// * [`debug_assert_infix`](macro@crate::debug_assert_infix)
302///
303#[macro_export]
304macro_rules! debug_assert_infix {
305    ($($arg:tt)*) => {
306        if $crate::cfg!(debug_assertions) {
307            $crate::assert_infix!($($arg)*);
308        }
309    };
310}