1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/// Works similarly to `matches!` but returns an `Option` of variables bound in the pattern /// /// The input of the macro looks like this: /// /// `bind_match!(input_expr, pattern => binding_expr)` /// /// Or with pattern guards: /// /// `bind_match!(input_expr, pattern if guard => binding_expr)` /// /// The `binding_expr` is returned, with variables bound in the pattern. If no binding /// expression is given then the result is `Some(())`. /// /// ## Example /// /// ``` /// use bind_match::bind_match; /// /// enum Foo { /// A(Option<i32>, bool), /// B { open: bool, closed: bool }, /// } /// struct Bar { /// foo: Foo, /// fun: bool, /// } /// /// # fn main() { /// let bar = Bar { /// foo: Foo::A(Some(42), true), /// fun: false, /// }; /// let result = bind_match!(bar, Bar { foo: Foo::A(Some(n), x), fun } if !fun => (n, x)); /// assert_eq!(result, Some((42, true))); /// # } /// ``` /// This can be particularly useful when matching inside iterator adapters. For example, using /// the same types as above: /// ``` /// # use bind_match::bind_match; /// # enum Foo { /// # A(Option<i32>, bool), /// # B { open: bool, closed: bool }, /// # } /// # struct Bar { /// # foo: Foo, /// # fun: bool, /// # } /// # fn main() { /// let bar = Bar { /// foo: Foo::A(Some(42), true), /// fun: false, /// }; /// let result = bind_match!(bar, Bar { foo: Foo::A(Some(n), x), fun } if !fun => (n, x)); /// assert_eq!(result, Some((42, true))); /// # } /// ``` /// The binding expression can be omitted, in which case it defaults to `Some(())`: /// ``` /// # use bind_match::bind_match; /// # enum Foo { /// # A(Option<i32>, bool), /// # B { open: bool, closed: bool }, /// # } /// # struct Bar { /// # foo: Foo, /// # fun: bool, /// # } /// # fn main() { /// let bar = Bar { /// foo: Foo::A(Some(42), true), /// fun: false, /// }; /// let result = bind_match!(bar, Bar { foo: Foo::A(Some(n), x), fun } if fun); /// assert!(result.is_none()); /// # } /// ``` #[macro_export] macro_rules! bind_match { ($expression: expr, $($pattern: pat)|+ $(if $guard: expr)? => $binding_expr: expr) => { match $expression { $($pattern)|+ $(if $guard)? => Some($binding_expr), _ => None } }; ($expression: expr, $($pattern: pat)|+ $(if $guard: expr)?) => { match $expression { $($pattern)|+ $(if $guard)? => Some(()), _ => None } }; }