pretty_sure/
lib.rs

1//! Like `.unwrap()` or `.or_else()` for arbitrary patterns.
2//!
3//! I'm not so sure this is a great idea, but it's useful for prototyping at least!
4
5
6/// When you're pretty sure something will match a pattern.
7///
8/// It simply expands to a two-branch match:
9/// ```
10/// sure!(val, pattern => result; otherwise);
11/// // expands to
12/// match val {
13///     pattern => result,
14///     _ => otherwise
15/// }
16/// ```
17/// 
18/// For example:
19/// ```
20/// sure!(val, Enum::Variant{field, name: Enum::Variant2(num)} => (field, num); return Err("oops"))
21/// // expands to
22/// match val {
23///   Enum::Variant{field, name: Enum::Variant2(num)} => (field, num),
24///   _ => return Err("oops")
25/// }
26/// ```
27/// The else branch is optional and defaults to a panic:
28/// ```
29/// let v = Enum::Var2;
30/// sure!(v, Enum::Var1(n) => n);
31/// // Will panic with "Expected v to match pattern: Enum::Var1(n)"
32/// ```
33/// 
34/// Asserting slice patterns can still feel redundant, so there are some affordances for that.
35/// If the pattern and result are the same, you can leave out the `=> result`.
36/// If a let binding, pattern, and result are all the same, you can pull in the let.
37/// ```
38/// // These are all equivalent
39/// let [a,b] = sure!(vec[..], [a,b] => [a,b]);
40/// let [a,b] = sure!(vec[..], [a,b]);
41/// sure!(let [a,b] = vec[..]);
42/// ```
43///
44#[macro_export]
45macro_rules! sure {
46    // main form
47    ($target:expr, $p:pat => $res:expr; $else:expr) => {
48        match $target {
49            $p => $res,
50            _ => $else
51        }
52    };
53    ($target:expr, $p:pat => $res:expr) => {
54        sure!($target, $p => $res; panic!("Expected {} to match pattern: {}", stringify!($target), stringify!($p)))
55    };
56
57    // self-matching form
58    // for tuple or slice patterns that also form the proper bindings
59    ($target:expr, $pat:tt; $else:expr) => {
60        sure!($target, $pat => $pat; $else)
61    };
62    ($target:expr, $pat:tt) => {
63        sure!($target, $pat => $pat)
64    };
65
66    // inlined let, for self-matching bindings
67    (let $pat:tt = $target:expr; $else:expr) => {
68        let $pat = sure!($target, $pat; $else);
69    };
70    (let $pat:tt = $target:expr) => {
71        let $pat = sure!($target, $pat);
72    };
73}