162 lines
3.8 KiB
Rust
162 lines
3.8 KiB
Rust
#![no_std]
|
|
//! A macro to evaluate, as a boolean, whether an expression matches a pattern.
|
|
//!
|
|
//! For users who build using only Rust 1.42 and newer, consider using [`std::matches`], which
|
|
//! is included in the [standard library prelude] and thus is automatically in scope.
|
|
//!
|
|
//! [`std::matches`]: core::matches
|
|
//! [standard library prelude]: https://doc.rust-lang.org/stable/reference/names/preludes.html
|
|
//!
|
|
//! # Examples
|
|
//!
|
|
//! ```
|
|
//! #[macro_use]
|
|
//! extern crate matches;
|
|
//!
|
|
//! #[derive(Debug)]
|
|
//! pub enum Foo<T> {
|
|
//! A,
|
|
//! B(T),
|
|
//! }
|
|
//!
|
|
//! impl<T> Foo<T> {
|
|
//! pub fn is_b(&self) -> bool {
|
|
//! matches!(*self, Foo::B(_))
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! impl<T: core::fmt::Debug> Foo<T> {
|
|
//! pub fn assert_is_b(&self) {
|
|
//! assert_matches!(&self, Foo::B(_));
|
|
//! }
|
|
//! }
|
|
//! # fn main() { }
|
|
//! ```
|
|
|
|
/// Check if an expression matches a refutable pattern.
|
|
///
|
|
/// Syntax: `matches!(` *expression* `,` *pattern* `)`
|
|
///
|
|
/// Return a boolean, true if the expression matches the pattern, false otherwise.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// #[macro_use]
|
|
/// extern crate matches;
|
|
///
|
|
/// pub enum Foo<T> {
|
|
/// A,
|
|
/// B(T),
|
|
/// }
|
|
///
|
|
/// impl<T> Foo<T> {
|
|
/// pub fn is_a(&self) -> bool {
|
|
/// matches!(*self, Foo::A)
|
|
/// }
|
|
///
|
|
/// pub fn is_b(&self) -> bool {
|
|
/// matches!(*self, Foo::B(_))
|
|
/// }
|
|
/// }
|
|
///
|
|
/// # fn main() { }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! matches {
|
|
($expression:expr, $($pattern:tt)+) => {
|
|
match $expression {
|
|
$($pattern)+ => true,
|
|
_ => false
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Assert that an expression matches a refutable pattern.
|
|
///
|
|
/// Syntax: `assert_matches!(` *expression* `,` *pattern* `)`
|
|
///
|
|
/// Panic with a message that shows the expression if it does not match the
|
|
/// pattern.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// #[macro_use]
|
|
/// extern crate matches;
|
|
///
|
|
/// fn main() {
|
|
/// let data = [1, 2, 3];
|
|
/// assert_matches!(data.get(1), Some(_));
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! assert_matches {
|
|
($expression:expr, $($pattern:tt)+) => {
|
|
match $expression {
|
|
$($pattern)+ => (),
|
|
ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pattern)+)),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Assert that an expression matches a refutable pattern using debug assertions.
|
|
///
|
|
/// Syntax: `debug_assert_matches!(` *expression* `,` *pattern* `)`
|
|
///
|
|
/// If debug assertions are enabled, panic with a message that shows the
|
|
/// expression if it does not match the pattern.
|
|
///
|
|
/// When debug assertions are not enabled, this macro does nothing.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// #[macro_use]
|
|
/// extern crate matches;
|
|
///
|
|
/// fn main() {
|
|
/// let data = [1, 2, 3];
|
|
/// debug_assert_matches!(data.get(1), Some(_));
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! debug_assert_matches {
|
|
($expression:expr, $($pattern:tt)+) => {
|
|
if cfg!(debug_assertions) {
|
|
match $expression {
|
|
$($pattern)+ => (),
|
|
ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pattern)+)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn matches_works() {
|
|
let foo = Some("-12");
|
|
assert!(matches!(foo, Some(bar) if
|
|
matches!(bar.as_bytes()[0], b'+' | b'-') &&
|
|
matches!(bar.as_bytes()[1], b'0'...b'9')
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn assert_matches_works() {
|
|
let foo = Some("-12");
|
|
assert_matches!(foo, Some(bar) if
|
|
matches!(bar.as_bytes()[0], b'+' | b'-') &&
|
|
matches!(bar.as_bytes()[1], b'0'...b'9')
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "assertion failed: `Some(\"-AB\")` does not match ")]
|
|
fn assert_matches_panics() {
|
|
let foo = Some("-AB");
|
|
assert_matches!(foo, Some(bar) if
|
|
matches!(bar.as_bytes()[0], b'+' | b'-') &&
|
|
matches!(bar.as_bytes()[1], b'0'...b'9')
|
|
);
|
|
}
|