Repository: greyblake/nutype (language: rust)

Issue:
Use cfg-if instead of match_feature
Use [cfg-if](https://crates.io/crates/cfg-if) crate instead of `match_feature` macro rule.


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 8c84a24..7565334 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -35,6 +35,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
 [[package]]
 name = "dissimilar"
 version = "1.0.6"
@@ -95,6 +101,7 @@ dependencies = [
 name = "nutype_macros"
 version = "0.3.1"
 dependencies = [
+ "cfg-if",
  "proc-macro2",
  "quote",
  "regex",
diff --git a/nutype_macros/Cargo.toml b/nutype_macros/Cargo.toml
index 5eac8b5..e3cfcc7 100644
--- a/nutype_macros/Cargo.toml
+++ b/nutype_macros/Cargo.toml
@@ -22,6 +22,7 @@ syn = { version = "2.0", features = ["extra-traits", "full"] }
 # regex is used at compile-time to verify that a string literal provided
 # as `regex = "^foo|bar$"` can be compiled to a Regex without errors.
 regex = { version = "1", optional = true }
+cfg-if = "1.0.0"
 
 [lib]
 proc-macro = true
diff --git a/nutype_macros/src/common/gen/traits.rs b/nutype_macros/src/common/gen/traits.rs
index 7b0f482..2a6d21c 100644
--- a/nutype_macros/src/common/gen/traits.rs
+++ b/nutype_macros/src/common/gen/traits.rs
@@ -1,12 +1,10 @@
 use std::collections::HashSet;
 
+use cfg_if::cfg_if;
 use proc_macro2::TokenStream;
 use quote::{quote, ToTokens};
 
-use crate::{
-    common::models::{ErrorTypeName, InnerType, TypeName},
-    utils::match_feature,
-};
+use crate::common::models::{ErrorTypeName, InnerType, TypeName};
 
 use super::parse_error::{gen_def_parse_error, gen_parse_error_name};
 
@@ -268,16 +266,19 @@ pub fn gen_impl_trait_default(
     // satisfy the validation rules.
     // For this purpose we generate a unit test to verify this at run time.
     let unit_test = if has_validation {
-        match_feature!("nutype_test",
-            on  => quote!(),
-            off => quote!(
-                #[test]
-                fn should_have_valid_default_value() {
-                    let default_inner_value = #type_name::default().into_inner();
-                    #type_name::new(default_inner_value).expect("Default value must be valid");
-                }
-            )
-        )
+        cfg_if! {
+            if #[cfg(feature = "nutype_test")] {
+                quote!()
+            } else {
+                quote!(
+                    #[test]
+                    fn should_have_valid_default_value() {
+                        let default_inner_value = #type_name::default().into_inner();
+                        #type_name::new(default_inner_value).expect("Default value must be valid");
+                    }
+                )
+            }
+        }
     } else {
         quote!()
     };
diff --git a/nutype_macros/src/common/parse/mod.rs b/nutype_macros/src/common/parse/mod.rs
index 9b26486..6309428 100644
--- a/nutype_macros/src/common/parse/mod.rs
+++ b/nutype_macros/src/common/parse/mod.rs
@@ -2,6 +2,7 @@ pub mod meta;
 
 use std::{any::type_name, fmt::Debug, str::FromStr};
 
+use cfg_if::cfg_if;
 use proc_macro2::{Ident, Span, TokenTree};
 use syn::{
     parenthesized,
@@ -11,10 +12,7 @@ use syn::{
     Expr, Lit, Token,
 };
 
-use crate::{
-    common::models::{DeriveTrait, SpannedDeriveTrait},
-    utils::match_feature,
-};
+use crate::common::models::{DeriveTrait, SpannedDeriveTrait};
 
 use super::models::{CustomFunction, NewUnchecked, TypedCustomFunction};
 
@@ -115,28 +113,31 @@ fn parse_ident_into_derive_trait(ident: Ident) -> Result<SpannedDeriveTrait, syn
         "Borrow" => DeriveTrait::Borrow,
         "Default" => DeriveTrait::Default,
         "Serialize" => {
-            match_feature!("serde",
-                on => DeriveTrait::SerdeSerialize,
-                off => {
+            cfg_if! {
+                if #[cfg(feature = "serde")] {
+                    DeriveTrait::SerdeSerialize
+                } else {
                     return Err(syn::Error::new(ident.span(), "To derive Serialize, the feature `serde` of the crate `nutype` needs to be enabled."));
-                },
-            )
+                }
+            }
         }
         "Deserialize" => {
-            match_feature!("serde",
-                on => DeriveTrait::SerdeDeserialize,
-                off => {
+            cfg_if! {
+                if #[cfg(feature = "serde")] {
+                    DeriveTrait::SerdeDeserialize
+                } else {
                     return Err(syn::Error::new(ident.span(), "To derive Deserialize, the feature `serde` of the crate `nutype` needs to be enabled."));
-                },
-            )
+                }
+            }
         }
         "JsonSchema" => {
-            match_feature!("schemars08",
-                on => DeriveTrait::SchemarsJsonSchema,
-                off => {
+            cfg_if! {
+                if #[cfg(feature = "schemars08")] {
+                    DeriveTrait::SchemarsJsonSchema
+                } else {
                     return Err(syn::Error::new(ident.span(), "To derive JsonSchema, the feature `schemars08` of the crate `nutype` needs to be enabled."));
                 }
-            )
+            }
         }
         _ => {
             return Err(syn::Error::new(
@@ -160,7 +161,7 @@ pub struct ParseableAttributes<Sanitizer, Validator> {
     pub default: Option<Expr>,
 }
 
-// By some reason Default cannot be derive.
+// By some reason Default cannot be derived.
 impl<Sanitizer, Validator> Default for ParseableAttributes<Sanitizer, Validator> {
     fn default() -> Self {
         Self {
@@ -211,19 +212,18 @@ impl<Sanitizer: Parse, Validator: Parse> Parse for ParseableAttributes<Sanitizer
                 let default_expr: Expr = input.parse()?;
                 attrs.default = Some(default_expr);
             } else if ident == "new_unchecked" {
-                match_feature!("new_unchecked",
-                    // The feature is not enabled, so we return an error
-                    on => {
+                cfg_if! {
+                    if #[cfg(feature = "new_unchecked")] {
                         attrs.new_unchecked = NewUnchecked::On;
-                    },
-                    off => {
+                    } else {
+                        // The feature is not enabled, so we return an error
                         let msg = concat!(
                             "To generate ::new_unchecked() function, the feature `new_unchecked` of crate `nutype` needs to be enabled.\n",
                             "But you ought to know: generally, THIS IS A BAD IDEA.\nUse it only when you really need it."
                         );
                         return Err(syn::Error::new(ident.span(), msg));
                     }
-                )
+                }
             } else {
                 let msg = format!("Unknown attribute `{ident}`");
                 return Err(syn::Error::new(ident.span(), msg));
diff --git a/nutype_macros/src/lib.rs b/nutype_macros/src/lib.rs
index 0976679..a38b5b0 100644
--- a/nutype_macros/src/lib.rs
+++ b/nutype_macros/src/lib.rs
@@ -2,7 +2,6 @@ mod common;
 mod float;
 mod integer;
 mod string;
-mod utils;
 
 use common::models::{InnerType, Newtype};
 use common::parse::meta::parse_meta;
diff --git a/nutype_macros/src/string/parse.rs b/nutype_macros/src/string/parse.rs
index 0b5b0c7..c2bd7e0 100644
--- a/nutype_macros/src/string/parse.rs
+++ b/nutype_macros/src/string/parse.rs
@@ -3,7 +3,7 @@ use crate::common::parse::{parse_number, parse_typed_custom_function_raw, Parsea
 use crate::string::models::StringGuard;
 use crate::string::models::StringRawGuard;
 use crate::string::models::{StringSanitizer, StringValidator};
-use crate::utils::match_feature;
+use cfg_if::cfg_if;
 use proc_macro2::{Ident, TokenStream};
 use quote::quote;
 use syn::parse::{Parse, ParseStream};
@@ -100,8 +100,8 @@ impl Parse for SpannedStringValidator {
                 span,
             })
         } else if ident == "regex" {
-            match_feature!("regex",
-                on => {
+            cfg_if! {
+                if #[cfg(feature = "regex")] {
                     let _eq: Token![=] = input.parse()?;
                     let SpannedRegexDef {
                         item: regex_def,
@@ -111,8 +111,7 @@ impl Parse for SpannedStringValidator {
                         item: StringValidator::Regex(regex_def),
                         span
                     })
-                },
-                off => {
+                } else {
                     let msg = concat!(
                         "To validate string types with regex, the feature `regex` of the crate `nutype` must be enabled.\n",
                         "IMPORTANT: Make sure that your crate EXPLICITLY depends on `regex` and `lazy_static` crates.\n",
@@ -120,7 +119,7 @@ impl Parse for SpannedStringValidator {
                     );
                     Err(syn::Error::new(ident.span(), msg))
                 }
-            )
+            }
         } else {
             let msg = format!("Unknown validator `{ident}`");
             Err(syn::Error::new(ident.span(), msg))
diff --git a/nutype_macros/src/utils.rs b/nutype_macros/src/utils.rs
deleted file mode 100644
index c71938a..0000000
--- a/nutype_macros/src/utils.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Example:
-//
-//     let msg = match_feature!("foo",
-//         on => "Foo is on!",
-//         off => "Foo is off",
-//     );
-//
-macro_rules! match_feature {
-    // Canonical
-    (
-        $feature_name:literal,
-        on => $on_code:expr,
-        off => $off_code:expr,
-    ) => {{
-        #[cfg(feature = $feature_name)]
-        {
-            $on_code
-        }
-
-        #[cfg(not(feature = $feature_name))]
-        {
-            $off_code
-        }
-    }};
-
-    // Alternative: without trailing comma
-    (
-        $feature_name:literal,
-        on => $on_code:expr,
-        off => $off_code:expr
-    ) => {{
-        match_feature!($feature_name,
-            on => $on_code,
-            off => $off_code,
-        )
-    }}
-}
-
-pub(crate) use match_feature;


Test patch: