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#[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}