Update strum_macros to 0.26.2

Test: m
Change-Id: Ia4b992b3227b2bde5ca332adea4fded67fe0b28d
diff --git a/crates/strum_macros/.android-checksum.json b/crates/strum_macros/.android-checksum.json
new file mode 100644
index 0000000..36dc750
--- /dev/null
+++ b/crates/strum_macros/.android-checksum.json
@@ -0,0 +1 @@
+{"package":null,"files":{"src/lib.rs":"52d5f49927e5e5c3e3d6bd668c5a24599c516121df7cbd79145943cd804586d0","src/macros/enum_discriminants.rs":"d80616c8889ace6e1f1e8eb036140a7127bb0a536414a20cc984933b72aa41c0","MODULE_LICENSE_MIT":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","src/helpers/case_style.rs":"a401e30dc1198a382681dfbc7edabe641df80e6717b6b57ad3d8f9d3457c24ca","src/macros/from_repr.rs":"83b62edd8bfe91db286bd1531a77082d30d4f9d4ee8185f7a95689fa4860365f","src/macros/strings/display.rs":"20388c5ff17fe164d99988ca3557b0e4db2e54ca90ac4fd6b3bc34443ddbf9b4","src/macros/enum_iter.rs":"761d34a9633be1f920cc04910cd70e39dd2e1830fdb3a7239eb95d79e30f7a4f","TEST_MAPPING":"130934553eb809f532f064b6d924421ef21dc989325f59a50bd6f726f2cba884","LICENSE":"1884079d8260fd6643f913346f742df6dabc32a0d1d1a973f6c70b2ae20383fe","src/helpers/variant_props.rs":"c007bed549c30a6c9a64521639608e7dd3e6f9c70553ec78a183ebda02bddd54","src/macros/enum_table.rs":"8002a82697ae43cba9cbb77baf3c6aa60f810f948c7ca97d46f0a2a96e5dbdfe","src/macros/strings/mod.rs":"5f0003e2cb561686d347d008fd890d52a691e40bdbeef8a36fadc11512abcfbe","src/helpers/type_props.rs":"9f7227dfe0f9ab4f1ee4dfdcb960c49db4706497861ae82cc9a9db904287ebab","src/macros/enum_properties.rs":"c1a386c408a09b7af7754b0e28220ebae02abd75b123d0edac8a0f00880a633b","Cargo.toml":"90f40b0d04e3d330cd5fae3c5d1d04944045e3a0ba8dce9a0bd47423d29c53e0","src/helpers/metadata.rs":"abb82cefe57fc10d87c4fe5a4846eacd97ca3306851e28b7c7699fbdec412ddf","METADATA":"8f07cd6e794503efad77467157be7fa09c030036131a37cc2da4842029a20eeb","src/helpers/mod.rs":"928c2e83113fac0183b291b2e064bd6444140698e4b4f2410e55d85ea1deab28","src/macros/enum_variant_array.rs":"4a82897758e6059aae96e8d999e7c69e226bd61fe54c0d9cf610bdfd38e407b9","src/macros/enum_variant_names.rs":"9c3bac48f80b7aab75d779377de56ba143e7f831d659bb4e1070ee4e6181d2fe","src/macros/strings/to_string.rs":"ef77f2087f20dfc2775324e99e178bc40831c1a3017de1a58104b901daced823","src/macros/enum_try_as.rs":"6299527af91a6478ca48c56871c2649cb19eaa371186b08b81fc21bea76b18c6","src/macros/enum_is.rs":"a67764b68d10774516aec79b4a121aa8526b85c1ba4eb19406ea839925ac2fbf","src/macros/enum_count.rs":"c3f068684816e891171537745c5a4a86bbb76f74578e079880a874ef0d1e7fc5","src/macros/mod.rs":"d3f44f5625d76d0f114ff394d6b95723ca9f6b2a089784c09b12dab42f54cc47","src/macros/strings/from_string.rs":"913f990421d76985c4a609fc13d58f31c7b25dfc48f37c564feaf48a61e66fe0","README.md":"01b98982954529385a99d3557d04bfd9d4ff2773a87fc5a8cf5d57680fe936a2","cargo_embargo.json":"fa702ccdadce959e0baa3621834e37c34b5b20d1d2993055e3efbb9ad62a03b8","src/helpers/inner_variant_props.rs":"fb25aac1a36405f4912d239241ed50d304946b3bdff79bd90466b41fa99785cc","Android.bp":"adc2184a419c0200731d0e6a81a8d1a449083737aa53c9014586e420b74fb751","src/macros/enum_messages.rs":"ad5fc215c0e992dc09024c3ad76b8bd18a56147170bab71ab964e58c44e82cad","src/macros/strings/as_ref_str.rs":"9f7b73f0848d346f54f0efb78de66da53c29b4d22386075554eed603e4fdb93d",".cargo-checksum.json":"5c20c1ce69ea23d2d61dcf13b032ae2aa2b29fa8a34e1abf2f57e4d355ad8bc4"}}
\ No newline at end of file
diff --git a/crates/strum_macros/.cargo-checksum.json b/crates/strum_macros/.cargo-checksum.json
index a9f9601..16f7225 100644
--- a/crates/strum_macros/.cargo-checksum.json
+++ b/crates/strum_macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"23072aa33960a8ac715daca71a1aef3236d09e65c8b3dc1c69b1fd0ab5f83a90","LICENSE":"8bce3b45e49ecd1461f223b46de133d8f62cd39f745cfdaf81bee554b908bd42","README.md":"78ad65413ae9989028bfef9ebf198dee8dc74af3ec7fb60d26e0d984b979c126","src/helpers/case_style.rs":"6094ea43fb51d249f0685957060bd7170e5bcea3356a93569a01ef011dc41cdb","src/helpers/metadata.rs":"87320d82b70220a75ccf411dc66a4e0b9eb959e7ad1602d82006a7cd07d6e310","src/helpers/mod.rs":"e3e8977fcf94b7cf3b769d976cc998707cc4641e5857f88859a10d2dc1bd8d5a","src/helpers/type_props.rs":"f9c5f1ae29173f5dd51025f83e723e176d47b01de0abc45105cedaa7abccbb47","src/helpers/variant_props.rs":"d528ce14015850ac1b34cbea46a8836bdaf50a290a2fe92ca560af6b192b5507","src/lib.rs":"eb2cc12a6136780ba93ab069d01fdfdaa41b3ca959ccb6f5350ec9006f778d0b","src/macros/enum_count.rs":"44084ab800ca8fca3b17f76c6025e8e59855598c0119807ce7bc80d5dc345d99","src/macros/enum_discriminants.rs":"7513c5eb515da55ff6507c8fd80fd1c626de78e68ea737d3edea48e0ee56337c","src/macros/enum_is.rs":"c56e67aa93b173b1fc0301106864ed567bc708e55bc28982ad05f5c8efa343ce","src/macros/enum_iter.rs":"81f62d61cfe50320ee4cacb09d19f817ec04c0b7c77c6a7aad24dafe093eedab","src/macros/enum_messages.rs":"d23b427e1b0f8ab9709e93837aba16bff12ccd92fb55bf013ca80a292ed7ffc5","src/macros/enum_properties.rs":"a9e1bf27504d46df689aad8910c7ad8ae7b3780ee97b6e659b2b19e481474030","src/macros/enum_try_as.rs":"b3bbc5020351251f005cfadf86a8759bb28172c9d176684b90074d32cc2ae3dd","src/macros/enum_variant_names.rs":"7d6d381ab10c603d1e87a089057138ef21c9b3de1246ba1fdcec894ef239a461","src/macros/from_repr.rs":"69b904604cdb0287f9dccafa15592627e32d3edd2310a2ddaa53a5547e903f71","src/macros/mod.rs":"13b0e3b5ddc63e4750aa29fbdb4a338307367cf148099b17813e340fe5dfdf32","src/macros/strings/as_ref_str.rs":"73ce53ae25c8a148075e858ab03eb13fe7cba350cfb649048b5b6582703fc5da","src/macros/strings/display.rs":"c53989fcb45a9d22f0990cf620e0ffff9e2d9e46a93edc780901ab43650dfb29","src/macros/strings/from_string.rs":"99d8b8c1a7aa99ab12f63e5f74e96c980e17740738e800a854d688d6fed59ecb","src/macros/strings/mod.rs":"b7937f72a46c807fd87c787f3d23029509565a0388a30106e7026363782f2b56","src/macros/strings/to_string.rs":"3d43865603be815cc52a8364bc3e969af7a1bd9532d9461fcce8252098488b0a"},"package":"23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"}
\ No newline at end of file
+{"files":{"Cargo.toml":"092265d6ab49a30549ada59bb62e244b28649758ec3a789af589b09e07c3cc48","LICENSE":"8bce3b45e49ecd1461f223b46de133d8f62cd39f745cfdaf81bee554b908bd42","README.md":"4d1475987c8866226ac2f4136dfb5196dfd0b16a2fa3d63ddbd0f4f5011f65af","src/helpers/case_style.rs":"ac429454fad24d1a5a9829711f2024ae9477ffad7cc293b711fe588d1a5e1edf","src/helpers/inner_variant_props.rs":"09c4a2c73aadaaa934e6a20b429b99d4229ce76a4cc1edc916298100d971deb4","src/helpers/metadata.rs":"a9391071f1d4750781eda79bdf4553e77c65c28b1df87dfb3d00df6b290c18dd","src/helpers/mod.rs":"dc171dd27e723aede6c45cb981d48c710f42167afb06a5fbf013470a2962b9f2","src/helpers/type_props.rs":"cb1cdfb0e7927d3b0e364237e7048285ef5968e036d2ebacea642c66d96cc669","src/helpers/variant_props.rs":"36cc466e29b20246f87b9b87d39e4d23545596c522a201e0fb320ac2b231b045","src/lib.rs":"5198869272f00b3adc78d2ffbfb129f42062f3d5c1f3d06fe081a06c3440b51f","src/macros/enum_count.rs":"44084ab800ca8fca3b17f76c6025e8e59855598c0119807ce7bc80d5dc345d99","src/macros/enum_discriminants.rs":"98abbefad100dda4aaafa959ebb9fa77f518dd483414113e6c8bd1eea193bdff","src/macros/enum_is.rs":"cd63fb79f4f9b3479f11bce2ad45d3cb5d23f1d5c9c2a5fbb7af7e813fb70fa7","src/macros/enum_iter.rs":"a6c42eefae4e442301dfd9a622aa6a502aac7a0fc9ab7e2b8aaea221cd9d06b0","src/macros/enum_messages.rs":"ee89c3a10ebb553aa9c342f4b3b4346e97be1744fc5df72f580a331d4ea87393","src/macros/enum_properties.rs":"a9e1bf27504d46df689aad8910c7ad8ae7b3780ee97b6e659b2b19e481474030","src/macros/enum_table.rs":"434da77cbca12082d4daeba28ef0e416cea3064f1f641b31f4a330589369e04f","src/macros/enum_try_as.rs":"8bd311522786f0186290ea31a6f3483aa3fa23ccb3441b7fcf9b3743c9d3670b","src/macros/enum_variant_array.rs":"cb8de5cb5841fa9514c423c195b47a2fc13b9f5fb257093311fbb9c136c737d9","src/macros/enum_variant_names.rs":"ad4d2f87bf26e4d07327896118382a4b83c2cca5de6fdfecca6e7639eb73118b","src/macros/from_repr.rs":"561a6f10372c365674e064b31c6eb4c531ffa0b39f03476452bb0746201d579d","src/macros/mod.rs":"c94b29d4ad0f40a7803605d42647cc9fafec76545c7f3c435fe675a3102eb0ef","src/macros/strings/as_ref_str.rs":"594f29efd111ceef258ab0dd449db4cb52e638e1bd17efe589c5a90ee03686b9","src/macros/strings/display.rs":"30b2c4d4f2f29c98058dd88d004782688241a2608d2976621c6919ea0cf615cb","src/macros/strings/from_string.rs":"53d298f6859df3c13197a8bd303971d2a9ac14cb9860ea1e7c4df1bffdea58bd","src/macros/strings/mod.rs":"b7937f72a46c807fd87c787f3d23029509565a0388a30106e7026363782f2b56","src/macros/strings/to_string.rs":"983e6c1b1dec145acfa0c6a7ef8ff01d30507145753a1d85d0387c5ab61f6fa1"},"package":"c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"}
\ No newline at end of file
diff --git a/crates/strum_macros/Android.bp b/crates/strum_macros/Android.bp
index 344b2b7..fceb38a 100644
--- a/crates/strum_macros/Android.bp
+++ b/crates/strum_macros/Android.bp
@@ -17,7 +17,7 @@
     name: "libstrum_macros",
     crate_name: "strum_macros",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.25.3",
