more_asserts/lib.rs
1//! Small library providing some macros helpful for asserting. The API is very
2//! similar to the API provided by the stdlib's own
3//! [`assert_eq!`](core::assert_eq), [`assert_ne!`](core::assert_ne),
4//! [`debug_assert_eq!`](core::debug_assert_eq), and
5//! [`debug_assert_ne!`](core::debug_assert_ne).
6//!
7//! | Name | Enabled | Equivalent to |
8//! | -------------------- | ----------------------------- | -------------------------------------------- |
9//! | `assert_le!` | Always | `assert!(a <= b)` |
10//! | `assert_lt!` | Always | `assert!(a < b)` |
11//! | `assert_ge!` | Always | `assert!(a >= b)` |
12//! | `assert_gt!` | Always | `assert!(a > b)` |
13//! | `debug_assert_le!` | `if cfg!(debug_assertions)` | `debug_assert!(a <= b)` |
14//! | `debug_assert_lt!` | `if cfg!(debug_assertions)` | `debug_assert!(a < b)` |
15//! | `debug_assert_ge!` | `if cfg!(debug_assertions)` | `debug_assert!(a >= b)` |
16//! | `debug_assert_gt!` | `if cfg!(debug_assertions)` | `debug_assert!(a > b)` |
17//! | `debug_unreachable!` | `if cfg!(debug_assertions)` | `unreachable!` when debug_assertions are on. |
18//!
19//! When one of the assertions fails, it prints out a message like the
20//! following:
21//!
22//! ```text
23//! thread 'main' panicked at 'assertion failed: `left < right`
24//! left: `4`,
25//! right: `3`', src/main.rs:47:5
26//! note: Run with `RUST_BACKTRACE=1` for a backtrace.
27//! ```
28//!
29//! # Example
30//!
31//! ```rust
32//! use more_asserts as ma;
33//!
34//! #[derive(Debug, PartialEq, PartialOrd)]
35//! enum Example { Foo, Bar }
36//!
37//! ma::assert_le!(3, 4);
38//! ma::assert_ge!(
39//! 10, 10,
40//! "You can pass a message too (just like `assert_eq!`)",
41//! );
42//! ma::debug_assert_lt!(
43//! 1.3, 4.5,
44//! "Format syntax is supported ({}).",
45//! "also like `assert_eq!`"
46//! );
47//!
48//! ma::assert_gt!(
49//! Example::Bar, Example::Foo,
50//! "It works on anything that implements PartialOrd and Debug!",
51//! );
52//! ```
53#![no_std]
54#![deny(missing_docs)]
55
56mod inner;
57
58// From use with macros. Not public API.
59#[doc(hidden)]
60pub extern crate core as __core;
61
62// From use with macros. Not public API.
63#[doc(hidden)]
64pub mod __private {
65 pub use crate::inner::AssertType;
66 // Wrap the outlined functions with generic versions in an effort to improve
67 // the error message given when using one of these macros on a type which
68 // doesn't impl `core::fmt::Debug`.
69 #[cold]
70 #[track_caller]
71 pub fn assert_failed_nomsg<A, B>(left: &A, right: &B, ty: AssertType) -> !
72 where
73 A: core::fmt::Debug,
74 B: core::fmt::Debug,
75 {
76 crate::inner::assert_failed_nomsg_impl(left, right, ty);
77 }
78
79 #[cold]
80 #[track_caller]
81 #[doc(hidden)]
82 pub fn assert_failed_msg<A, B>(
83 left: &A,
84 right: &B,
85 ty: AssertType,
86 msg: core::fmt::Arguments<'_>,
87 ) -> !
88 where
89 A: core::fmt::Debug,
90 B: core::fmt::Debug,
91 {
92 crate::inner::assert_failed_msg_impl(left, right, ty, msg);
93 }
94}
95
96/// Panics if the first expression is not strictly less than the second.
97///
98/// Requires that the values implement [`Debug`](core::fmt::Debug) and
99/// [`PartialOrd`](core::cmp::PartialOrd).
100///
101/// On failure, panics and prints the values out in a manner similar to
102/// [`assert_eq!`](core::assert_eq).
103///
104/// # Example
105///
106/// ```rust
107/// use more_asserts as ma;
108///
109/// ma::assert_lt!(3, 4);
110/// ma::assert_lt!(3, 4, "With a message");
111/// ma::assert_lt!(3, 4, "With a formatted message: {}", "oh no");
112/// ```
113#[macro_export]
114macro_rules! assert_lt {
115 ($left:expr, $right:expr) => {
116 match (&$left, &$right) {
117 (left, right) => if !(left < right) {
118 $crate::__private::assert_failed_nomsg(
119 left, right, $crate::__private::AssertType::Lt,
120 );
121 }
122 }
123 };
124 ($left:expr, $right:expr, ) => {
125 $crate::assert_lt!($left, $right)
126 };
127 ($left:expr, $right:expr, $($msg_args:tt)+) => {
128 match (&$left, &$right) {
129 (left, right) => if !(left < right) {
130 $crate::__private::assert_failed_msg(
131 left, right, $crate::__private::AssertType::Lt,
132 $crate::__core::format_args!($($msg_args)+),
133 );
134 }
135 }
136 };
137}
138
139/// Panics if the first expression is not strictly greater than the second.
140///
141/// Requires that the values implement [`Debug`](core::fmt::Debug) and
142/// [`PartialOrd`](core::cmp::PartialOrd).
143///
144/// On failure, panics and prints the values out in a manner similar to
145/// prelude's [`assert_eq!`](core::assert_eq).
146///
147/// # Example
148///
149/// ```rust
150/// use more_asserts as ma;
151///
152/// ma::assert_gt!(5, 3);
153/// ma::assert_gt!(5, 3, "With a message");
154/// ma::assert_gt!(5, 3, "With a formatted message: {}", "oh no");
155/// ```
156#[macro_export]
157macro_rules! assert_gt {
158 ($left:expr, $right:expr) => {
159 match (&$left, &$right) {
160 (left, right) => if !(left > right) {
161 $crate::__private::assert_failed_nomsg(
162 left, right, $crate::__private::AssertType::Gt,
163 );
164 }
165 }
166 };
167 ($left:expr, $right:expr, ) => {
168 $crate::assert_gt!($left, $right)
169 };
170 ($left:expr, $right:expr, $($msg_args:tt)+) => {
171 match (&$left, &$right) {
172 (left, right) => if !(left > right) {
173 $crate::__private::assert_failed_msg(
174 left, right, $crate::__private::AssertType::Gt,
175 $crate::__core::format_args!($($msg_args)+),
176 );
177 }
178 }
179 };
180}
181
182/// Panics if the first expression is not less than or equal to the second.
183///
184/// Requires that the values implement [`Debug`](core::fmt::Debug) and
185/// [`PartialOrd`](core::cmp::PartialOrd).
186///
187/// On failure, panics and prints the values out in a manner similar to
188/// prelude's [`assert_eq!`](core::assert_eq).
189///
190/// # Example
191///
192/// ```rust
193/// use more_asserts as ma;
194///
195/// ma::assert_le!(4, 4);
196/// ma::assert_le!(4, 5);
197/// ma::assert_le!(4, 5, "With a message");
198/// ma::assert_le!(4, 4, "With a formatted message: {}", "oh no");
199/// ```
200#[macro_export]
201macro_rules! assert_le {
202 ($left:expr, $right:expr) => {
203 match (&$left, &$right) {
204 (left, right) => if !(left <= right) {
205 $crate::__private::assert_failed_nomsg(
206 left, right, $crate::__private::AssertType::Le,
207 );
208 }
209 }
210 };
211 ($left:expr, $right:expr, ) => {
212 $crate::assert_le!($left, $right)
213 };
214 ($left:expr, $right:expr, $($msg_args:tt)+) => {
215 match (&$left, &$right) {
216 (left, right) => if !(left <= right) {
217 $crate::__private::assert_failed_msg(
218 left, right, $crate::__private::AssertType::Le,
219 $crate::__core::format_args!($($msg_args)+),
220 );
221 }
222 }
223 };
224}
225
226/// Panics if the first expression is not greater than or equal to the second.
227///
228/// Requires that the values implement [`Debug`](core::fmt::Debug) and
229/// [`PartialOrd`](core::cmp::PartialOrd).
230///
231/// On failure, panics and prints the values out in a manner similar to
232/// prelude's [`assert_eq!`](core::assert_eq).
233///
234/// Optionally may take an additional message to display on failure, which is
235/// formatted using standard format syntax.
236///
237/// # Example
238///
239/// ```rust
240/// use more_asserts as ma;
241///
242/// ma::assert_ge!(4, 4);
243/// ma::assert_ge!(4, 3);
244/// ma::assert_ge!(4, 3, "With a message");
245/// ma::assert_ge!(4, 4, "With a formatted message: {}", "oh no");
246/// ```
247#[macro_export]
248macro_rules! assert_ge {
249 ($left:expr, $right:expr) => {
250 match (&$left, &$right) {
251 (left, right) => if !(left >= right) {
252 $crate::__private::assert_failed_nomsg(
253 left, right, $crate::__private::AssertType::Ge,
254 );
255 }
256 }
257 };
258 ($left:expr, $right:expr, ) => {
259 $crate::assert_ge!($left, $right)
260 };
261 ($left:expr, $right:expr, $($msg_args:tt)+) => {
262 match (&$left, &$right) {
263 (left, right) => if !(left >= right) {
264 $crate::__private::assert_failed_msg(
265 left, right, $crate::__private::AssertType::Ge,
266 $crate::__core::format_args!($($msg_args)+),
267 );
268 }
269 }
270 };
271}
272
273/// Same as [`assert_lt!`] in builds with debug assertions enabled, and a no-op
274/// otherwise.
275///
276/// # Example
277///
278/// ```rust
279/// use more_asserts as ma;
280///
281/// // These are compiled to nothing if debug_assertions are off!
282/// ma::debug_assert_lt!(3, 4);
283/// ma::debug_assert_lt!(3, 4, "With a message");
284/// ma::debug_assert_lt!(3, 4, "With a formatted message: {}", "oh no");
285/// ```
286#[macro_export]
287macro_rules! debug_assert_lt {
288 ($($arg:tt)+) => {
289 if $crate::__core::cfg!(debug_assertions) {
290 $crate::assert_lt!($($arg)+);
291 }
292 };
293}
294
295/// Same as [`assert_gt!`] in builds with debug assertions enabled, and a no-op
296/// otherwise.
297///
298/// # Example
299///
300/// ```rust
301/// use more_asserts as ma;
302///
303/// // These are compiled to nothing if debug_assertions are off!
304/// ma::debug_assert_gt!(5, 3);
305/// ma::debug_assert_gt!(5, 3, "With a message");
306/// ma::debug_assert_gt!(5, 3, "With a formatted message: {}", "oh no");
307/// ```
308#[macro_export]
309macro_rules! debug_assert_gt {
310 ($($arg:tt)+) => {
311 if $crate::__core::cfg!(debug_assertions) {
312 $crate::assert_gt!($($arg)+);
313 }
314 };
315}
316
317/// Same as [`assert_le!`] in builds with debug assertions enabled, and a no-op
318/// otherwise.
319///
320/// # Example
321///
322/// ```rust
323/// use more_asserts as ma;
324///
325/// // These are compiled to nothing if debug_assertions are off!
326/// ma::debug_assert_le!(4, 4);
327/// ma::debug_assert_le!(4, 5);
328/// ma::debug_assert_le!(4, 5, "With a message");
329/// ma::debug_assert_le!(4, 4, "With a formatted message: {}", "oh no");
330/// ```
331#[macro_export]
332macro_rules! debug_assert_le {
333 ($($arg:tt)+) => {
334 if $crate::__core::cfg!(debug_assertions) {
335 $crate::assert_le!($($arg)+);
336 }
337 };
338}
339
340/// Same as [`assert_ge!`] in builds with debug assertions enabled, and a no-op
341/// otherwise.
342///
343/// # Example
344///
345/// ```rust
346/// use more_asserts as ma;
347///
348/// // These are compiled to nothing if debug_assertions are off!
349/// ma::debug_assert_ge!(4, 4);
350/// ma::debug_assert_ge!(4, 3);
351/// ma::debug_assert_ge!(4, 3, "With a message");
352/// ma::debug_assert_ge!(4, 4, "With a formatted message: {}", "oh no");
353/// ```
354#[macro_export]
355macro_rules! debug_assert_ge {
356 ($($arg:tt)+) => {
357 if $crate::__core::cfg!(debug_assertions) {
358 $crate::assert_ge!($($arg)+);
359 }
360 };
361}
362
363/// Panics if reached when debug assertions are enabled.
364///
365/// This is a variant of the standard library's [`unreachable!`] macro that is
366/// controlled by `cfg!(debug_assertions)`. For builds without debug assertions
367/// enabled (such as typical release builds), it is a no-op.
368///
369/// # Example
370///
371/// ```rust
372/// use more_asserts as ma;
373///
374/// let mut value = 0.5;
375/// if value < 0.0 {
376/// ma::debug_unreachable!("Value out of range {}", value);
377/// value = 0.0;
378/// }
379/// ```
380#[macro_export]
381macro_rules! debug_unreachable {
382 ($($arg:tt)*) => {
383 if $crate::__core::cfg!(debug_assertions) {
384 $crate::__core::unreachable!($($arg)*);
385 }
386 };
387}