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