+    cargo_pkg_version: "0.26.2",
     crate_root: "src/lib.rs",
     edition: "2018",
     rustlibs: [
@@ -34,7 +34,7 @@
     host_cross_supported: false,
     crate_name: "strum_macros",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.25.3",
+    cargo_pkg_version: "0.26.2",
     crate_root: "src/lib.rs",
     test_suites: ["general-tests"],
     auto_gen_config: true,
diff --git a/crates/strum_macros/Cargo.toml b/crates/strum_macros/Cargo.toml
index 45078e7..9748353 100644
--- a/crates/strum_macros/Cargo.toml
+++ b/crates/strum_macros/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2018"
 name = "strum_macros"
-version = "0.25.3"
+version = "0.26.2"
 authors = ["Peter Glotfelty <peter.glotfelty@microsoft.com>"]
 description = "Helpful macros for working with enums and strings"
 homepage = "https://github.com/Peternator7/strum"
@@ -55,4 +55,4 @@
 ]
 
 [dev-dependencies.strum]
-version = "0.25"
+version = "0.26"
diff --git a/crates/strum_macros/METADATA b/crates/strum_macros/METADATA
index 9df3aeb..9e6d739 100644
--- a/crates/strum_macros/METADATA
+++ b/crates/strum_macros/METADATA
@@ -1,17 +1,17 @@
 name: "strum_macros"
 description: "Helpful macros for working with enums and strings"
 third_party {
-  version: "0.25.3"
+  version: "0.26.2"
   license_type: NOTICE
   last_upgrade_date {
     year: 2024
-    month: 1
-    day: 17
+    month: 12
+    day: 20
   }
   homepage: "https://crates.io/crates/strum_macros"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/strum_macros/strum_macros-0.25.3.crate"
-    version: "0.25.3"
+    value: "https://static.crates.io/crates/strum_macros/strum_macros-0.26.2.crate"
+    version: "0.26.2"
   }
 }
diff --git a/crates/strum_macros/README.md b/crates/strum_macros/README.md
index 491c24f..4099439 100644
--- a/crates/strum_macros/README.md
+++ b/crates/strum_macros/README.md
@@ -22,11 +22,11 @@
 
 ```toml
 [dependencies]
-strum = "0.25"
-strum_macros = "0.25"
+strum = "0.26"
+strum_macros = "0.26"
 
 # You can also use the "derive" feature, and import the macros directly from "strum"
-# strum = { version = "0.25", features = ["derive"] }
+# strum = { version = "0.26", features = ["derive"] }
 ```
 
 # Strum Macros
@@ -40,16 +40,21 @@
 | [FromRepr] | Convert from an integer to an enum. |
 | [AsRefStr] | Implement `AsRef<str>` for `MyEnum` |
 | [IntoStaticStr] | Implements `From<MyEnum> for &'static str` on an enum |
-| [EnumVariantNames] | Adds an associated `VARIANTS` constant which is an array of discriminant names |
 | [EnumIter] | Creates a new type that iterates of the variants of an enum. |
 | [EnumProperty] | Add custom properties to enum variants. |
 | [EnumMessage] | Add a verbose message to an enum variant. |
 | [EnumDiscriminants] | Generate a new type with only the discriminant names. |
 | [EnumCount] | Add a constant `usize` equal to the number of variants. |
+| [VariantArray] | Adds an associated `VARIANTS` constant which is an array of all enum discriminants |
+| [VariantNames] | Adds an associated `VARIANTS` constant which is an array of discriminant names |
+| [EnumTable] | *Experimental*, creates a new type that stores an item of a specified type for each variant of the enum. |
 
 # Contributing
 
-Thanks for your interest in contributing. The project is divided into 3 parts, the traits are in the
+Thanks for your interest in contributing. Bug fixes are always welcome. If you are interested in implementing or
+adding a macro, please open an issue first to discuss the feature. I have limited bandwidth to review new features.
+
+The project is divided into 3 parts, the traits are in the
 `/strum` folder. The procedural macros are in the `/strum_macros` folder, and the integration tests are
 in `/strum_tests`. If you are adding additional features to `strum` or `strum_macros`, you should make sure
 to run the tests and add new integration tests to make sure the features work as expected.
@@ -67,16 +72,17 @@
 
 Strumming is also a very whimsical motion, much like writing Rust code.
 
