any_opt/
lib.rs

1//! This crate exports a macro to chain multiple options together to retrieve the first item that is `Some`, from left to right
2//!
3//! Every item is lazily evaluated, but to make this possible there's a caveat when trying to pass closures:
4//! you have to call them in place when passing the item
5//!
6//! # Example
7//! ```rust
8//! # #[macro_use] extern crate any_opt;
9//! fn my_fn<T>() -> Option<T> { None }
10//! fn main() {
11//!     let opt = Some(3);
12//!     let v = any_opt!((|| None)(), my_fn(), Some(13), Some(55), None, Some(42), opt).unwrap_or_default();
13//!
14//!     assert_eq!(v, 13);
15//! }
16//! ```
17#[macro_export]
18macro_rules! any_opt {
19    ($opt:expr) => {
20        $opt
21    };
22    ($opt:expr, $($other:expr),+) => {
23        $opt.or_else(|| any_opt!($($other),+))
24    };
25}
26
27#[cfg(test)]
28mod tests {
29    fn something<T>(counter: &mut u32) -> Option<T> {
30        println!("{}", counter);
31        *counter += 1;
32        None
33    }
34
35    #[test]
36    fn single_item() {
37        let v: usize = any_opt!(None).unwrap_or_default();
38        assert_eq!(v, 0);
39    }
40
41    #[test]
42    fn multi_item() {
43        let v: usize = any_opt!(None, None, Some(3)).unwrap_or_default();
44        assert_eq!(v, 3);
45    }
46
47    #[test]
48    fn lazy_eval() {
49        let opt = None;
50        let mut counter = 0;
51        let v: usize = any_opt!(opt, something(&mut counter), Some(3), something(&mut counter))
52            .unwrap_or_default();
53        assert_eq!(v, 3);
54        assert_eq!(counter, 1);
55    }
56
57    #[test]
58    fn closure() {
59        let v: usize = any_opt!((|| None)(), None, Some(3)).unwrap_or_default();
60        assert_eq!(v, 3);
61    }
62}