#![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 { //! A, //! B(T), //! } //! //! impl Foo { //! pub fn is_b(&self) -> bool { //! matches!(*self, Foo::B(_)) //! } //! } //! //! impl Foo { //! 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 { /// A, /// B(T), /// } /// /// impl Foo { /// 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') ); }