From 49e1af5b6d06188327a9972dbfdaae68421a299e Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Mon, 16 Dec 2024 06:59:23 +0800 Subject: [PATCH 1/4] fix typo (#393) --- strum_macros/src/helpers/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strum_macros/src/helpers/mod.rs b/strum_macros/src/helpers/mod.rs index a00e8e4..5d37ea6 100644 --- a/strum_macros/src/helpers/mod.rs +++ b/strum_macros/src/helpers/mod.rs @@ -16,7 +16,7 @@ use syn::spanned::Spanned; pub fn missing_parse_err_attr_error() -> syn::Error { syn::Error::new( Span::call_site(), - "`parse_err_ty` and `parse_err_fn` attribute is both required.", + "`parse_err_ty` and `parse_err_fn` attributes are both required.", ) } From 3408033e9aee44d7c57eef5d3bd414cb48b8f24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Li=C5=A1ka?= Date: Mon, 16 Dec 2024 00:25:39 +0100 Subject: [PATCH 2/4] Implement `get_int`/`get_bool` for properties (#391) * Implement get_bool/get_int for properies * Reimplement using HashMap * Document new methods in EnumProperty section --- strum/src/lib.rs | 22 +++--- strum_macros/src/helpers/metadata.rs | 4 +- strum_macros/src/helpers/variant_props.rs | 6 +- strum_macros/src/macros/enum_properties.rs | 84 +++++++++++++++++----- strum_tests/tests/enum_props.rs | 27 +++++++ 5 files changed, 109 insertions(+), 34 deletions(-) diff --git a/strum/src/lib.rs b/strum/src/lib.rs index 90f2d75..2a6d44c 100644 --- a/strum/src/lib.rs +++ b/strum/src/lib.rs @@ -155,9 +155,8 @@ pub trait EnumMessage { /// `EnumProperty` is a trait that makes it possible to store additional information /// with enum variants. This trait is designed to be used with the macro of the same -/// name in the `strum_macros` crate. Currently, the only string literals are supported -/// in attributes, the other methods will be implemented as additional attribute types -/// become stabilized. +/// name in the `strum_macros` crate. Currently, the string, integer and bool literals +/// are supported in attributes. /// /// # Example /// @@ -168,27 +167,24 @@ pub trait EnumMessage { /// /// #[derive(PartialEq, Eq, Debug, EnumProperty)] /// enum Class { -/// #[strum(props(Teacher="Ms.Frizzle", Room="201"))] +/// #[strum(props(Teacher="Ms.Frizzle", Room="201", students=16, mandatory=true))] /// History, /// #[strum(props(Teacher="Mr.Smith"))] -/// #[strum(props(Room="103"))] +/// #[strum(props(Room="103", students=10))] /// Mathematics, -/// #[strum(props(Time="2:30"))] +/// #[strum(props(Time="2:30", mandatory=true))] /// Science, /// } /// /// let history = Class::History; /// assert_eq!("Ms.Frizzle", history.get_str("Teacher").unwrap()); +/// assert_eq!(16, history.get_int("students").unwrap()); +/// assert!(history.get_bool("mandatory").unwrap()); /// ``` pub trait EnumProperty { fn get_str(&self, prop: &str) -> Option<&'static str>; - fn get_int(&self, _prop: &str) -> Option { - Option::None - } - - fn get_bool(&self, _prop: &str) -> Option { - Option::None - } + fn get_int(&self, _prop: &str) -> Option; + fn get_bool(&self, _prop: &str) -> Option; } /// A cheap reference-to-reference conversion. Used to convert a value to a diff --git a/strum_macros/src/helpers/metadata.rs b/strum_macros/src/helpers/metadata.rs index 40d6394..4c333e4 100644 --- a/strum_macros/src/helpers/metadata.rs +++ b/strum_macros/src/helpers/metadata.rs @@ -204,7 +204,7 @@ pub enum VariantMeta { }, Props { kw: kw::props, - props: Vec<(LitStr, LitStr)>, + props: Vec<(LitStr, Lit)>, }, } @@ -267,7 +267,7 @@ impl Parse for VariantMeta { } } -struct Prop(Ident, LitStr); +struct Prop(Ident, Lit); impl Parse for Prop { fn parse(input: ParseStream) -> syn::Result { diff --git a/strum_macros/src/helpers/variant_props.rs b/strum_macros/src/helpers/variant_props.rs index e0fffdc..ff98817 100644 --- a/strum_macros/src/helpers/variant_props.rs +++ b/strum_macros/src/helpers/variant_props.rs @@ -1,5 +1,5 @@ use std::default::Default; -use syn::{Ident, LitStr, Variant}; +use syn::{Ident, Lit, LitStr, Variant}; use super::case_style::{CaseStyle, CaseStyleHelpers}; use super::metadata::{kw, VariantExt, VariantMeta}; @@ -18,7 +18,7 @@ pub struct StrumVariantProperties { pub message: Option, pub detailed_message: Option, pub documentation: Vec, - pub string_props: Vec<(LitStr, LitStr)>, + pub props: Vec<(LitStr, Lit)>, serialize: Vec, pub to_string: Option, ident: Option, @@ -143,7 +143,7 @@ impl HasStrumVariantProperties for Variant { output.ascii_case_insensitive = Some(value); } VariantMeta::Props { props, .. } => { - output.string_props.extend(props); + output.props.extend(props); } } } diff --git a/strum_macros/src/macros/enum_properties.rs b/strum_macros/src/macros/enum_properties.rs index b2a2b23..4ba9af3 100644 --- a/strum_macros/src/macros/enum_properties.rs +++ b/strum_macros/src/macros/enum_properties.rs @@ -1,9 +1,24 @@ +use std::collections::HashMap; + use proc_macro2::TokenStream; use quote::quote; -use syn::{Data, DeriveInput, Fields}; +use syn::{Data, DeriveInput, Fields, Lit}; use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties}; +#[derive(Hash, PartialEq, Eq)] +enum PropertyType { + String, + Integer, + Bool, +} + +const PROPERTY_TYPES: [PropertyType; 3] = [ + PropertyType::String, + PropertyType::Integer, + PropertyType::Bool, +]; + pub fn enum_properties_inner(ast: &DeriveInput) -> syn::Result { let name = &ast.ident; let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); @@ -14,11 +29,12 @@ pub fn enum_properties_inner(ast: &DeriveInput) -> syn::Result { let type_properties = ast.get_type_properties()?; let strum_module_path = type_properties.crate_module_path(); - let mut arms = Vec::new(); + let mut built_arms: HashMap<_, _> = PROPERTY_TYPES.iter().map(|p| (p, Vec::new())).collect(); + for variant in variants { let ident = &variant.ident; let variant_properties = variant.get_variant_properties()?; - let mut string_arms = Vec::new(); + let mut arms: HashMap<_, _> = PROPERTY_TYPES.iter().map(|p| (p, Vec::new())).collect(); // But you can disable the messages. if variant_properties.disabled.is_some() { continue; @@ -30,33 +46,69 @@ pub fn enum_properties_inner(ast: &DeriveInput) -> syn::Result { Fields::Named(..) => quote! { {..} }, }; - for (key, value) in variant_properties.string_props { - string_arms.push(quote! { #key => ::core::option::Option::Some( #value )}); - } + for (key, value) in variant_properties.props { + let property_type = match value { + Lit::Str(..) => PropertyType::String, + Lit::Bool(..) => PropertyType::Bool, + Lit::Int(..) => PropertyType::Integer, + _ => todo!("TODO"), + }; - string_arms.push(quote! { _ => ::core::option::Option::None }); + arms.get_mut(&property_type) + .unwrap() + .push(quote! { #key => ::core::option::Option::Some( #value )}); + } - arms.push(quote! { - &#name::#ident #params => { - match prop { - #(#string_arms),* + for property in &PROPERTY_TYPES { + arms.get_mut(&property) + .unwrap() + .push(quote! { _ => ::core::option::Option::None }); + let arms_as_string = &arms[property]; + built_arms.get_mut(&property).unwrap().push(quote! { + &#name::#ident #params => { + match prop { + #(#arms_as_string),* + } } - } - }); + }); + } } - if arms.len() < variants.len() { - arms.push(quote! { _ => ::core::option::Option::None }); + for (_, arms) in built_arms.iter_mut() { + if arms.len() < variants.len() { + arms.push(quote! { _ => ::core::option::Option::None }); + } } + let (built_string_arms, built_int_arms, built_bool_arms) = ( + &built_arms[&PropertyType::String], + &built_arms[&PropertyType::Integer], + &built_arms[&PropertyType::Bool], + ); + Ok(quote! { impl #impl_generics #strum_module_path::EnumProperty for #name #ty_generics #where_clause { #[inline] fn get_str(&self, prop: &str) -> ::core::option::Option<&'static str> { match self { - #(#arms),* + #(#built_string_arms),* } } + + #[inline] + fn get_int(&self, prop: &str) -> ::core::option::Option { + match self { + #(#built_int_arms),* + } + } + + #[inline] + fn get_bool(&self, prop: &str) -> ::core::option::Option { + match self { + #(#built_bool_arms),* + } + } + } }) } diff --git a/strum_tests/tests/enum_props.rs b/strum_tests/tests/enum_props.rs index c32c07e..3a2ed32 100644 --- a/strum_tests/tests/enum_props.rs +++ b/strum_tests/tests/enum_props.rs @@ -47,3 +47,30 @@ fn crate_module_path_test() { let a = Test::A; assert_eq!("value", a.get_str("key").unwrap()); } + +#[derive(Debug, EnumProperty)] +enum TestGet { + #[strum(props(weight = 42, flat = true, big = false))] + A, + #[strum(props(weight = -42, flat = false))] + B, + C, +} + +#[test] +fn get_bool_test() { + const BOOL_KEY: &str = "flat"; + assert_eq!(Some(true), TestGet::A.get_bool(BOOL_KEY)); + assert_eq!(Some(false), TestGet::B.get_bool(BOOL_KEY)); + assert_eq!(None, TestGet::C.get_bool(BOOL_KEY)); + assert_eq!(None, TestGet::A.get_bool("weight")); +} + +#[test] +fn get_int_test() { + const INT_KEY: &str = "weight"; + assert_eq!(Some(42), TestGet::A.get_int(INT_KEY)); + assert_eq!(Some(-42), TestGet::B.get_int(INT_KEY)); + assert_eq!(None, TestGet::C.get_int(INT_KEY)); + assert_eq!(None, TestGet::A.get_int("flat")); +} From 73ef6bfe66535554bfe9d9cb101cc1ff041b9060 Mon Sep 17 00:00:00 2001 From: MHS-0 Date: Wed, 1 Jan 2025 12:36:46 +0330 Subject: [PATCH 3/4] Upgrade dependencies to the latest possible version where possible enum_variant_type wasn't upgraded as it will stop us from making sure that ::core is used in macros --- Cargo.toml | 2 +- strum/Cargo.toml | 5 +++-- strum_macros/Cargo.toml | 3 ++- strum_macros/src/lib.rs | 7 ++++--- strum_nostd_tests/Cargo.toml | 7 +++---- strum_tests/Cargo.toml | 8 ++++---- strum_tests/tests/enum_variant_names.rs | 10 +++++----- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 094b6e6..bbd6c9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,4 @@ members = [ "strum_tests", "strum_nostd_tests" ] - \ No newline at end of file +resolver = "2" diff --git a/strum/Cargo.toml b/strum/Cargo.toml index 2152d63..c53dc83 100644 --- a/strum/Cargo.toml +++ b/strum/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "strum" version = "0.26.3" -edition = "2018" +edition = "2021" authors = ["Peter Glotfelty "] license = "MIT" @@ -13,10 +13,11 @@ documentation = "https://docs.rs/strum" homepage = "https://github.com/Peternator7/strum" repository = "https://github.com/Peternator7/strum" readme = "../README.md" +rust-version = "1.66.1" [dependencies] strum_macros = { path = "../strum_macros", optional = true, version = "0.26.3" } -phf = { version = "0.10", features = ["macros"], optional = true } +phf = { version = "0.11.2", features = ["macros"], optional = true } [dev-dependencies] strum_macros = { path = "../strum_macros", version = "0.26" } diff --git a/strum_macros/Cargo.toml b/strum_macros/Cargo.toml index 243d723..f76a994 100644 --- a/strum_macros/Cargo.toml +++ b/strum_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "strum_macros" version = "0.26.4" -edition = "2018" +edition = "2021" authors = ["Peter Glotfelty "] license = "MIT" @@ -13,6 +13,7 @@ documentation = "https://docs.rs/strum" homepage = "https://github.com/Peternator7/strum" repository = "https://github.com/Peternator7/strum" readme = "../README.md" +rust-version = "1.66.1" [lib] proc-macro = true diff --git a/strum_macros/src/lib.rs b/strum_macros/src/lib.rs index 5954ca1..108654b 100644 --- a/strum_macros/src/lib.rs +++ b/strum_macros/src/lib.rs @@ -237,7 +237,8 @@ pub fn variant_names_deprecated(input: proc_macro::TokenStream) -> proc_macro::T /// meaning that the variants must not have any data. /// /// ``` -/// use strum::VariantArray; +/// use strum::VariantArray as _; +/// use strum_macros::VariantArray; /// /// #[derive(VariantArray, Debug, PartialEq, Eq)] /// enum Op { @@ -830,8 +831,8 @@ pub fn enum_properties(input: proc_macro::TokenStream) -> proc_macro::TokenStrea /// ``` /// // Bring trait into scope /// use std::str::FromStr; -/// use strum::{IntoEnumIterator, EnumMessage}; -/// use strum_macros::{EnumDiscriminants, EnumIter, EnumString}; +/// use strum::{IntoEnumIterator, EnumMessage as _}; +/// use strum_macros::{EnumDiscriminants, EnumIter, EnumString, EnumMessage}; /// /// #[derive(Debug)] /// struct NonDefault; diff --git a/strum_nostd_tests/Cargo.toml b/strum_nostd_tests/Cargo.toml index 9129c4a..4d0f8af 100644 --- a/strum_nostd_tests/Cargo.toml +++ b/strum_nostd_tests/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "strum_nostd_tests" version = "0.26.0" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +edition = "2021" +rust-version = "1.66.1" [dependencies] strum = { path = "../strum", features = ["derive"] } strum_macros = { path = "../strum_macros", features = [] } [dev-dependencies] -rustversion = "1.0" \ No newline at end of file +rustversion = "1.0" diff --git a/strum_tests/Cargo.toml b/strum_tests/Cargo.toml index d166a6b..c66b6c6 100644 --- a/strum_tests/Cargo.toml +++ b/strum_tests/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "strum_tests" version = "0.26.0" -edition = "2018" +edition = "2021" authors = ["Peter Glotfelty "] +rust-version = "1.66.1" [features] default = [] @@ -11,10 +12,9 @@ test_phf = ["strum/phf"] [dependencies] strum = { path = "../strum", features = ["derive"] } strum_macros = { path = "../strum_macros", features = [] } -clap = "=2.33.0" +clap = "=4.2.7" enum_variant_type = "=0.2.0" -structopt = "0.2.18" -bitflags = "=1.2" +structopt = "=0.3.26" [dev-dependencies] rustversion = "1.0" diff --git a/strum_tests/tests/enum_variant_names.rs b/strum_tests/tests/enum_variant_names.rs index c6f77e6..233e634 100644 --- a/strum_tests/tests/enum_variant_names.rs +++ b/strum_tests/tests/enum_variant_names.rs @@ -80,7 +80,7 @@ fn clap_and_structopt() { #[structopt( long = "color", default_value = "Color::Blue", - raw(possible_values = "Color::VARIANTS") + possible_values = Color::VARIANTS )] color: Color, } @@ -99,11 +99,11 @@ fn clap_and_structopt() { &["red", "blue", "yellow", "rebecca-purple"] ); - let _clap_example = clap::App::new("app").arg( - clap::Arg::with_name("color") + let _clap_example = clap::Command::new("app").arg( + clap::Arg::new("color") .long("color") - .possible_values(Color::VARIANTS) - .case_insensitive(true), + .value_names(Color::VARIANTS) + .ignore_case(true), ); } From 8903ea052f70f67914864598a6f03beec0766e3b Mon Sep 17 00:00:00 2001 From: Joel Natividad <1980690+jqnatividad@users.noreply.github.com> Date: Sun, 12 Jan 2025 17:28:20 -0500 Subject: [PATCH 4/4] deps: bumped phf to 0.11 (#401) --- strum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strum/Cargo.toml b/strum/Cargo.toml index 2152d63..cb1c8b5 100644 --- a/strum/Cargo.toml +++ b/strum/Cargo.toml @@ -16,7 +16,7 @@ readme = "../README.md" [dependencies] strum_macros = { path = "../strum_macros", optional = true, version = "0.26.3" } -phf = { version = "0.10", features = ["macros"], optional = true } +phf = { version = "0.11", features = ["macros"], optional = true } [dev-dependencies] strum_macros = { path = "../strum_macros", version = "0.26" }