-[Macro-Renames]: https://github.com/Peternator7/strum/wiki/Macro-Renames
-[EnumString]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumString.html
-[Display]: https://docs.rs/strum_macros/0.25/strum_macros/derive.Display.html
-[AsRefStr]: https://docs.rs/strum_macros/0.25/strum_macros/derive.AsRefStr.html
-[IntoStaticStr]: https://docs.rs/strum_macros/0.25/strum_macros/derive.IntoStaticStr.html
-[EnumVariantNames]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumVariantNames.html
-[EnumIter]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumIter.html
-[EnumIs]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumIs.html
-[EnumProperty]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumProperty.html
-[EnumMessage]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumMessage.html
-[EnumDiscriminants]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumDiscriminants.html
-[EnumCount]: https://docs.rs/strum_macros/0.25/strum_macros/derive.EnumCount.html
-[FromRepr]: https://docs.rs/strum_macros/0.25/strum_macros/derive.FromRepr.html
+[EnumString]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumString.html
+[Display]: https://docs.rs/strum_macros/latest/strum_macros/derive.Display.html
+[AsRefStr]: https://docs.rs/strum_macros/latest/strum_macros/derive.AsRefStr.html
+[IntoStaticStr]: https://docs.rs/strum_macros/latest/strum_macros/derive.IntoStaticStr.html
+[EnumIter]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumIter.html
+[EnumIs]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumIs.html
+[EnumProperty]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumProperty.html
+[EnumMessage]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumMessage.html
+[EnumDiscriminants]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumDiscriminants.html
+[EnumCount]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumCount.html
+[FromRepr]: https://docs.rs/strum_macros/latest/strum_macros/derive.FromRepr.html
+[VariantArray]: https://docs.rs/strum_macros/latest/strum_macros/derive.StaticVariantsArray.html
+[VariantNames]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumVariantNames.html
+[EnumTable]: https://docs.rs/strum_macros/latest/strum_macros/derive.EnumTable.html
diff --git a/crates/strum_macros/src/helpers/case_style.rs b/crates/strum_macros/src/helpers/case_style.rs
index 86a8583..bcea788 100644
--- a/crates/strum_macros/src/helpers/case_style.rs
+++ b/crates/strum_macros/src/helpers/case_style.rs
@@ -1,5 +1,6 @@
 use heck::{
-    ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase, ToUpperCamelCase, ToTrainCase,
+    ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase, ToTrainCase,
+    ToUpperCamelCase,
 };
 use std::str::FromStr;
 use syn::{
diff --git a/crates/strum_macros/src/helpers/inner_variant_props.rs b/crates/strum_macros/src/helpers/inner_variant_props.rs
new file mode 100644
index 0000000..bc0fe79
--- /dev/null
+++ b/crates/strum_macros/src/helpers/inner_variant_props.rs
@@ -0,0 +1,33 @@
+use super::metadata::{InnerVariantExt, InnerVariantMeta};
+use super::occurrence_error;
+use syn::{Field, LitStr};
+
+pub trait HasInnerVariantProperties {
+    fn get_variant_inner_properties(&self) -> syn::Result<StrumInnerVariantProperties>;
+}
+
+#[derive(Clone, Eq, PartialEq, Debug, Default)]
+pub struct StrumInnerVariantProperties {
+    pub default_with: Option<LitStr>,
+}
+
+impl HasInnerVariantProperties for Field {
+    fn get_variant_inner_properties(&self) -> syn::Result<StrumInnerVariantProperties> {
+        let mut output = StrumInnerVariantProperties { default_with: None };
+
+        let mut default_with_kw = None;
+        for meta in self.get_named_metadata()? {
+            match meta {
+                InnerVariantMeta::DefaultWith { kw, value } => {
+                    if let Some(fst_kw) = default_with_kw {
+                        return Err(occurrence_error(fst_kw, kw, "default_with"));
+                    }
+                    default_with_kw = Some(kw);
+                    output.default_with = Some(value);
+                }
+            }
+        }
+
+        Ok(output)
+    }
+}
diff --git a/crates/strum_macros/src/helpers/metadata.rs b/crates/strum_macros/src/helpers/metadata.rs
index d638ae3..94100a7 100644
--- a/crates/strum_macros/src/helpers/metadata.rs
+++ b/crates/strum_macros/src/helpers/metadata.rs
@@ -4,8 +4,8 @@
     parse::{Parse, ParseStream},
     parse2, parse_str,
     punctuated::Punctuated,
-    Attribute, DeriveInput, Expr, ExprLit, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue, Path,
-    Token, Variant, Visibility,
+    Attribute, DeriveInput, Expr, ExprLit, Field, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue,
+    Path, Token, Variant, Visibility,
 };
 
 use super::case_style::CaseStyle;
@@ -17,6 +17,7 @@
     // enum metadata
     custom_keyword!(serialize_all);
     custom_keyword!(use_phf);
+    custom_keyword!(prefix);
 
     // enum discriminant metadata
     custom_keyword!(derive);
@@ -30,6 +31,7 @@
     custom_keyword!(to_string);
     custom_keyword!(disabled);
     custom_keyword!(default);
+    custom_keyword!(default_with);
     custom_keyword!(props);
     custom_keyword!(ascii_case_insensitive);
 }
@@ -45,6 +47,10 @@
         crate_module_path: Path,
     },
     UsePhf(kw::use_phf),
+    Prefix {
+        kw: kw::prefix,
+        prefix: LitStr,
+    },
 }
 
 impl Parse for EnumMeta {
@@ -69,6 +75,11 @@
             Ok(EnumMeta::AsciiCaseInsensitive(input.parse()?))
         } else if lookahead.peek(kw::use_phf) {
             Ok(EnumMeta::UsePhf(input.parse()?))
+        } else if lookahead.peek(kw::prefix) {
+            let kw = input.parse::<kw::prefix>()?;
+            input.parse::<Token![=]>()?;
+            let prefix = input.parse()?;
+            Ok(EnumMeta::Prefix { kw, prefix })
         } else {
             Err(lookahead.error())
         }
@@ -155,6 +166,10 @@
     },
     Disabled(kw::disabled),
     Default(kw::default),
+    DefaultWith {
+        kw: kw::default_with,
+        value: LitStr,
+    },
     AsciiCaseInsensitive {
         kw: kw::ascii_case_insensitive,
         value: bool,
@@ -192,6 +207,11 @@
             Ok(VariantMeta::Disabled(input.parse()?))
         } else if lookahead.peek(kw::default) {
             Ok(VariantMeta::Default(input.parse()?))
+        } else if lookahead.peek(kw::default_with) {
+            let kw = input.parse()?;
+            let _: Token![=] = input.parse()?;
+            let value = input.parse()?;
+            Ok(VariantMeta::DefaultWith { kw, value })
         } else if lookahead.peek(kw::ascii_case_insensitive) {
             let kw = input.parse()?;
             let value = if input.peek(Token![=]) {
@@ -243,7 +263,7 @@
         let result = get_metadata_inner("strum", &self.attrs)?;
         self.attrs
             .iter()
-            .filter(|attr| attr.path().is_ident("doc"))
+            .filter(|attr| attr.meta.path().is_ident("doc"))
             .try_fold(result, |mut vec, attr| {
                 if let Meta::NameValue(MetaNameValue {
                     value:
@@ -274,3 +294,37 @@
             Ok(vec)
         })
 }
+
+#[derive(Debug)]
+pub enum InnerVariantMeta {
+    DefaultWith { kw: kw::default_with, value: LitStr },
+}
+
+impl Parse for InnerVariantMeta {
+    fn parse(input: ParseStream) -> syn::Result<Self> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(kw::default_with) {
+            let kw = input.parse()?;
+            let _: Token![=] = input.parse()?;
+            let value = input.parse()?;
+            Ok(InnerVariantMeta::DefaultWith { kw, value })
+        } else {
+            Err(lookahead.error())
+        }
+    }
+}
+
+pub trait InnerVariantExt {
+    /// Get all the metadata associated with an enum variant inner.
+    fn get_named_metadata(&self) -> syn::Result<Vec<InnerVariantMeta>>;
+}
+
+impl InnerVariantExt for Field {
+    fn get_named_metadata(&self) -> syn::Result<Vec<InnerVariantMeta>> {
+        let result = get_metadata_inner("strum", &self.attrs)?;
+        self.attrs
+            .iter()
+            .filter(|attr| attr.meta.path().is_ident("default_with"))
+            .try_fold(result, |vec, _attr| Ok(vec))
+    }
+}
diff --git a/crates/strum_macros/src/helpers/mod.rs b/crates/strum_macros/src/helpers/mod.rs
index 142ea0b..23d60b5 100644
--- a/crates/strum_macros/src/helpers/mod.rs
+++ b/crates/strum_macros/src/helpers/mod.rs
@@ -1,8 +1,10 @@
-pub use self::case_style::{CaseStyleHelpers, snakify};
+pub use self::case_style::snakify;
+pub use self::inner_variant_props::HasInnerVariantProperties;
 pub use self::type_props::HasTypeProperties;
 pub use self::variant_props::HasStrumVariantProperties;
 
 pub mod case_style;
+pub mod inner_variant_props;
 mod metadata;
 pub mod type_props;
 pub mod variant_props;
@@ -15,6 +17,14 @@
     syn::Error::new(Span::call_site(), "This macro only supports enums.")
 }
 
+pub fn non_unit_variant_error() -> syn::Error {
+    syn::Error::new(
+        Span::call_site(),
+        "This macro only supports enums of strictly unit variants. Consider \
+        using it in conjunction with [`EnumDiscriminants`]",
+    )
+}
+
 pub fn strum_discriminants_passthrough_error(span: &impl Spanned) -> syn::Error {
     syn::Error::new(
         span.span(),
diff --git a/crates/strum_macros/src/helpers/type_props.rs b/crates/strum_macros/src/helpers/type_props.rs
index 0d49e04..7302853 100644
--- a/crates/strum_macros/src/helpers/type_props.rs
+++ b/crates/strum_macros/src/helpers/type_props.rs
@@ -1,7 +1,7 @@
 use proc_macro2::TokenStream;
 use quote::quote;
 use std::default::Default;
-use syn::{parse_quote, DeriveInput, Ident, Path, Visibility};
+use syn::{parse_quote, DeriveInput, Ident, LitStr, Path, Visibility};
 
 use super::case_style::CaseStyle;
 use super::metadata::{DeriveInputExt, EnumDiscriminantsMeta, EnumMeta};
@@ -21,6 +21,8 @@
     pub discriminant_others: Vec<TokenStream>,
     pub discriminant_vis: Option<Visibility>,
     pub use_phf: bool,
+    pub prefix: Option<LitStr>,
+    pub enum_repr: Option<TokenStream>,
 }
 
 impl HasTypeProperties for DeriveInput {
@@ -34,6 +36,7 @@
         let mut ascii_case_insensitive_kw = None;
         let mut use_phf_kw = None;
         let mut crate_module_path_kw = None;
+        let mut prefix_kw = None;
         for meta in strum_meta {
             match meta {
                 EnumMeta::SerializeAll { case_style, kw } => {
@@ -71,6 +74,14 @@
                     crate_module_path_kw = Some(kw);
                     output.crate_module_path = Some(crate_module_path);
                 }
+                EnumMeta::Prefix { prefix, kw } => {
+                    if let Some(fst_kw) = prefix_kw {
+                        return Err(occurrence_error(fst_kw, kw, "prefix"));
+                    }
+
+                    prefix_kw = Some(kw);
+                    output.prefix = Some(prefix);
+                }
             }
         }
 
@@ -103,6 +114,17 @@
             }
         }
 
+        let attrs = &self.attrs;
+        for attr in attrs {
+            if let Ok(list) = attr.meta.require_list() {
+                if let Some(ident) = list.path.get_ident() {
+                    if ident == "repr" {
+                        output.enum_repr = Some(list.tokens.clone())
+                    }
+                }
+            }
+        }
+
         Ok(output)
     }
 }
