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
//! Like `.unwrap()` or `.or_else()` for arbitrary patterns. //! //! I'm not so sure this is a great idea, but it's useful for prototyping at least! /// When you're pretty sure something will match a pattern. /// /// It simply expands to a two-branch match: /// ``` /// sure!(val, pattern => result; otherwise); /// // expands to /// match val { /// pattern => result, /// _ => otherwise /// } /// ``` /// /// For example: /// ``` /// sure!(val, Enum::Variant{field, name: Enum::Variant2(num)} => (field, num); return Err("oops")) /// // expands to /// match val { /// Enum::Variant{field, name: Enum::Variant2(num)} => (field, num), /// _ => return Err("oops") /// } /// ``` /// The else branch is optional and defaults to a panic: /// ``` /// let v = Enum::Var2; /// sure!(v, Enum::Var1(n) => n); /// // Will panic with "Expected v to match pattern: Enum::Var1(n)" /// ``` /// /// Asserting slice patterns can still feel redundant, so there are some affordances for that. /// If the pattern and result are the same, you can leave out the `=> result`. /// If a let binding, pattern, and result are all the same, you can pull in the let. /// ``` /// // These are all equivalent /// let [a,b] = sure!(vec[..], [a,b] => [a,b]); /// let [a,b] = sure!(vec[..], [a,b]); /// sure!(let [a,b] = vec[..]); /// ``` /// #[macro_export] macro_rules! sure { // main form ($target:expr, $p:pat => $res:expr; $else:expr) => { match $target { $p => $res, _ => $else } }; ($target:expr, $p:pat => $res:expr) => { sure!($target, $p => $res; panic!("Expected {} to match pattern: {}", stringify!($target), stringify!($p))) }; // self-matching form // for tuple or slice patterns that also form the proper bindings ($target:expr, $pat:tt; $else:expr) => { sure!($target, $pat => $pat; $else) }; ($target:expr, $pat:tt) => { sure!($target, $pat => $pat) }; // inlined let, for self-matching bindings (let $pat:tt = $target:expr; $else:expr) => { let $pat = sure!($target, $pat; $else); }; (let $pat:tt = $target:expr) => { let $pat = sure!($target, $pat); }; }