osom_lib_cfg_ext/lib.rs
1//! proc-macros that makes working with `#[cfg(...)]` easier.
2//!
3//! At the moment it provides [`cfg_match`] only.
4#![deny(warnings)]
5#![warn(clippy::all, clippy::pedantic)]
6#![allow(clippy::redundant_field_names)]
7#![allow(clippy::inline_always)]
8
9use syn::parse_macro_input;
10
11mod cfg_matcher;
12mod generator;
13
14/// Matches against various cfg settings.
15///
16/// # Examples
17///
18/// ```rust
19/// use osom_lib_cfg_ext::cfg_match;
20///
21/// cfg_match!(
22/// (target_os = "windows") => {
23/// fn os_name() -> &'static str {
24/// "W"
25/// }
26/// },
27/// (target_os = "linux") => {
28/// fn os_name() -> &'static str {
29/// "L"
30/// }
31/// },
32/// _ => {
33/// fn os_name() -> &'static str {
34/// "U"
35/// }
36/// }
37/// );
38/// ```
39///
40/// The call above will generate only one `os_name` function, depending on the matched
41/// condition. The condition is translated to one of `#[cfg(...)]` attributes.
42///
43/// Conditions are evaluated one after another. In particular the order doesn't matter
44/// if they are independent. However it does matter in general. For example say we have
45/// this:
46///
47/// ```rust
48/// use osom_lib_cfg_ext::cfg_match;
49///
50/// cfg_match!(
51/// (A) => {
52/// const A: i32 = 1;
53/// },
54/// (B) => {
55/// const B: i32 = 2;
56/// }
57/// );
58/// ```
59///
60/// Then if `B` implies `A` (as a condition) then `B` arm will never be matched here.
61/// For it to be matched you need to reverse the order:
62///
63/// ```rust
64/// use osom_lib_cfg_ext::cfg_match;
65///
66/// cfg_match!(
67/// (B) => {
68/// const B: i32 = 2;
69/// },
70/// (A) => {
71/// const A: i32 = 1;
72/// }
73/// );
74/// ```
75#[proc_macro]
76pub fn cfg_match(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
77 let item = parse_macro_input!(tokens as cfg_matcher::CfgMatcher);
78 generator::generate_from_cfg_match(&item).into()
79}
80
81/// Helper when generating code from [`cfg_match`].
82#[doc(hidden)]
83#[proc_macro]
84pub fn identity(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
85 tokens
86}