diff --git a/crates/strum_macros/src/helpers/variant_props.rs b/crates/strum_macros/src/helpers/variant_props.rs
index f637253..681c7c0 100644
--- a/crates/strum_macros/src/helpers/variant_props.rs
+++ b/crates/strum_macros/src/helpers/variant_props.rs
@@ -13,6 +13,7 @@
 pub struct StrumVariantProperties {
     pub disabled: Option<kw::disabled>,
     pub default: Option<kw::default>,
+    pub default_with: Option<LitStr>,
     pub ascii_case_insensitive: Option<bool>,
     pub message: Option<LitStr>,
     pub detailed_message: Option<LitStr>,
@@ -29,14 +30,24 @@
         LitStr::new(&ident.convert_case(case_style), ident.span())
     }
 
-    pub fn get_preferred_name(&self, case_style: Option<CaseStyle>) -> LitStr {
-        self.to_string.as_ref().cloned().unwrap_or_else(|| {
+    pub fn get_preferred_name(
+        &self,
+        case_style: Option<CaseStyle>,
+        prefix: Option<&LitStr>,
+    ) -> LitStr {
+        let mut output = self.to_string.as_ref().cloned().unwrap_or_else(|| {
             self.serialize
                 .iter()
                 .max_by_key(|s| s.value().len())
                 .cloned()
                 .unwrap_or_else(|| self.ident_as_str(case_style))
-        })
+        });
+
+        if let Some(prefix) = prefix {
+            output = LitStr::new(&(prefix.value() + &output.value()), output.span());
+        }
+
+        output
     }
 
     pub fn get_serializations(&self, case_style: Option<CaseStyle>) -> Vec<LitStr> {
@@ -62,9 +73,10 @@
 
         let mut message_kw = None;
         let mut detailed_message_kw = None;
-        let mut to_string_kw = None;
         let mut disabled_kw = None;
         let mut default_kw = None;
+        let mut default_with_kw = None;
+        let mut to_string_kw = None;
         let mut ascii_case_insensitive_kw = None;
         for meta in self.get_metadata()? {
             match meta {
@@ -114,6 +126,14 @@
                     default_kw = Some(kw);
                     output.default = Some(kw);
                 }
+                VariantMeta::DefaultWith { kw, value } => {
+                    if let Some(fst_kw) = default_with_kw {
+                        return Err(occurrence_error(fst_kw, kw, "default_with"));
+                    }
+
+                    default_with_kw = Some(kw);
+                    output.default_with = Some(value);
+                }
                 VariantMeta::AsciiCaseInsensitive { kw, value } => {
                     if let Some(fst_kw) = ascii_case_insensitive_kw {
                         return Err(occurrence_error(fst_kw, kw, "ascii_case_insensitive"));
diff --git a/crates/strum_macros/src/lib.rs b/crates/strum_macros/src/lib.rs
index 82db12a..b337fb3 100644
--- a/crates/strum_macros/src/lib.rs
+++ b/crates/strum_macros/src/lib.rs
@@ -44,7 +44,7 @@
 /// variant. There is an option to match on different case conversions through the
 /// `#[strum(serialize_all = "snake_case")]` type attribute.
 ///
-/// See the [Additional Attributes](https://docs.rs/strum/0.22/strum/additional_attributes/index.html)
+/// See the [Additional Attributes](https://docs.rs/strum/latest/strum/additional_attributes/index.html)
 /// Section for more information on using this feature.
 ///
 /// If you have a large enum, you may want to consider using the `use_phf` attribute here. It leverages
@@ -118,12 +118,15 @@
     toks.into()
 }
 
-/// Converts enum variants to `&'static str`.
+/// Converts enum variants to `&'a str`, where `'a` is the lifetime of the input enum reference.
 ///
 /// Implements `AsRef<str>` on your enum using the same rules as
 /// `Display` for determining what string is returned. The difference is that `as_ref()` returns
 /// a `&str` instead of a `String` so you don't allocate any additional memory with each call.
 ///
+/// If you require a `&'static str`, you can use
+/// [`strum::IntoStaticStr`](crate::IntoStaticStr) instead.
+///
 /// ```
 /// // You need to bring the AsRef trait into scope to use it
 /// use std::convert::AsRef;
@@ -152,6 +155,18 @@
 ///     Color::Blue(10).as_ref(),
 ///     Color::Green { range: 42 }.as_ref()
 /// );
+///
+/// // With prefix on all variants
+/// #[derive(AsRefStr, Debug)]
+/// #[strum(prefix = "/")]
+/// enum ColorWithPrefix {
+///     #[strum(serialize = "redred")]
+///     Red,
+///     Green,
+/// }
+///
+/// assert_eq!("/redred", ColorWithPrefix::Red.as_ref());
+/// assert_eq!("/Green", ColorWithPrefix::Green.as_ref());
 /// ```
 #[proc_macro_derive(AsRefStr, attributes(strum))]
 pub fn as_ref_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -163,18 +178,18 @@
     toks.into()
 }
 
-/// Implements `Strum::VariantNames` which adds an associated constant `VARIANTS` which is an array of discriminant names.
+/// Implements `Strum::VariantNames` which adds an associated constant `VARIANTS` which is a `'static` slice of discriminant names.
 ///
 /// Adds an `impl` block for the `enum` that adds a static `VARIANTS` array of `&'static str` that are the discriminant names.
 /// This will respect the `serialize_all` attribute on the `enum` (like `#[strum(serialize_all = "snake_case")]`.
 ///
 /// ```
 /// // import the macros needed
-/// use strum_macros::{EnumString, EnumVariantNames};
+/// use strum_macros::{EnumString};
 /// // You need to import the trait, to have access to VARIANTS
 /// use strum::VariantNames;
 ///
-/// #[derive(Debug, EnumString, EnumVariantNames)]
+/// #[derive(Debug, EnumString, strum_macros::VariantNames)]
 /// #[strum(serialize_all = "kebab-case")]
 /// enum Color {
 ///     Red,
@@ -184,7 +199,7 @@
 /// }
 /// assert_eq!(["red", "blue", "yellow", "rebecca-purple"], Color::VARIANTS);
 /// ```
-#[proc_macro_derive(EnumVariantNames, attributes(strum))]
+#[proc_macro_derive(VariantNames, attributes(strum))]
 pub fn variant_names(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let ast = syn::parse_macro_input!(input as DeriveInput);
 
@@ -194,7 +209,54 @@
     toks.into()
 }
 
+#[doc(hidden)]
+#[proc_macro_derive(EnumVariantNames, attributes(strum))]
+#[deprecated(
+    since = "0.26.0",
+    note = "please use `#[derive(VariantNames)]` instead"
+)]
+pub fn variant_names_deprecated(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let ast = syn::parse_macro_input!(input as DeriveInput);
+
+    let toks = macros::enum_variant_names::enum_variant_names_inner(&ast)
+        .unwrap_or_else(|err| err.to_compile_error());
+    debug_print_generated(&ast, &toks);
+    toks.into()
+}
+
+/// Adds a `'static` slice with all of the Enum's variants.
+///
+/// Implements `strum::VariantArray` which adds an associated constant `VARIANTS`.
+/// This constant contains an array with all the variants of the enumerator.
+///
+/// This trait can only be autoderived if the enumerator is composed only of unit-type variants,
+/// meaning that the variants must not have any data.
+///
+/// ```
+/// use strum::VariantArray;
+///
+/// #[derive(VariantArray, Debug, PartialEq, Eq)]
+/// enum Op {
+///     Add,
+///     Sub,
+///     Mul,
+///     Div,
+/// }
+///
+/// assert_eq!(Op::VARIANTS, &[Op::Add, Op::Sub, Op::Mul, Op::Div]);
+/// ```
+#[proc_macro_derive(VariantArray, attributes(strum))]
+pub fn static_variants_array(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let ast = syn::parse_macro_input!(input as DeriveInput);
+
+    let toks = macros::enum_variant_array::static_variants_array_inner(&ast)
+        .unwrap_or_else(|err| err.to_compile_error());
+    debug_print_generated(&ast, &toks);
+    toks.into()
+}
+
 #[proc_macro_derive(AsStaticStr, attributes(strum))]
+#[doc(hidden)]
 #[deprecated(
     since = "0.22.0",
     note = "please use `#[derive(IntoStaticStr)]` instead"
@@ -282,6 +344,7 @@
     since = "0.22.0",
     note = "please use `#[derive(Display)]` instead. See issue https://github.com/Peternator7/strum/issues/132"
 )]
