diff --git a/CHANGELOG.md b/CHANGELOG.md index 43acd4a..a15fa3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,8 @@ Please make sure to add your changes to the appropriate categories: ### Added -- n/a +- Added enum-level `#[enumcapsulate(discriminant(…))]` helper attribute for `VariantDiscriminant` derive macro, allowing for customizing `repr = …` and `name = …` for the generated enum. +- Added variant-level `#[enumcapsulate(discriminant(…))]` helper attribute for `VariantDiscriminant` derive macro, allowing for customizing `value = …` and `name = …` for the generated variant. ### Changed diff --git a/macros/README.md b/macros/README.md index 46f09e6..6424cd8 100644 --- a/macros/README.md +++ b/macros/README.md @@ -79,10 +79,6 @@ enum Enum { /* ... */ } > } > ``` -### `#[derive(AsVariant)]` - -The `AsVariant` derive macro requires the variant's field type to implement `Clone`. - ## Macro helper attributes Most of the derive macros support helper attributes: @@ -91,7 +87,7 @@ Most of the derive macros support helper attributes: #### `#[enumcapsulate(exclude(…))]` -Exclude this variant from trait derivation. +Selectively opt out of `enumcapsulate` trait derivations. - `#[enumcapsulate(exclude(…))]` @@ -109,6 +105,40 @@ then you can do so by use of an `#[enumcapsulate(exclude(…))]` attribute: enum Enum { /* ... */ } ``` +##### `#[enumcapsulate(discriminant(repr = …))]` + +Specify a memory representation for the generated discriminant type. + +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom memory representation for the discriminant +type generated by the `VariantDiscriminant` derive macro, then you can +do so by use of an `#[enumcapsulate(discriminant(repr = ))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +#[enumcapsulate(discriminant(repr = u8))] +enum MyEnum { /* ... */ } +``` + +##### `#[enumcapsulate(discriminant(name = …))]` + +Specify a custom name for the generated discriminant type. + +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom name for the discriminant type +generated by the `VariantDiscriminant` derive macro, then you can do +so by use of an `#[enumcapsulate(discriminant(name = ))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +#[enumcapsulate(discriminant(name = MyDiscriminant))] +enum MyEnum { /* ... */ } +``` + ### Variant attributes > [!NOTE] @@ -127,6 +157,24 @@ Exclude this variant from trait derivation. Exclude variant from specific `enumcapsulate` derive macros. +> [!IMPORTANT] +> This attribute is recognized by the following variant-based derive macros: +> +> - `AsVariant` +> - `AsVariantMut` +> - `AsVariantRef` +> - `FromVariant` +> - `IntoVariant` +> - `From` +> - `TryInto` +> +> … as well as the umbrella derive macro: +> +> - `Encapsulate` + +If you wish to opt out of a select few of `Encapsulate`'s trait derives, +then you can do so by use of an `#[enumcapsulate(exclude(…))]` attribute: + ```rust #[derive(Encapsulate)] enum Enum { @@ -143,20 +191,6 @@ enum Enum { } ``` -This attribute is recognized by the following variant-based derive macros: - -- `AsVariant` -- `AsVariantMut` -- `AsVariantRef` -- `FromVariant` -- `IntoVariant` -- `From` -- `TryInto` - -… as well as the umbrella derive macro: - -- `Encapsulate` - #### `#[enumcapsulate(field(… = …)]` Select a specific variant field as target for trait derivation. @@ -169,6 +203,21 @@ Select a specific variant field as target for trait derivation. Select field with name `` to be used as target. +> [!IMPORTANT] +> This attribute is recognized by the following variant-based derive macros: +> +> - `AsVariant` +> - `AsVariantMut` +> - `AsVariantRef` +> - `FromVariant` +> - `IntoVariant` +> - `From` +> - `TryInto` +> +> … as well as the umbrella derive macro: +> +> - `Encapsulate` + ```rust #[derive(Encapsulate)] enum Enum { @@ -188,19 +237,89 @@ enum Enum { > > Alternatively the variant can be excluded via `#[enumcapsulate(exclude)]`. -This attribute is recognized by the following variant-based derive macros: +##### `#[enumcapsulate(discriminant(value = …))]` + +Specify a memory representation for the generated discriminant type. + +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom memory representation for the discriminant +type generated by the `VariantDiscriminant` derive macro, then you can +do so by use of an `#[enumcapsulate(discriminant(value = ))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +enum Enum { + #[enumcapsulate(discriminant(value = 42))] + VariantA(i32), + + VariantB { b: u32 }, +} +``` + +##### `#[enumcapsulate(discriminant(name = …))]` + +Specify a custom name for the generated discriminant type. + +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom name for the discriminant type +generated by the `VariantDiscriminant` derive macro, then you can do +so by use of an `#[enumcapsulate(discriminant(name = …))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +enum Enum { + #[enumcapsulate(discriminant(name = CustomDiscriminant))] + VariantA(i32), + + VariantB { b: u32 }, +} +``` -- `AsVariant` -- `AsVariantMut` -- `AsVariantRef` -- `FromVariant` -- `IntoVariant` -- `From` -- `TryInto` +##### `#[enumcapsulate(discriminant(value = …))]` -… as well as the umbrella derive macro: +Specify a memory representation for the generated discriminant type. -- `Encapsulate` +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom memory representation for the discriminant +type generated by the `VariantDiscriminant` derive macro, then you can +do so by use of an `#[enumcapsulate(discriminant(value = ))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +enum Enum { + #[enumcapsulate(discriminant(value = 42))] + VariantA(i32), + + VariantB { b: u32 }, +} +``` + +##### `#[enumcapsulate(discriminant(name = …))]` + +Specify a custom name for the generated discriminant type. + +> [!IMPORTANT] +> This attribute is only recognized by the `VariantDiscriminant` derive macro. + +If you wish to specify a custom name for the discriminant type +generated by the `VariantDiscriminant` derive macro, then you can do +so by use of an `#[enumcapsulate(discriminant(name = …))]` attribute: + +```rust +#[derive(VariantDiscriminant)] +enum Enum { + #[enumcapsulate(discriminant(name = CustomDiscriminant))] + VariantA(i32), + + VariantB { b: u32 }, +} +``` ## Generics diff --git a/macros/src/config/for_enum.rs b/macros/src/config/for_enum.rs index 1079794..044d738 100644 --- a/macros/src/config/for_enum.rs +++ b/macros/src/config/for_enum.rs @@ -1,9 +1,12 @@ +mod discriminant; mod encapsulate; mod standard; +mod variant_discriminant; pub(crate) use self::encapsulate::EncapsulateDeriveEnumConfig; +pub(crate) use self::variant_discriminant::VariantDiscriminantDeriveEnumConfig; -use self::standard::EnumConfig; +use self::{discriminant::DiscriminantConfig, standard::EnumConfig}; pub(crate) type FromDeriveEnumConfig = EnumConfig; pub(crate) type TryIntoDeriveEnumConfig = EnumConfig; diff --git a/macros/src/config/for_enum/discriminant.rs b/macros/src/config/for_enum/discriminant.rs new file mode 100644 index 0000000..fa3169b --- /dev/null +++ b/macros/src/config/for_enum/discriminant.rs @@ -0,0 +1,45 @@ +use syn::meta::ParseNestedMeta; + +use crate::attr::{NAME, REPR}; + +#[derive(Clone, Default)] +pub(crate) struct DiscriminantConfig { + repr: Option, + ident: Option, +} + +impl DiscriminantConfig { + pub(crate) fn parse( + &mut self, + meta: &ParseNestedMeta, + _item_enum: &syn::ItemEnum, + ) -> Result<(), syn::Error> { + meta.parse_nested_meta(|meta| { + if meta.path.is_ident(REPR) { + if self.repr.is_some() { + return Err(meta.error("repr already specified")); + } + + self.repr = Some(meta.value()?.parse()?); + } else if meta.path.is_ident(NAME) { + if self.ident.is_some() { + return Err(meta.error("name already specified")); + } + + self.ident = Some(meta.value()?.parse()?); + } else { + return Err(meta.error("unsupported discriminant attribute")); + } + + Ok(()) + }) + } + + pub(crate) fn repr(&self) -> Option<&syn::Type> { + self.repr.as_ref() + } + + pub(crate) fn ident(&self) -> Option<&syn::Ident> { + self.ident.as_ref() + } +} diff --git a/macros/src/config/for_enum/variant_discriminant.rs b/macros/src/config/for_enum/variant_discriminant.rs new file mode 100644 index 0000000..2c87a3a --- /dev/null +++ b/macros/src/config/for_enum/variant_discriminant.rs @@ -0,0 +1,40 @@ +use crate::{attr::DISCRIMINANT, parse_enumcapsulate_attrs}; + +use super::DiscriminantConfig; + +#[derive(Clone, Default)] +pub(crate) struct VariantDiscriminantDeriveEnumConfig { + discriminant: Option, +} + +impl VariantDiscriminantDeriveEnumConfig { + pub(crate) fn from_enum(item_enum: &syn::ItemEnum) -> Result { + let mut this = Self::default(); + + parse_enumcapsulate_attrs(&item_enum.attrs, |meta| { + if meta.path.is_ident(DISCRIMINANT) { + let mut discriminant = this.discriminant.take().unwrap_or_default(); + + discriminant.parse(&meta, item_enum)?; + + this.discriminant = Some(discriminant); + } + + Ok(()) + })?; + + Ok(this) + } + + pub fn repr(&self) -> Option<&syn::Type> { + self.discriminant + .as_ref() + .and_then(|discriminant| discriminant.repr()) + } + + pub fn ident(&self) -> Option<&syn::Ident> { + self.discriminant + .as_ref() + .and_then(|discriminant| discriminant.ident()) + } +} diff --git a/macros/src/config/for_variant.rs b/macros/src/config/for_variant.rs index 3353838..c069d0c 100644 --- a/macros/src/config/for_variant.rs +++ b/macros/src/config/for_variant.rs @@ -1,6 +1,10 @@ +mod discriminant; mod standard; +mod variant_discriminant; -use self::standard::VariantConfig; +pub(crate) use self::variant_discriminant::VariantDiscriminantDeriveVariantConfig; + +use self::{discriminant::DiscriminantConfig, standard::VariantConfig}; pub(crate) type FromDeriveVariantConfig = VariantConfig; pub(crate) type TryIntoDeriveVariantConfig = VariantConfig; diff --git a/macros/src/config/for_variant/discriminant.rs b/macros/src/config/for_variant/discriminant.rs new file mode 100644 index 0000000..941f9ee --- /dev/null +++ b/macros/src/config/for_variant/discriminant.rs @@ -0,0 +1,45 @@ +use syn::meta::ParseNestedMeta; + +use crate::attr::{NAME, VALUE}; + +#[derive(Clone, Default)] +pub(crate) struct DiscriminantConfig { + expr: Option, + ident: Option, +} + +impl DiscriminantConfig { + pub(crate) fn parse( + &mut self, + meta: &ParseNestedMeta, + _variant: &syn::Variant, + ) -> Result<(), syn::Error> { + meta.parse_nested_meta(|meta| { + if meta.path.is_ident(VALUE) { + if self.expr.is_some() { + return Err(meta.error("value already specified")); + } + + self.expr = Some(meta.value()?.parse()?); + } else if meta.path.is_ident(NAME) { + if self.ident.is_some() { + return Err(meta.error("name already specified")); + } + + self.ident = Some(meta.value()?.parse()?); + } else { + return Err(meta.error("unsupported discriminant attribute")); + } + + Ok(()) + }) + } + + pub(crate) fn expr(&self) -> Option<&syn::Expr> { + self.expr.as_ref() + } + + pub(crate) fn ident(&self) -> Option<&syn::Ident> { + self.ident.as_ref() + } +} diff --git a/macros/src/config/for_variant/variant_discriminant.rs b/macros/src/config/for_variant/variant_discriminant.rs new file mode 100644 index 0000000..f08c439 --- /dev/null +++ b/macros/src/config/for_variant/variant_discriminant.rs @@ -0,0 +1,40 @@ +use crate::{attr::DISCRIMINANT, parse_enumcapsulate_attrs}; + +use super::DiscriminantConfig; + +#[derive(Clone, Default)] +pub(crate) struct VariantDiscriminantDeriveVariantConfig { + discriminant: Option, +} + +impl VariantDiscriminantDeriveVariantConfig { + pub(crate) fn from_variant(variant: &syn::Variant) -> Result { + let mut this = Self::default(); + + parse_enumcapsulate_attrs(&variant.attrs, |meta| { + if meta.path.is_ident(DISCRIMINANT) { + let mut discriminant = this.discriminant.take().unwrap_or_default(); + + discriminant.parse(&meta, variant)?; + + this.discriminant = Some(discriminant); + } + + Ok(()) + })?; + + Ok(this) + } + + pub fn expr(&self) -> Option<&syn::Expr> { + self.discriminant + .as_ref() + .and_then(|discriminant| discriminant.expr()) + } + + pub fn ident(&self) -> Option<&syn::Ident> { + self.discriminant + .as_ref() + .and_then(|discriminant| discriminant.ident()) + } +} diff --git a/macros/src/enum_deriver.rs b/macros/src/enum_deriver.rs index 7eb269c..dad0e01 100644 --- a/macros/src/enum_deriver.rs +++ b/macros/src/enum_deriver.rs @@ -552,60 +552,83 @@ impl EnumDeriver { pub fn derive_variant_discriminant(&self) -> Result { let enum_ident = &self.item.ident; - let outer = enum_ident; - let outer_ty: Type = parse_quote_spanned! { outer.span() => #outer }; + let enum_config = VariantDiscriminantDeriveEnumConfig::from_enum(&self.item)?; + + let mut discriminant_enum_ident = quote::format_ident!("{enum_ident}Discriminant"); + let mut repr_attr: Option = None; + + if let Some(ident) = enum_config.ident() { + discriminant_enum_ident = ident.clone(); + } + + if let Some(ty) = enum_config.repr() { + repr_attr = Some(quote! { + #[repr(#ty)] + }); + } let (impl_generics, type_generics, where_clause) = self.item.generics.split_for_impl(); let variants = self.variants(); - let discriminant_ident = quote::format_ident!("{outer}Discriminant"); - let mut discriminant_variants: Vec = vec![]; + let mut match_arms: Vec = vec![]; for variant in &variants { - let variant_ident = &variant.ident; + let variant_config = VariantDiscriminantDeriveVariantConfig::from_variant(variant)?; - discriminant_variants.push(quote! { - #variant_ident, - }); - } + let variant_ident: &syn::Ident = &variant.ident; - let discriminant_enum = quote! { - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub enum #discriminant_ident { - #(#discriminant_variants)* + let mut discriminant_variant_ident: syn::Ident = variant_ident.clone(); + let mut discriminant_variant_expr: Option<&syn::Expr> = + variant.discriminant.as_ref().map(|(_, expr)| expr); + + if let Some(ident) = variant_config.ident() { + discriminant_variant_ident = ident.clone(); } - }; - let mut match_arms: Vec = vec![]; + if let Some(expr) = variant_config.expr() { + discriminant_variant_expr = Some(expr); + } - for variant in variants { - let variant_ident = &variant.ident; - let inner = variant_ident; + let variant_discriminant = discriminant_variant_expr.map(|expr| { + quote! { = #expr } + }); + + discriminant_variants.push(quote! { + #discriminant_variant_ident #variant_discriminant, + }); let pattern = match &variant.fields { Fields::Named(_) => quote! { - #outer_ty::#inner { .. } + #enum_ident::#variant_ident { .. } }, Fields::Unnamed(_) => quote! { - #outer_ty::#inner(..) + #enum_ident::#variant_ident(..) }, Fields::Unit => quote! { - #outer_ty::#inner + #enum_ident::#variant_ident }, }; match_arms.push(quote! { - #pattern => #discriminant_ident::#inner, + #pattern => #discriminant_enum_ident::#discriminant_variant_ident, }); } + let discriminant_enum = quote! { + #repr_attr + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub enum #discriminant_enum_ident { + #(#discriminant_variants)* + } + }; + Ok(quote! { #discriminant_enum - impl #impl_generics ::enumcapsulate::VariantDiscriminant for #outer_ty #type_generics #where_clause { - type Discriminant = #discriminant_ident; + impl #impl_generics ::enumcapsulate::VariantDiscriminant for #enum_ident #type_generics #where_clause { + type Discriminant = #discriminant_enum_ident; fn variant_discriminant(&self) -> Self::Discriminant { match self { diff --git a/macros/src/lib.rs b/macros/src/lib.rs index f49a309..c8bb028 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -348,7 +348,7 @@ pub fn derive_variant_downcast(input: TokenStream) -> TokenStream { /// } /// ``` /// -#[proc_macro_derive(VariantDiscriminant)] +#[proc_macro_derive(VariantDiscriminant, attributes(enumcapsulate))] pub fn derive_variant_discriminant(input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as syn::ItemEnum); diff --git a/macros/src/utils.rs b/macros/src/utils.rs index e3fa90c..647c907 100644 --- a/macros/src/utils.rs +++ b/macros/src/utils.rs @@ -2,9 +2,15 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; pub(crate) mod attr { + #![allow(dead_code)] + + pub(crate) const DISCRIMINANT: &str = "discriminant"; pub(crate) const EXCLUDE: &str = "exclude"; pub(crate) const FIELD: &str = "field"; + pub(crate) const NAME: &str = "name"; pub(crate) const NAMESPACE: &str = "enumcapsulate"; + pub(crate) const REPR: &str = "repr"; + pub(crate) const VALUE: &str = "value"; } pub(crate) mod macro_name { diff --git a/tests/derive-tests/variant_discriminant/pass/enum/name.out.rs b/tests/derive-tests/variant_discriminant/pass/enum/name.out.rs new file mode 100644 index 0000000..9418f96 --- /dev/null +++ b/tests/derive-tests/variant_discriminant/pass/enum/name.out.rs @@ -0,0 +1,78 @@ +use enumcapsulate::VariantDiscriminant; +#[enumcapsulate(discriminant(name = RenamedDiscriminant))] +pub enum Enum { + VariantA, + VariantB, + VariantC, + #[enumcapsulate(discriminant(name = RenamedVariant))] + VariantD, +} +pub enum RenamedDiscriminant { + VariantA, + VariantB, + VariantC, + RenamedVariant, +} +#[automatically_derived] +impl ::core::marker::Copy for RenamedDiscriminant {} +#[automatically_derived] +impl ::core::clone::Clone for RenamedDiscriminant { + #[inline] + fn clone(&self) -> RenamedDiscriminant { + *self + } +} +#[automatically_derived] +impl ::core::cmp::Eq for RenamedDiscriminant { + #[inline] + #[doc(hidden)] + #[coverage(off)] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for RenamedDiscriminant {} +#[automatically_derived] +impl ::core::cmp::PartialEq for RenamedDiscriminant { + #[inline] + fn eq(&self, other: &RenamedDiscriminant) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag + } +} +#[automatically_derived] +impl ::core::hash::Hash for RenamedDiscriminant { + #[inline] + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state) + } +} +#[automatically_derived] +impl ::core::fmt::Debug for RenamedDiscriminant { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str( + f, + match self { + RenamedDiscriminant::VariantA => "VariantA", + RenamedDiscriminant::VariantB => "VariantB", + RenamedDiscriminant::VariantC => "VariantC", + RenamedDiscriminant::RenamedVariant => "RenamedVariant", + }, + ) + } +} +impl ::enumcapsulate::VariantDiscriminant for Enum { + type Discriminant = RenamedDiscriminant; + fn variant_discriminant(&self) -> Self::Discriminant { + match self { + Enum::VariantA => RenamedDiscriminant::VariantA, + Enum::VariantB => RenamedDiscriminant::VariantB, + Enum::VariantC => RenamedDiscriminant::VariantC, + Enum::VariantD => RenamedDiscriminant::RenamedVariant, + _ => ::core::panicking::panic("internal error: entered unreachable code"), + } + } +} +fn main() {} diff --git a/tests/derive-tests/variant_discriminant/pass/enum/name.rs b/tests/derive-tests/variant_discriminant/pass/enum/name.rs new file mode 100644 index 0000000..ba3ec70 --- /dev/null +++ b/tests/derive-tests/variant_discriminant/pass/enum/name.rs @@ -0,0 +1,13 @@ +use enumcapsulate::VariantDiscriminant; + +#[derive(VariantDiscriminant)] +#[enumcapsulate(discriminant(name = RenamedDiscriminant))] +pub enum Enum { + VariantA, + VariantB, + VariantC, + #[enumcapsulate(discriminant(name = RenamedVariant))] + VariantD, +} + +fn main() {} diff --git a/tests/derive-tests/variant_discriminant/pass/enum/repr.out.rs b/tests/derive-tests/variant_discriminant/pass/enum/repr.out.rs new file mode 100644 index 0000000..ee34f65 --- /dev/null +++ b/tests/derive-tests/variant_discriminant/pass/enum/repr.out.rs @@ -0,0 +1,79 @@ +use enumcapsulate::VariantDiscriminant; +#[enumcapsulate(discriminant(repr = u8))] +pub enum Enum { + VariantA, + VariantB = 5, + VariantC, + #[enumcapsulate(discriminant(value = 42))] + VariantD, +} +#[repr(u8)] +pub enum EnumDiscriminant { + VariantA, + VariantB = 5, + VariantC, + VariantD = 42, +} +#[automatically_derived] +impl ::core::marker::Copy for EnumDiscriminant {} +#[automatically_derived] +impl ::core::clone::Clone for EnumDiscriminant { + #[inline] + fn clone(&self) -> EnumDiscriminant { + *self + } +} +#[automatically_derived] +impl ::core::cmp::Eq for EnumDiscriminant { + #[inline] + #[doc(hidden)] + #[coverage(off)] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for EnumDiscriminant {} +#[automatically_derived] +impl ::core::cmp::PartialEq for EnumDiscriminant { + #[inline] + fn eq(&self, other: &EnumDiscriminant) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag + } +} +#[automatically_derived] +impl ::core::hash::Hash for EnumDiscriminant { + #[inline] + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state) + } +} +#[automatically_derived] +impl ::core::fmt::Debug for EnumDiscriminant { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str( + f, + match self { + EnumDiscriminant::VariantA => "VariantA", + EnumDiscriminant::VariantB => "VariantB", + EnumDiscriminant::VariantC => "VariantC", + EnumDiscriminant::VariantD => "VariantD", + }, + ) + } +} +impl ::enumcapsulate::VariantDiscriminant for Enum { + type Discriminant = EnumDiscriminant; + fn variant_discriminant(&self) -> Self::Discriminant { + match self { + Enum::VariantA => EnumDiscriminant::VariantA, + Enum::VariantB => EnumDiscriminant::VariantB, + Enum::VariantC => EnumDiscriminant::VariantC, + Enum::VariantD => EnumDiscriminant::VariantD, + _ => ::core::panicking::panic("internal error: entered unreachable code"), + } + } +} +fn main() {} diff --git a/tests/derive-tests/variant_discriminant/pass/enum/repr.rs b/tests/derive-tests/variant_discriminant/pass/enum/repr.rs new file mode 100644 index 0000000..3b7fe2c --- /dev/null +++ b/tests/derive-tests/variant_discriminant/pass/enum/repr.rs @@ -0,0 +1,13 @@ +use enumcapsulate::VariantDiscriminant; + +#[derive(VariantDiscriminant)] +#[enumcapsulate(discriminant(repr = u8))] +pub enum Enum { + VariantA, + VariantB = 5, + VariantC, + #[enumcapsulate(discriminant(value = 42))] + VariantD, +} + +fn main() {}