option_chain/
lib.rs

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