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}