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
//! This is a minimal crate which implements match through different types. //! //! Usage: //! //! ```rust //! #[macro_use] //! extern crate match_cast; //! use std::panic; //! //! fn main() { //! let res = panic::catch_unwind(|| { //! panic!("Oh no!"); //! }); //! //! let any = res.unwrap_err(); //! //! let result = match_cast!( any { //! val as Option<u8> => { //! format!("Option<u8> = {:?}", val) //! }, //! val as String => { //! format!("String = {:?}", val) //! }, //! val as &'static str => { //! format!("&'static str = {:?}", val) //! }, //! }); //! //! assert_eq!(result.unwrap(), "&'static str = \"Oh no!\""); //! } //! ``` //! //! To use pattern there is `match_down` macro: //! //! ```rust //! #[macro_use] //! extern crate match_cast; //! use std::any::Any; //! //! struct Bar { //! x: u8, //! } //! //! struct Foo { //! x: u8, //! } //! //! fn main() { //! //! let any: Box<Any> = Box::new(Foo { x: 45 }); //! //! let result = match_down!( any { //! Bar { x } => { x }, //! Foo { x } => { x }, //! }); //! //! assert_eq!(result.unwrap(), 45); //! } //! ``` #[macro_export] macro_rules! match_cast { ($any:ident { $( $bind:ident as $patt:ty => $body:block , )+ }) => {{ let downcast = || { $( if let Some($bind) = $any.downcast_ref::<$patt>() { return Some($body); } )+ None }; downcast() }}; } #[macro_export] macro_rules! match_down { ($any:ident { $( $pt:pat => $body:block , )+ }) => {{ let downcast = || { $( if let Some(&$pt) = $any.downcast_ref() { return Some($body); } )+ None }; downcast() }}; }