|
62 | 62 | //! you include. |
63 | 63 | //! * `assert_ne` is also switched to multi-line presentation, but does _not_ show |
64 | 64 | //! a diff. |
| 65 | +//! |
| 66 | +//! ## Features |
| 67 | +//! |
| 68 | +//! Features provided by the crate are as follows: |
| 69 | +//! |
| 70 | +//! - `unstable`: opt-in to unstable features that may not follow Semantic Versioning. |
| 71 | +//! Implmenetion behind this feature is subject to change without warning between patch versions. |
65 | 72 |
|
66 | 73 | #![deny(clippy::all, missing_docs, unsafe_code)] |
67 | 74 |
|
@@ -238,3 +245,85 @@ macro_rules! assert_ne { |
238 | 245 | } |
239 | 246 | }); |
240 | 247 | } |
| 248 | + |
| 249 | +/// Asserts that a value matches a pattern. |
| 250 | +/// |
| 251 | +/// On panic, this macro will print a diff derived from [`Debug`] representation of |
| 252 | +/// the value, and a string representation of the pattern. |
| 253 | +/// |
| 254 | +/// This is a drop in replacement for [`std::assert_matches::assert_matches!`]. |
| 255 | +/// You can provide a custom panic message if desired. |
| 256 | +/// |
| 257 | +/// # Examples |
| 258 | +/// |
| 259 | +/// ``` |
| 260 | +/// use pretty_assertions::assert_matches; |
| 261 | +/// |
| 262 | +/// let a = Some(3); |
| 263 | +/// assert_matches!(a, Some(_)); |
| 264 | +/// |
| 265 | +/// assert_matches!(a, Some(value) if value > 2, "we are testing {:?} with a pattern", a); |
| 266 | +/// ``` |
| 267 | +/// |
| 268 | +/// # Features |
| 269 | +/// |
| 270 | +/// Requires the `unstable` feature to be enabled. |
| 271 | +/// |
| 272 | +/// **Please note:** implementation under the `unstable` feature may be changed between |
| 273 | +/// patch versions without warning. |
| 274 | +#[cfg(feature = "unstable")] |
| 275 | +#[macro_export] |
| 276 | +macro_rules! assert_matches { |
| 277 | + ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => ({ |
| 278 | + match $left { |
| 279 | + $( $pattern )|+ $( if $guard )? => {} |
| 280 | + ref left_val => { |
| 281 | + $crate::assert_matches!( |
| 282 | + @ |
| 283 | + left_val, |
| 284 | + ::std::stringify!($($pattern)|+ $(if $guard)?), |
| 285 | + "", |
| 286 | + "" |
| 287 | + ); |
| 288 | + } |
| 289 | + } |
| 290 | + }); |
| 291 | + ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )?, $($arg:tt)+) => ({ |
| 292 | + match $left { |
| 293 | + $( $pattern )|+ $( if $guard )? => {} |
| 294 | + ref left_val => { |
| 295 | + $crate::assert_matches!( |
| 296 | + @ |
| 297 | + left_val, |
| 298 | + ::std::stringify!($($pattern)|+ $(if $guard)?), |
| 299 | + ": ", |
| 300 | + $($arg)+ |
| 301 | + ); |
| 302 | + } |
| 303 | + } |
| 304 | + |
| 305 | + }); |
| 306 | + (@ $left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)*) => ({ |
| 307 | + match (&($left), &($right)) { |
| 308 | + (left_val, right_val) => { |
| 309 | + // Use the Display implementation to display the pattern, |
| 310 | + // as using Debug would add another layer of quotes to the output. |
| 311 | + struct Pattern<'a>(&'a str); |
| 312 | + impl ::std::fmt::Debug for Pattern<'_> { |
| 313 | + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { |
| 314 | + ::std::fmt::Display::fmt(self.0, f) |
| 315 | + } |
| 316 | + } |
| 317 | + |
| 318 | + ::std::panic!("assertion failed: `(left matches right)`{}{}\ |
| 319 | + \n\ |
| 320 | + \n{}\ |
| 321 | + \n", |
| 322 | + $maybe_semicolon, |
| 323 | + format_args!($($arg)*), |
| 324 | + $crate::Comparison::new(left_val, &Pattern(right_val)) |
| 325 | + ) |
| 326 | + } |
| 327 | + } |
| 328 | + }); |
| 329 | +} |
0 commit comments