+#[doc(hidden)]
 #[proc_macro_derive(ToString, attributes(strum))]
 pub fn to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let ast = syn::parse_macro_input!(input as DeriveInput);
@@ -299,9 +362,21 @@
 /// choose which serialization to used based on the following criteria:
 ///
 /// 1. If there is a `to_string` property, this value will be used. There can only be one per variant.
-/// 1. Of the various `serialize` properties, the value with the longest length is chosen. If that
+/// 2. Of the various `serialize` properties, the value with the longest length is chosen. If that
 ///    behavior isn't desired, you should use `to_string`.
-/// 1. The name of the variant will be used if there are no `serialize` or `to_string` attributes.
+/// 3. The name of the variant will be used if there are no `serialize` or `to_string` attributes.
+/// 4. If the enum has a `strum(prefix = "some_value_")`, every variant will have that prefix prepended
+///    to the serialization.
+/// 5. Enums with named fields support named field interpolation. The value will be interpolated into the output string.
+///    Note this means the variant will not "round trip" if you then deserialize the string.
+///
+///    ```rust
+///    #[derive(strum_macros::Display)]
+///    pub enum Color {
+///        #[strum(to_string = "saturation is {sat}")]
+///        Red { sat: usize },
+///    }
+///    ```
 ///
 /// ```
 /// // You need to bring the ToString trait into scope to use it
@@ -317,6 +392,10 @@
 ///     },
 ///     Blue(usize),
 ///     Yellow,
+///     #[strum(to_string = "purple with {sat} saturation")]
+///     Purple {
+///         sat: usize,
+///     },
 /// }
 ///
 /// // uses the serialize string for Display
@@ -331,6 +410,9 @@
 ///     Color::Blue(10),
 ///     Color::Green { range: 42 }
 /// );
+/// // you can also use named fields in message
+/// let purple = Color::Purple { sat: 10 };
+/// assert_eq!(String::from("purple with 10 saturation"), purple.to_string());
 /// ```
 #[proc_macro_derive(Display, attributes(strum))]
 pub fn display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -444,6 +526,60 @@
     toks.into()
 }
 
+/// Creates a new type that maps all the variants of an enum to another generic value.
+///
+/// This macro only supports enums with unit type variants.A new type called `YourEnumTable<T>`. Essentially, it's a wrapper
+/// `[T; YourEnum::Count]` where gets/sets are infallible. Some important caveats to note:
+///
+/// * The size of `YourEnumTable<T>` increases with the number of variants, not the number of values because it's always
+///   fully populated. This means it may not be a good choice for sparsely populated maps.
+///
+/// * Lookups are basically constant time since it's functionally an array index.
+///
+/// * Your variants cannot have associated data. You can use `EnumDiscriminants` to generate an Enum with the same
+///   names to work around this.
+///
+/// # Stability
+///
+/// Several people expressed interest in a data structure like this and pushed the PR through to completion, but the api
+/// seems incomplete, and I reserve the right to deprecate it in the future if it becomes clear the design is flawed.
+///
+/// # Example
+/// ```rust
+/// use strum_macros::EnumTable;
+///
+/// #[derive(EnumTable)]
+/// enum Color {
+///     Red,
+///     Yellow,
+///     Green,
+///     Blue,
+/// }
+///
+/// assert_eq!(ColorTable::default(), ColorTable::new(0, 0, 0, 0));
+/// assert_eq!(ColorTable::filled(2), ColorTable::new(2, 2, 2, 2));
+/// assert_eq!(ColorTable::from_closure(|_| 3), ColorTable::new(3, 3, 3, 3));
+/// assert_eq!(ColorTable::default().transform(|_, val| val + 2), ColorTable::new(2, 2, 2, 2));
+///
+/// let mut complex_map = ColorTable::from_closure(|color| match color {
+///     Color::Red => 0,
+///     _ => 3
+/// });
+///
+/// complex_map[Color::Green] = complex_map[Color::Red];
+/// assert_eq!(complex_map, ColorTable::new(0, 3, 0, 3));
+/// ```
+#[doc(hidden)]
+#[proc_macro_derive(EnumTable, attributes(strum))]
+pub fn enum_table(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let ast = syn::parse_macro_input!(input as DeriveInput);
+
+    let toks =
+        macros::enum_table::enum_table_inner(&ast).unwrap_or_else(|err| err.to_compile_error());
+    debug_print_generated(&ast, &toks);
+    toks.into()
+}
+
 /// Add a function to enum that allows accessing variants by its discriminant
 ///
 /// This macro adds a standalone function to obtain an enum variant by its discriminant. The macro adds
@@ -518,7 +654,6 @@
 /// assert_eq!(Some(Number::Three), number_from_repr(3));
 /// assert_eq!(None, number_from_repr(4));
 /// ```
-
 #[proc_macro_derive(FromRepr, attributes(strum))]
 pub fn from_repr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let ast = syn::parse_macro_input!(input as DeriveInput);
@@ -690,7 +825,7 @@
 /// // Bring trait into scope
 /// use std::str::FromStr;
 /// use strum::{IntoEnumIterator, EnumMessage};
-/// use strum_macros::{EnumDiscriminants, EnumIter, EnumString, EnumMessage};
+/// use strum_macros::{EnumDiscriminants, EnumIter, EnumString};
 ///
 /// #[derive(Debug)]
 /// struct NonDefault;
diff --git a/crates/strum_macros/src/macros/enum_discriminants.rs b/crates/strum_macros/src/macros/enum_discriminants.rs
index 4e54a30..f7d6372 100644
--- a/crates/strum_macros/src/macros/enum_discriminants.rs
+++ b/crates/strum_macros/src/macros/enum_discriminants.rs
@@ -40,10 +40,16 @@
     // Pass through all other attributes
     let pass_though_attributes = type_properties.discriminant_others;
 
