option_chain/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![deny(missing_docs)]
4#![warn(clippy::all, clippy::nursery, clippy::pedantic, clippy::cargo)]
5
6/// A macro for using `?` operator in functions that don't return `Option`.
7///
8/// See [crate level documentation](crate) for more information.
9#[macro_export]
10macro_rules! opt {
11    ($e:expr) => {
12        {
13            || -> ::core::option::Option<_> { ::core::option::Option::Some($e) }()
14        }
15    };
16}
17
18#[cfg(test)]
19mod tests {
20    use super::*;
21
22    #[test]
23    fn test_macro_named() {
24        struct Test1 {
25            a: Option<Test2>,
26        }
27        struct Test2 {
28            b: Option<Test3>,
29        }
30        struct Test3 {
31            c: i32,
32        }
33
34        let v1 = Test1 {
35            a: None,
36        };
37        let v1 = opt!(v1.a?.b?.c);
38        assert!(v1.is_none());
39
40        let v2 = Test1 {
41            a: Some(Test2 { b: None }),
42        };
43        let v2 = opt!(v2.a?.b?.c);
44        assert!(v2.is_none());
45
46        let v3 = Test1 {
47            a: Some(Test2 { b: Some(Test3 { c: 42 }) }),
48        };
49        let v3 = opt!(v3.a?.b?.c);
50        assert_eq!(v3.unwrap(), 42);
51    }
52
53    #[test]
54    fn test_macro_unnamed() {
55        struct Test1(Option<Test2>);
56        struct Test2(Option<Test3>);
57        struct Test3(i32);
58
59        let v1 = Test1(None);
60        let v1 = opt!(v1.0?.0?.0);
61        assert!(v1.is_none());
62
63        let v2 = Test1(Some(Test2(None)));
64        let v2 = opt!(v2.0?.0?.0);
65        assert!(v2.is_none());
66
67        let v3 = Test1(Some(Test2(Some(Test3(42)))));
68        let v3 = opt!(v3.0?.0?.0);
69        assert_eq!(v3.unwrap(), 42);
70    }
71
72    #[test]
73    fn test_macro_mixed() {
74        struct Test1 {
75            a: Option<Test2>,
76        }
77        struct Test2(Option<Test3>);
78        struct Test3(i32);
79
80        let v1 = Test1 {
81            a: None,
82        };
83        let v1 = opt!(v1.a?.0?.0);
84        assert!(v1.is_none());
85
86        let v2 = Test1 {
87            a: Some(Test2(None)),
88        };
89        let v2 = opt!(v2.a?.0?.0);
90        assert!(v2.is_none());
91
92        let v3 = Test1 {
93            a: Some(Test2(Some(Test3(42)))),
94        };
95        let v3 = opt!(v3.a?.0?.0);
96        assert_eq!(v3.unwrap(), 42);
97    }
98}