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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
#![no_std] /// Matches an expression to any of the patterns and executes the same expression arm for any match. /// /// This macro allows you to use the same expression arm for different types /// by creating the same match arm for each of the patterns separated by `|`. /// A standard match statement only allows such patterns for the same type: /// /// ```compile_fail /// let result: Result<i64, i32> = Err(42); /// let int: i64 = match result { Ok(i) | Err(i) => i.into() }; // does not compile! /// ``` /// /// ``` /// # use match_any::match_any; /// let result: Result<i64, i32> = Err(42); /// let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); // compiles just fine /// assert_eq!(int, 42); /// ``` /// /// # Examples /// /// ``` /// use match_any::match_any; /// /// enum Id { U8(u8), I16(i16), I32(i32) } /// use Id::*; /// /// let id = Id::I16(-2); /// let id: i32 = match_any!(id, U8(x) | I16(x) | I32(x) => x.into()); /// assert_eq!(id, -2); /// ``` /// /// With multiple match arms: /// /// ``` /// use core::convert::TryFrom; /// use match_any::match_any; /// /// enum Id { U8(u8), I16(i16), I32(i32), U64(u64) } /// use Id::*; /// /// let id = Id::I32(-3); /// let id: i32 = match_any!(id, /// U8(a) | I16(a) | I32(a) => a.into(), /// U64(b) => i32::try_from(b).unwrap_or(0) /// ); /// assert_eq!(id, -3); /// ``` /// /// # Macro Expansion /// /// ``` /// # use match_any::match_any; /// let result: Result<i32, i32> = Err(42); /// match_any!(result, Ok(i) | Err(i) => Some(i)); /// ``` /// expands to /// ``` /// let result: Result<i32, i32> = Err(42); /// match result { Ok(i) => Some(i), Err(i) => Some(i) }; /// ``` /// /// # Enum Dispatch /// /// Similarly to the [enum_dispatch crate](https://crates.io/crates/enum_dispatch), /// this macro can be used to implement "enum dispatch" as an alternative to dynamic dispatch. /// The major difference between the enum_dispatch crate and this macro is, /// that enum_dispatch provides a _procedural_ macro, while this is a _declarative_ macro. /// This allows enum_dispatch to reduce the boilerplate code a lot more than match_any. /// However IDE support should be a bit better with match_any. /// /// ## Enum Dispatch Example /// /// ``` /// use match_any::match_any; /// /// trait IntId { /// fn int_id(&self) -> i32; /// } /// /// impl IntId for u64 { /// fn int_id(&self) -> i32 { 64 } /// } /// /// impl IntId for u32 { /// fn int_id(&self) -> i32 { 32 } /// } /// /// enum IntIdKind { U64(u64), U32(u32) } /// /// impl IntId for IntIdKind { /// fn int_id(&self) -> i32 { /// use IntIdKind::*; /// match_any!(self, U64(i) | U32(i) => i.int_id()) /// } /// } /// /// let int_id_kind = IntIdKind::U32(0); /// assert_eq!(int_id_kind.int_id(), 32); // enum dispatch /// let int_id_box: Box<dyn IntId> = Box::new(0_u32); /// assert_eq!(int_id_box.int_id(), 32); // dynamic dispatch /// ``` #[macro_export] macro_rules! match_any { ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { match $expr { $( $( $pat => $expr_arm, )+ )+ } }; }