+    let repr = type_properties.enum_repr.map(|repr| quote!(#[repr(#repr)]));
+
     // Add the variants without fields, but exclude the `strum` meta item
     let mut discriminants = Vec::new();
     for variant in variants {
         let ident = &variant.ident;
+        let discriminant = variant
+            .discriminant
+            .as_ref()
+            .map(|(_, expr)| quote!( = #expr));
 
         // Don't copy across the "strum" meta attribute. Only passthrough the whitelisted
         // attributes and proxy `#[strum_discriminants(...)]` attributes
@@ -81,7 +87,7 @@
             })
             .collect::<Result<Vec<_>, _>>()?;
 
-        discriminants.push(quote! { #(#attrs)* #ident });
+        discriminants.push(quote! { #(#attrs)* #ident #discriminant});
     }
 
     // Ideally:
@@ -153,6 +159,7 @@
     Ok(quote! {
         /// Auto-generated discriminant enum variants
         #derives
+        #repr
         #(#[ #pass_though_attributes ])*
         #discriminants_vis enum #discriminants_name {
             #(#discriminants),*
diff --git a/crates/strum_macros/src/macros/enum_is.rs b/crates/strum_macros/src/macros/enum_is.rs
index ecada45..c239628 100644
--- a/crates/strum_macros/src/macros/enum_is.rs
+++ b/crates/strum_macros/src/macros/enum_is.rs
@@ -1,4 +1,4 @@
-use crate::helpers::{non_enum_error, snakify, HasStrumVariantProperties};
+use crate::helpers::{case_style::snakify, non_enum_error, HasStrumVariantProperties};
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
 use syn::{Data, DeriveInput};
@@ -20,7 +20,10 @@
 
             let variant_name = &variant.ident;
             let fn_name = format_ident!("is_{}", snakify(&variant_name.to_string()));
-            let doc_comment = format!("Returns [true] if the enum is [{}::{}] otherwise [false]", enum_name, variant_name);
+            let doc_comment = format!(
+                "Returns [true] if the enum is [{}::{}] otherwise [false]",
+                enum_name, variant_name
+            );
             Some(quote! {
                 #[must_use]
                 #[inline]
diff --git a/crates/strum_macros/src/macros/enum_iter.rs b/crates/strum_macros/src/macros/enum_iter.rs
index 0e700aa..5e81001 100644
--- a/crates/strum_macros/src/macros/enum_iter.rs
+++ b/crates/strum_macros/src/macros/enum_iter.rs
@@ -74,7 +74,7 @@
         #[allow(
             missing_copy_implementations,
         )]
-        #vis struct #iter_name #ty_generics {
+        #vis struct #iter_name #impl_generics {
             idx: usize,
             back_idx: usize,
             marker: ::core::marker::PhantomData #phantom_data,
@@ -159,6 +159,8 @@
             }
         }
 
+        impl #impl_generics ::core::iter::FusedIterator for #iter_name #ty_generics #where_clause { }
+
         impl #impl_generics Clone for #iter_name #ty_generics #where_clause {
             fn clone(&self) -> #iter_name #ty_generics {
                 #iter_name {
diff --git a/crates/strum_macros/src/macros/enum_messages.rs b/crates/strum_macros/src/macros/enum_messages.rs
index c056108..2dad411 100644
--- a/crates/strum_macros/src/macros/enum_messages.rs
+++ b/crates/strum_macros/src/macros/enum_messages.rs
@@ -74,14 +74,17 @@
         if !documentation.is_empty() {
             let params = params.clone();
             // Strip a single leading space from each documentation line.
-            let documentation: Vec<LitStr> = documentation.iter().map(|lit_str| {
-                let line = lit_str.value();
-                if line.starts_with(' ') {
-                    LitStr::new(&line.as_str()[1..], lit_str.span())
-                } else {
-                    lit_str.clone()
-                }
-            }).collect();
+            let documentation: Vec<LitStr> = documentation
+                .iter()
+                .map(|lit_str| {
+                    let line = lit_str.value();
+                    if line.starts_with(' ') {
+                        LitStr::new(&line.as_str()[1..], lit_str.span())
+                    } else {
+                        lit_str.clone()
+                    }
+                })
+                .collect();
             if documentation.len() == 1 {
                 let text = &documentation[0];
                 documentation_arms
diff --git a/crates/strum_macros/src/macros/enum_table.rs b/crates/strum_macros/src/macros/enum_table.rs
new file mode 100644
index 0000000..f9d4e81
--- /dev/null
+++ b/crates/strum_macros/src/macros/enum_table.rs
@@ -0,0 +1,204 @@
+use proc_macro2::{Span, TokenStream};
+use quote::{format_ident, quote};
+use syn::{spanned::Spanned, Data, DeriveInput, Fields};
+
+use crate::helpers::{non_enum_error, snakify, HasStrumVariantProperties};
+
+pub fn enum_table_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
+    let name = &ast.ident;
+    let gen = &ast.generics;
+    let vis = &ast.vis;
+    let mut doc_comment = format!("A map over the variants of `{}`", name);
+
+    if gen.lifetimes().count() > 0 {
+        return Err(syn::Error::new(
+            Span::call_site(),
+            "`EnumTable` doesn't support enums with lifetimes.",
+        ));
+    }
+
+    let variants = match &ast.data {
+        Data::Enum(v) => &v.variants,
+        _ => return Err(non_enum_error()),
+    };
+
+    let table_name = format_ident!("{}Table", name);
+
+    // the identifiers of each variant, in PascalCase
+    let mut pascal_idents = Vec::new();
+    // the identifiers of each struct field, in snake_case
+    let mut snake_idents = Vec::new();
+    // match arms in the form `MyEnumTable::Variant => &self.variant,`
+    let mut get_matches = Vec::new();
+    // match arms in the form `MyEnumTable::Variant => &mut self.variant,`
+    let mut get_matches_mut = Vec::new();
+    // match arms in the form `MyEnumTable::Variant => self.variant = new_value`
+    let mut set_matches = Vec::new();
+    // struct fields of the form `variant: func(MyEnum::Variant),*
+    let mut closure_fields = Vec::new();
+    // struct fields of the form `variant: func(MyEnum::Variant, self.variant),`
+    let mut transform_fields = Vec::new();
+
+    // identifiers for disabled variants
+    let mut disabled_variants = Vec::new();
+    // match arms for disabled variants
+    let mut disabled_matches = Vec::new();
+
+    for variant in variants {
+        // skip disabled variants
+        if variant.get_variant_properties()?.disabled.is_some() {
+            let disabled_ident = &variant.ident;
+            let panic_message = format!(
+                "Can't use `{}` with `{}` - variant is disabled for Strum features",
+                disabled_ident, table_name
+            );
+            disabled_variants.push(disabled_ident);
+            disabled_matches.push(quote!(#name::#disabled_ident => panic!(#panic_message),));
+            continue;
+        }
+
+        // Error on variants with data
+        if variant.fields != Fields::Unit {
+            return Err(syn::Error::new(
+                variant.fields.span(),
+                "`EnumTable` doesn't support enums with non-unit variants",
+            ));
+        };
+
+        let pascal_case = &variant.ident;
+        let snake_case = format_ident!("_{}", snakify(&pascal_case.to_string()));
+
+        get_matches.push(quote! {#name::#pascal_case => &self.#snake_case,});
+        get_matches_mut.push(quote! {#name::#pascal_case => &mut self.#snake_case,});
+        set_matches.push(quote! {#name::#pascal_case => self.#snake_case = new_value,});
+        closure_fields.push(quote! {#snake_case: func(#name::#pascal_case),});
+        transform_fields.push(quote! {#snake_case: func(#name::#pascal_case, &self.#snake_case),});
+        pascal_idents.push(pascal_case);
+        snake_idents.push(snake_case);
+    }
+
+    // Error on empty enums
+    if pascal_idents.is_empty() {
+        return Err(syn::Error::new(
+            variants.span(),
+            "`EnumTable` requires at least one non-disabled variant",
+        ));
+    }
+
+    // if the index operation can panic, add that to the documentation
+    if !disabled_variants.is_empty() {
+        doc_comment.push_str(&format!(
+            "\n# Panics\nIndexing `{}` with any of the following variants will cause a panic:",
+            table_name
+        ));
+        for variant in disabled_variants {
+            doc_comment.push_str(&format!("\n\n- `{}::{}`", name, variant));
+        }
+    }
+
+    let doc_new = format!(
+        "Create a new {} with a value for each variant of {}",
+        table_name, name
+    );
+    let doc_closure = format!(
+        "Create a new {} by running a function on each variant of `{}`",
+        table_name, name
+    );
+    let doc_transform = format!("Create a new `{}` by running a function on each variant of `{}` and the corresponding value in the current `{0}`", table_name, name);
+    let doc_filled = format!(
+        "Create a new `{}` with the same value in each field.",
+        table_name
+    );
+    let doc_option_all = format!("Converts `{}<Option<T>>` into `Option<{0}<T>>`. Returns `Some` if all fields are `Some`, otherwise returns `None`.", table_name);
+    let doc_result_all_ok = format!("Converts `{}<Result<T, E>>` into `Result<{0}<T>, E>`. Returns `Ok` if all fields are `Ok`, otherwise returns `Err`.", table_name);
+
+    Ok(quote! {
+        #[doc = #doc_comment]
+        #[allow(
+            missing_copy_implementations,
+        )]
+        #[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
+        #vis struct #table_name<T> {
+            #(#snake_idents: T,)*
+        }
+
+        impl<T: Clone> #table_name<T> {
+            #[doc = #doc_filled]
+            #vis fn filled(value: T) -> #table_name<T> {
+                #table_name {
+                    #(#snake_idents: value.clone(),)*
+                }
+            }
+        }
+
+        impl<T> #table_name<T> {
+            #[doc = #doc_new]
+            #vis fn new(
+                #(#snake_idents: T,)*
+            ) -> #table_name<T> {
+                #table_name {
+                    #(#snake_idents,)*
+                }
+            }
+
+            #[doc = #doc_closure]
+            #vis fn from_closure<F: Fn(#name)->T>(func: F) -> #table_name<T> {
+              #table_name {
+                #(#closure_fields)*
+              }
+            }
+
+            #[doc = #doc_transform]
+            #vis fn transform<U, F: Fn(#name, &T)->U>(&self, func: F) -> #table_name<U> {
+              #table_name {
+                #(#transform_fields)*
+              }
+            }
+
+        }
+
+        impl<T> ::core::ops::Index<#name> for #table_name<T> {
+            type Output = T;
+
+            fn index(&self, idx: #name) -> &T {
+                match idx {
+                    #(#get_matches)*
+                    #(#disabled_matches)*
+                }
+            }
+        }
+
+        impl<T> ::core::ops::IndexMut<#name> for #table_name<T> {
+            fn index_mut(&mut self, idx: #name) -> &mut T {
+                match idx {
+                    #(#get_matches_mut)*
+                    #(#disabled_matches)*
+                }
+            }
+        }
+
+        impl<T> #table_name<::core::option::Option<T>> {
+            #[doc = #doc_option_all]
+            #vis fn all(self) -> ::core::option::Option<#table_name<T>> {
+                if let #table_name {
+                    #(#snake_idents: ::core::option::Option::Some(#snake_idents),)*
+                } = self {
+                    ::core::option::Option::Some(#table_name {
+                        #(#snake_idents,)*
+                    })
+                } else {
+                    ::core::option::Option::None
+                }
+            }
+        }
+
+        impl<T, E> #table_name<::core::result::Result<T, E>> {
+            #[doc = #doc_result_all_ok]
+            #vis fn all_ok(self) -> ::core::result::Result<#table_name<T>, E> {
+                ::core::result::Result::Ok(#table_name {
+                    #(#snake_idents: self.#snake_idents?,)*
+                })
+            }
+        }
+    })
+}
diff --git a/crates/strum_macros/src/macros/enum_try_as.rs b/crates/strum_macros/src/macros/enum_try_as.rs
index 088a1f1..c6d0127 100644
--- a/crates/strum_macros/src/macros/enum_try_as.rs
+++ b/crates/strum_macros/src/macros/enum_try_as.rs
@@ -1,4 +1,4 @@
-use crate::helpers::{non_enum_error, snakify, HasStrumVariantProperties};
+use crate::helpers::{case_style::snakify, non_enum_error, HasStrumVariantProperties};
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote, ToTokens};
 use syn::{Data, DeriveInput};
