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
//! This crate exports a macro to chain multiple options together to retrieve the first item that is `Some`, from left to right
//!
//! Every item is lazily evaluated, but to make this possible there's a caveat when trying to pass closures:
//! you have to call them in place when passing the item
//!
//! # Example
//! ```rust
//! # #[macro_use] extern crate any_opt;
//! fn my_fn<T>() -> Option<T> { None }
//! fn main() {
//!     let opt = Some(3);
//!     let v = any_opt!((|| None)(), my_fn(), Some(13), Some(55), None, Some(42), opt).unwrap_or_default();
//!
//!     assert_eq!(v, 13);
//! }
//! ```
#[macro_export]
macro_rules! any_opt {
    ($opt:expr) => {
        $opt
    };
    ($opt:expr, $($other:expr),+) => {
        $opt.or_else(|| any_opt!($($other),+))
    };
}

#[cfg(test)]
mod tests {
    fn something<T>(counter: &mut u32) -> Option<T> {
        println!("{}", counter);
        *counter += 1;
        None
    }

    #[test]
    fn single_item() {
        let v: usize = any_opt!(None).unwrap_or_default();
        assert_eq!(v, 0);
    }

    #[test]
    fn multi_item() {
        let v: usize = any_opt!(None, None, Some(3)).unwrap_or_default();
        assert_eq!(v, 3);
    }

    #[test]
    fn lazy_eval() {
        let opt = None;
        let mut counter = 0;
        let v: usize = any_opt!(opt, something(&mut counter), Some(3), something(&mut counter))
            .unwrap_or_default();
        assert_eq!(v, 3);
        assert_eq!(counter, 1);
    }

    #[test]
    fn closure() {
        let v: usize = any_opt!((|| None)(), None, Some(3)).unwrap_or_default();
        assert_eq!(v, 3);
    }
}