assertables/assert_ready/
assert_ready_eq_x.rs

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