@@ -10,6 +10,7 @@
     };
 
     let enum_name = &ast.ident;
+    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
 
     let variants: Vec<_> = variants
         .iter()
@@ -72,9 +73,8 @@
         .collect();
 
     Ok(quote! {
-        impl #enum_name {
+        impl #impl_generics #enum_name #ty_generics #where_clause {
             #(#variants)*
         }
-    }
-    .into())
+    })
 }
diff --git a/crates/strum_macros/src/macros/enum_variant_array.rs b/crates/strum_macros/src/macros/enum_variant_array.rs
new file mode 100644
index 0000000..a6974d6
--- /dev/null
+++ b/crates/strum_macros/src/macros/enum_variant_array.rs
@@ -0,0 +1,34 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Data, DeriveInput, Fields};
+
+use crate::helpers::{non_enum_error, non_unit_variant_error, HasTypeProperties};
+
+pub fn static_variants_array_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
+    let name = &ast.ident;
+    let gen = &ast.generics;
+    let (impl_generics, ty_generics, where_clause) = gen.split_for_impl();
+
+    let variants = match &ast.data {
+        Data::Enum(v) => &v.variants,
+        _ => return Err(non_enum_error()),
+    };
+
+    let type_properties = ast.get_type_properties()?;
+    let strum_module_path = type_properties.crate_module_path();
+
+    let idents = variants
+        .iter()
+        .cloned()
+        .map(|v| match v.fields {
+            Fields::Unit => Ok(v.ident),
+            _ => Err(non_unit_variant_error()),
+        })
+        .collect::<syn::Result<Vec<_>>>()?;
+
+    Ok(quote! {
+        impl #impl_generics #strum_module_path::VariantArray for #name #ty_generics #where_clause {
+            const VARIANTS: &'static [Self] = &[ #(#name::#idents),* ];
+        }
+    })
+}
diff --git a/crates/strum_macros/src/macros/enum_variant_names.rs b/crates/strum_macros/src/macros/enum_variant_names.rs
index c54d45d..8c41cc4 100644
--- a/crates/strum_macros/src/macros/enum_variant_names.rs
+++ b/crates/strum_macros/src/macros/enum_variant_names.rs
@@ -1,6 +1,6 @@
 use proc_macro2::TokenStream;
 use quote::quote;
-use syn::{Data, DeriveInput};
+use syn::{Data, DeriveInput, LitStr};
 
 use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties};
 
@@ -22,9 +22,10 @@
         .iter()
         .map(|v| {
             let props = v.get_variant_properties()?;
-            Ok(props.get_preferred_name(type_properties.case_style))
+            Ok(props
+                .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref()))
         })
-        .collect::<syn::Result<Vec<_>>>()?;
+        .collect::<syn::Result<Vec<LitStr>>>()?;
 
     Ok(quote! {
         impl #impl_generics #strum_module_path::VariantNames for #name #ty_generics #where_clause {
diff --git a/crates/strum_macros/src/macros/from_repr.rs b/crates/strum_macros/src/macros/from_repr.rs
index 92fd7ad..78bbb28 100644
--- a/crates/strum_macros/src/macros/from_repr.rs
+++ b/crates/strum_macros/src/macros/from_repr.rs
@@ -1,62 +1,31 @@
-use heck::ToShoutySnakeCase;
 use proc_macro2::{Span, TokenStream};
-use quote::{format_ident, quote, ToTokens};
-use syn::{Data, DeriveInput, Fields, PathArguments, Type, TypeParen};
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Type};
 
-use crate::helpers::{non_enum_error, HasStrumVariantProperties};
+use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties};
 
 pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
     let name = &ast.ident;
     let gen = &ast.generics;
     let (impl_generics, ty_generics, where_clause) = gen.split_for_impl();
     let vis = &ast.vis;
-    let attrs = &ast.attrs;
 
     let mut discriminant_type: Type = syn::parse("usize".parse().unwrap()).unwrap();
