risingwave_error/
macros.rs1#[macro_export]
53macro_rules! ensure {
54 ($cond:expr $(,)?) => {
55 if !$cond {
56 return Err(::anyhow::anyhow!(stringify!($cond)).into());
57 }
58 };
59 ($cond:expr, $msg:literal $(,)?) => {
60 if !$cond {
61 return Err(::anyhow::anyhow!($msg).into());
62 }
63 };
64 ($cond:expr, $fmt:expr, $($arg:tt)*) => {
65 if !$cond {
66 return Err(::anyhow::anyhow!($fmt, $($arg)*).into());
67 }
68 };
69 ($cond:expr, $error_code:expr) => {
70 if !$cond {
71 return Err($error_code.into());
72 }
73 };
74}
75pub use ensure;
76
77#[macro_export]
79macro_rules! ensure_eq {
80 ($left:expr, $right:expr) => {
81 match (&$left, &$right) {
82 (left_val, right_val) => {
83 if !(left_val == right_val) {
84 $crate::bail!(
85 "{} == {} assertion failed ({} is {}, {} is {})",
86 stringify!($left),
87 stringify!($right),
88 stringify!($left),
89 &*left_val,
90 stringify!($right),
91 &*right_val,
92 );
93 }
94 }
95 }
96 };
97}
98pub use ensure_eq;
99
100#[macro_export]
105macro_rules! bail {
106 ($($arg:tt)*) => {
107 return Err(::anyhow::anyhow!($($arg)*).into())
108 };
109}
110pub use bail;
111
112#[macro_export]
116macro_rules! try_match_expand {
117 ($e:expr, $variant:path) => {
118 match $e {
119 $variant(internal) => Ok(internal),
120 _ => Err(::anyhow::anyhow!(
121 "unable to match {} with {}",
122 stringify!($e),
123 stringify!($variant),
124 )),
125 }
126 };
127 ($e:expr, $variant:path, $($arg:tt)+) => {
128 match $e {
129 $variant(internal) => Ok(internal),
130 _ => Err(::anyhow::anyhow!($($arg)+)),
131 }
132 };
133}
134pub use try_match_expand;
135
136#[macro_export]
140macro_rules! must_match {
141 ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $action:expr) => {
142 match $expression {
143 $( $pattern )|+ $( if $guard )? => $action,
144 _ => panic!("enum variant mismatch: `{}` is required", stringify!($( $pattern )|+ $( if $guard )?)),
145 }
146 };
147}
148pub use must_match;
149
150#[cfg(test)]
151mod ensure_tests {
152 use anyhow::anyhow;
153 use thiserror::Error;
154
155 use super::*;
156
157 #[derive(Error, Debug)]
158 #[error(transparent)]
159 struct MyError(#[from] anyhow::Error);
160
161 #[test]
162 fn test_ensure() {
163 let a = 1;
164
165 {
166 let err_msg = "a < 0";
167 let error = (|| {
168 ensure!(a < 0);
169 Ok::<_, MyError>(())
170 })()
171 .unwrap_err();
172
173 assert_eq!(MyError(anyhow!(err_msg)).to_string(), error.to_string(),);
174 }
175
176 {
177 let err_msg = "error msg without args";
178 let error = (|| {
179 ensure!(a < 0, "error msg without args");
180 Ok::<_, MyError>(())
181 })()
182 .unwrap_err();
183 assert_eq!(MyError(anyhow!(err_msg)).to_string(), error.to_string());
184 }
185
186 {
187 let error = (|| {
188 ensure!(a < 0, "error msg with args: {}", "xx");
189 Ok::<_, MyError>(())
190 })()
191 .unwrap_err();
192 assert_eq!(
193 MyError(anyhow!("error msg with args: {}", "xx")).to_string(),
194 error.to_string()
195 );
196 }
197 }
198
199 #[test]
200 fn test_ensure_eq() {
201 fn ensure_a_equals_b() -> Result<(), MyError> {
202 let a = 1;
203 let b = 2;
204 ensure_eq!(a, b);
205 Ok(())
206 }
207 let err = ensure_a_equals_b().unwrap_err();
208 assert_eq!(err.to_string(), "a == b assertion failed (a is 1, b is 2)");
209 }
210}
211
212#[cfg(test)]
213mod match_tests {
214 #[derive(thiserror::Error, Debug)]
215 #[error(transparent)]
216 struct ExpandError(#[from] anyhow::Error);
217
218 #[allow(dead_code)]
219 enum MyEnum {
220 A(String),
221 B,
222 }
223
224 #[test]
225 fn test_try_match() -> Result<(), ExpandError> {
226 assert_eq!(
227 try_match_expand!(MyEnum::A("failure".to_owned()), MyEnum::A)?,
228 "failure"
229 );
230 assert_eq!(
231 try_match_expand!(MyEnum::A("failure".to_owned()), MyEnum::A)?,
232 "failure"
233 );
234 assert_eq!(
235 try_match_expand!(MyEnum::A("failure".to_owned()), MyEnum::A)?,
236 "failure"
237 );
238
239 let err_str = try_match_expand!(MyEnum::A("failure".to_owned()), MyEnum::A)?;
241 assert_eq!(err_str, "failure");
242 Ok(())
243 }
244
245 #[test]
246 fn test_must_match() -> Result<(), ExpandError> {
247 #[allow(dead_code)]
248 enum A {
249 Foo,
250 Bar,
251 }
252 let a = A::Foo;
253 let val = must_match!(a, A::Foo => 42);
254 assert_eq!(val, 42);
255
256 #[allow(dead_code)]
257 enum B {
258 Foo,
259 Bar(i32),
260 Baz { x: u32, y: u32 },
261 }
262 let b = B::Baz { x: 1, y: 2 };
263 let val = must_match!(b, B::Baz { x, y } if x == 1 => x + y);
264 assert_eq!(val, 3);
265 let b = B::Bar(42);
266 let val = must_match!(b, B::Bar(x) => {
267 let y = x + 1;
268 y * 2
269 });
270 assert_eq!(val, 86);
271
272 Ok(())
273 }
274}