claims/assert_ge.rs
1/// Asserts that the first expression is greater than or equal to the second.
2///
3/// Requires that both expressions be comparable with `>=`.
4///
5/// ## Uses
6///
7/// Assertions are always checked in both debug and release builds, and cannot be disabled.
8/// See [`debug_assert_ge!`] for assertions that are not enabled in release builds by default.
9///
10/// ## Custom messages
11///
12/// This macro has a second form, where a custom panic message can be provided with or without
13/// arguments for formatting. See [`std::fmt`] for syntax for this form.
14///
15/// ## Examples
16///
17/// ```rust
18/// # #[macro_use] extern crate claims;
19/// # fn main() {
20/// assert_ge!(2, 1);
21///
22/// // With a custom message.
23/// assert_ge!(2, 1, "Expecting that {} is greater or equal than {}", 2, 1);
24/// assert_ge!(5, 5, "Expecting that both arguments are equal");
25/// # }
26/// ```
27///
28/// ```rust,should_panic
29/// # #[macro_use] extern crate claims;
30/// # fn main() {
31/// assert_ge!(5, 6); // Will panic
32/// # }
33/// ```
34///
35/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
36/// [`debug_assert_ge!`]: crate::debug_assert_ge!
37#[macro_export]
38macro_rules! assert_ge {
39 ($left:expr, $right:expr $(,)?) => {
40 match (&$left, &$right) {
41 (left_val, right_val) => {
42 if !(*left_val >= *right_val) {
43 // The reborrows below are intentional. Without them, the stack slot for the
44 // borrow is initialized even before the values are compared, leading to a
45 // noticeable slow down.
46 ::core::panic!(r#"assertion failed: `(left >= right)`
47 left: `{:?}`,
48 right: `{:?}`"#, &*left_val, &*right_val)
49 }
50 }
51 }
52 };
53 ($left:expr, $right:expr, $($arg:tt)+) => {
54 match (&$left, &$right) {
55 (left_val, right_val) => {
56 if !(*left_val >= *right_val) {
57 // The reborrows below are intentional. Without them, the stack slot for the
58 // borrow is initialized even before the values are compared, leading to a
59 // noticeable slow down.
60 ::core::panic!(r#"assertion failed: `(left >= right)`
61 left: `{:?}`,
62 right: `{:?}`: {}"#, &*left_val, &*right_val, ::core::format_args!($($arg)+))
63 }
64 }
65 }
66 };
67}
68
69/// Asserts that the first expression is greater than or equal to the second on debug builds.
70///
71/// This macro behaves the same as [`assert_ge!`] on debug builds. On release builds it is a no-op.
72#[macro_export]
73macro_rules! debug_assert_ge {
74 ($($arg:tt)*) => {
75 #[cfg(debug_assertions)]
76 $crate::assert_ge!($($arg)*);
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 #[test]
83 fn greater_than() {
84 assert_ge!(5, 3);
85 }
86
87 #[test]
88 fn equal() {
89 assert_ge!(3, 3);
90 }
91
92 #[test]
93 #[should_panic(
94 expected = "assertion failed: `(left >= right)`\n left: `1`,\n right: `3`"
95 )]
96 fn less_than() {
97 assert_ge!(1, 3);
98 }
99
100 #[test]
101 #[should_panic(
102 expected = "assertion failed: `(left >= right)`\n left: `1`,\n right: `3`: foo"
103 )]
104 fn less_than_custom_message() {
105 assert_ge!(1, 3, "foo");
106 }
107
108 #[test]
109 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
110 fn debug_greater_than() {
111 debug_assert_ge!(5, 3);
112 }
113
114 #[test]
115 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
116 fn debug_equal() {
117 debug_assert_ge!(3, 3);
118 }
119
120 #[test]
121 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
122 #[should_panic(
123 expected = "assertion failed: `(left >= right)`\n left: `1`,\n right: `3`"
124 )]
125 fn debug_less_than() {
126 debug_assert_ge!(1, 3);
127 }
128
129 #[test]
130 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
131 #[should_panic(
132 expected = "assertion failed: `(left >= right)`\n left: `1`,\n right: `3`: foo"
133 )]
134 fn debug_less_than_custom_message() {
135 debug_assert_ge!(1, 3, "foo");
136 }
137
138 #[test]
139 #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
140 fn debug_release_less_than() {
141 debug_assert_ge!(1, 3);
142 }
143}