option_chain/
lib.rs

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