diff options
Diffstat (limited to 'third_party/rust/matches/lib.rs')
-rw-r--r-- | third_party/rust/matches/lib.rs | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/third_party/rust/matches/lib.rs b/third_party/rust/matches/lib.rs new file mode 100644 index 0000000000..262f8d0764 --- /dev/null +++ b/third_party/rust/matches/lib.rs @@ -0,0 +1,161 @@ +#![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') + ); +} |