-    for attr in attrs {
-        let path = attr.path();
-
-        let mut ts = if let Ok(ts) = attr
-            .meta
-            .require_list()
-            .map(|metas| metas.to_token_stream().into_iter())
-        {
-            ts
-        } else {
-            continue;
-        };
-        // Discard the path
-        let _ = ts.next();
-        let tokens: TokenStream = ts.collect();
-
-        if path.leading_colon.is_some() {
-            continue;
-        }
-        if path.segments.len() != 1 {
-            continue;
-        }
-        let segment = path.segments.first().unwrap();
-        if segment.ident != "repr" {
-            continue;
-        }
-        if segment.arguments != PathArguments::None {
-            continue;
-        }
-        let typ_paren = match syn::parse2::<Type>(tokens.clone()) {
-            Ok(Type::Paren(TypeParen { elem, .. })) => *elem,
-            _ => continue,
-        };
-        let inner_path = match &typ_paren {
-            Type::Path(t) => t,
-            _ => continue,
-        };
-        if let Some(seg) = inner_path.path.segments.last() {
-            for t in &[
-                "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "isize",
-            ] {
-                if seg.ident == t {
-                    discriminant_type = typ_paren;
-                    break;
+    if let Some(type_path) = ast
+        .get_type_properties()
+        .ok()
+        .and_then(|tp| tp.enum_repr)
+        .and_then(|repr_ts| syn::parse2::<Type>(repr_ts).ok())
+    {
+        if let Type::Path(path) = type_path.clone() {
+            if let Some(seg) = path.path.segments.last() {
+                for t in &[
+                    "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "isize",
+                ] {
+                    if seg.ident == t {
+                        discriminant_type = type_path;
+                        break;
+                    }
                 }
             }
         }
@@ -103,7 +72,7 @@
             }
         };
 
-        let const_var_str = format!("{}_DISCRIMINANT", variant.ident).to_shouty_snake_case();
+        let const_var_str = format!("{}_DISCRIMINANT", variant.ident);
         let const_var_ident = format_ident!("{}", const_var_str);
 
         let const_val_expr = match &variant.discriminant {
@@ -114,7 +83,10 @@
             },
         };
 
-        constant_defs.push(quote! {const #const_var_ident: #discriminant_type = #const_val_expr;});
+        constant_defs.push(quote! {
+            #[allow(non_upper_case_globals)]
+            const #const_var_ident: #discriminant_type = #const_val_expr;
+        });
         arms.push(quote! {v if v == #const_var_ident => ::core::option::Option::Some(#name::#ident #params)});
 
         prev_const_var_ident = Some(const_var_ident);
diff --git a/crates/strum_macros/src/macros/mod.rs b/crates/strum_macros/src/macros/mod.rs
index 8df8cd6..fafc048 100644
--- a/crates/strum_macros/src/macros/mod.rs
+++ b/crates/strum_macros/src/macros/mod.rs
@@ -4,7 +4,9 @@
 pub mod enum_iter;
 pub mod enum_messages;
 pub mod enum_properties;
+pub mod enum_table;
 pub mod enum_try_as;
+pub mod enum_variant_array;
 pub mod enum_variant_names;
 pub mod from_repr;
 
diff --git a/crates/strum_macros/src/macros/strings/as_ref_str.rs b/crates/strum_macros/src/macros/strings/as_ref_str.rs
index 617b887..8d44f81 100644
--- a/crates/strum_macros/src/macros/strings/as_ref_str.rs
+++ b/crates/strum_macros/src/macros/strings/as_ref_str.rs
@@ -25,7 +25,9 @@
         // Look at all the serialize attributes.
         // Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent
         // (i.e. always `enum.as_ref().to_string() == enum.to_string()`).
-        let output = variant_properties.get_preferred_name(type_properties.case_style);
+        let output = variant_properties
+            .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref());
+
         let params = match variant.fields {
             Fields::Unit => quote! {},
             Fields::Unnamed(..) => quote! { (..) },
diff --git a/crates/strum_macros/src/macros/strings/display.rs b/crates/strum_macros/src/macros/strings/display.rs
index fcc5936..a2f6f24 100644
--- a/crates/strum_macros/src/macros/strings/display.rs
+++ b/crates/strum_macros/src/macros/strings/display.rs
@@ -1,6 +1,6 @@
-use proc_macro2::TokenStream;
+use proc_macro2::{Ident, TokenStream};
 use quote::quote;
-use syn::{Data, DeriveInput, Fields};
+use syn::{punctuated::Punctuated, Data, DeriveInput, Fields, LitStr, Token};
 
 use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties};
 
@@ -24,18 +24,31 @@
         }
 
         // Look at all the serialize attributes.
-        let output = variant_properties.get_preferred_name(type_properties.case_style);
+        let output = variant_properties
+            .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref());
 
         let params = match variant.fields {
             Fields::Unit => quote! {},
             Fields::Unnamed(..) => quote! { (..) },
-            Fields::Named(..) => quote! { {..} },
+            Fields::Named(ref field_names) => {
+                // Transform named params '{ name: String, age: u8 }' to '{ ref name, ref age }'
+                let names: Punctuated<TokenStream, Token!(,)> = field_names
+                    .named
+                    .iter()
+                    .map(|field| {
+                        let ident = field.ident.as_ref().unwrap();
+                        quote! { ref #ident }
+                    })
+                    .collect();
+
+                quote! { {#names} }
+            }
         };
 
         if variant_properties.to_string.is_none() && variant_properties.default.is_some() {
             match &variant.fields {
                 Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
-                    arms.push(quote! { #name::#ident(ref s) => f.pad(s) });
+                    arms.push(quote! { #name::#ident(ref s) => ::core::fmt::Display::fmt(s, f) });
                 }
                 _ => {
                     return Err(syn::Error::new_spanned(
@@ -45,7 +58,36 @@
                 }
             }
         } else {
-            arms.push(quote! { #name::#ident #params => f.pad(#output) });
+            let arm = if let Fields::Named(ref field_names) = variant.fields {
+                let used_vars = capture_format_string_idents(&output)?;
+                if used_vars.is_empty() {
+                    quote! { #name::#ident #params => ::core::fmt::Display::fmt(#output, f) }
+                } else {
+                    // Create args like 'name = name, age = age' for format macro
+                    let args: Punctuated<_, Token!(,)> = field_names
+                        .named
+                        .iter()
+                        .filter_map(|field| {
+                            let ident = field.ident.as_ref().unwrap();
+                            // Only contain variables that are used in format string
+                            if !used_vars.contains(ident) {
+                                None
+                            } else {
+                                Some(quote! { #ident = #ident })
+                            }
+                        })
+                        .collect();
+
+                    quote! {
+                        #[allow(unused_variables)]
+                        #name::#ident #params => ::core::fmt::Display::fmt(&format!(#output, #args), f)
+                    }
+                }
+            } else {
+                quote! { #name::#ident #params => ::core::fmt::Display::fmt(#output, f) }
+            };
+
+            arms.push(arm);
         }
     }
 
@@ -63,3 +105,43 @@
         }
     })
 }
+
+fn capture_format_string_idents(string_literal: &LitStr) -> syn::Result<Vec<Ident>> {
+    // Remove escaped brackets
+    let format_str = string_literal.value().replace("{{", "").replace("}}", "");
+
+    let mut new_var_start_index: Option<usize> = None;
+    let mut var_used: Vec<Ident> = Vec::new();
+
+    for (i, chr) in format_str.bytes().enumerate() {
+        if chr == b'{' {
+            if new_var_start_index.is_some() {
+                return Err(syn::Error::new_spanned(
+                    string_literal,
+                    "Bracket opened without closing previous bracket",
+                ));
+            }
+            new_var_start_index = Some(i);
+            continue;
+        }
+
+        if chr == b'}' {
+            let start_index = new_var_start_index.take().ok_or(syn::Error::new_spanned(
+                string_literal,
+                "Bracket closed without previous opened bracket",
+            ))?;
+
+            let inside_brackets = &format_str[start_index + 1..i];
+            let ident_str = inside_brackets.split(":").next().unwrap();
+            let ident = syn::parse_str::<Ident>(ident_str).map_err(|_| {
+                syn::Error::new_spanned(
+                    string_literal,
+                    "Invalid identifier inside format string bracket",
+                )
+            })?;
+            var_used.push(ident);
+        }
+    }
+
+    Ok(var_used)
+}
diff --git a/crates/strum_macros/src/macros/strings/from_string.rs b/crates/strum_macros/src/macros/strings/from_string.rs
index 2d25591..de32cbb 100644
--- a/crates/strum_macros/src/macros/strings/from_string.rs
+++ b/crates/strum_macros/src/macros/strings/from_string.rs
@@ -3,7 +3,8 @@
 use syn::{Data, DeriveInput, Fields};
 
 use crate::helpers::{
-    non_enum_error, occurrence_error, HasStrumVariantProperties, HasTypeProperties,
+    non_enum_error, occurrence_error, HasInnerVariantProperties, HasStrumVariantProperties,
+    HasTypeProperties,
 };
 
 pub fn from_string_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
@@ -45,7 +46,6 @@
                     ))
                 }
             }
-
             default_kw = Some(kw);
             default = quote! {
                 ::core::result::Result::Ok(#name::#ident(s.into()))
@@ -56,16 +56,34 @@
         let params = match &variant.fields {
             Fields::Unit => quote! {},
             Fields::Unnamed(fields) => {
-                let defaults =
-                    ::core::iter::repeat(quote!(Default::default())).take(fields.unnamed.len());
-                quote! { (#(#defaults),*) }
+                if let Some(ref value) = variant_properties.default_with {
+                    let func = proc_macro2::Ident::new(&value.value(), value.span());
+                    let defaults = vec![quote! { #func() }];
+                    quote! { (#(#defaults),*) }
+                } else {
+                    let defaults =
+                        ::core::iter::repeat(quote!(Default::default())).take(fields.unnamed.len());
+                    quote! { (#(#defaults),*) }
+                }
             }
             Fields::Named(fields) => {
-                let fields = fields
-                    .named
-                    .iter()
-                    .map(|field| field.ident.as_ref().unwrap());
-                quote! { {#(#fields: Default::default()),*} }
+                let mut defaults = vec![];
+                for field in &fields.named {
+                    let meta = field.get_variant_inner_properties()?;
+                    let field = field.ident.as_ref().unwrap();
+
+                    if let Some(default_with) = meta.default_with {
+                        let func =
+                            proc_macro2::Ident::new(&default_with.value(), default_with.span());
+                        defaults.push(quote! {
+                            #field: #func()
+                        });
+                    } else {
+                        defaults.push(quote! { #field: Default::default() });
+                    }
+                }
+
+                quote! { {#(#defaults),*} }
             }
         };
 
@@ -79,7 +97,7 @@
                 phf_exact_match_arms.push(quote! { #serialization => #name::#ident #params, });
 
                 if is_ascii_case_insensitive {
-                    // Store the lowercase and UPPERCASE variants in the phf map to capture 
+                    // Store the lowercase and UPPERCASE variants in the phf map to capture
                     let ser_string = serialization.value();
 
                     let lower =
@@ -113,6 +131,7 @@
             }
         }
     };
+
     let standard_match_body = if standard_match_arms.is_empty() {
         default
     } else {
@@ -134,7 +153,6 @@
             }
         }
     };
-
     let try_from_str = try_from_str(
         name,
         &impl_generics,
diff --git a/crates/strum_macros/src/macros/strings/to_string.rs b/crates/strum_macros/src/macros/strings/to_string.rs
index 9a1e661..6d44068 100644
--- a/crates/strum_macros/src/macros/strings/to_string.rs
+++ b/crates/strum_macros/src/macros/strings/to_string.rs
@@ -39,7 +39,8 @@
         }
 
         // Look at all the serialize attributes.
-        let output = variant_properties.get_preferred_name(type_properties.case_style);
+        let output = variant_properties
+            .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref());
 
         let params = match variant.fields {
             Fields::Unit => quote! {},
diff --git a/pseudo_crate/Cargo.lock b/pseudo_crate/Cargo.lock
index 8b5def0..2455d64 100644
--- a/pseudo_crate/Cargo.lock
+++ b/pseudo_crate/Cargo.lock
@@ -4962,9 +4962,9 @@
 
 [[package]]
 name = "strum_macros"
-version = "0.25.3"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
+checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
 dependencies = [
  "heck",
  "proc-macro2 1.0.92",
diff --git a/pseudo_crate/Cargo.toml b/pseudo_crate/Cargo.toml
index 6484aad..f680faf 100644
--- a/pseudo_crate/Cargo.toml
+++ b/pseudo_crate/Cargo.toml
@@ -310,7 +310,7 @@
 static_assertions = "=1.1.0"
 strsim = "=0.11.1"
 strum = "=0.25.0"
-strum_macros = "=0.25.3"
+strum_macros = "=0.26.2"
 syn = "=2.0.90"
 syn-mid = "=0.6.0"
 sync_wrapper = "=1.0.1"