| Crates.io | enumcapsulate-macros |
| lib.rs | enumcapsulate-macros |
| version | 0.6.3 |
| created_at | 2024-01-22 17:35:40.509834+00 |
| updated_at | 2025-05-22 15:40:48.122025+00 |
| description | Procedural macros for 'enumcapsulate' crate |
| homepage | https://github.com/regexident/enumcapsulate |
| repository | https://github.com/regexident/enumcapsulate |
| max_upload_size | |
| id | 1109023 |
| size | 81,566 |
enumcapsulate-macrosDerive macros for enumcapsulate crate.
The enumcapsulate-macros proc-macro crate exports the following derive macros:
| Derive macro | Functionality |
|---|---|
Encapsulate |
Derives impls for AsVariant, AsVariantMut, AsVariantRef, From, FromVariant, IntoVariant, TryInto, and VariantDowncast. |
FromVariant |
Derives impls for Self: enumcapsulate::FromVariant<T> for each non-unit variant type T. |
IntoVariant |
Derives impls for Self: enumcapsulate::FromVariant<T> for each non-unit variant type T. |
From |
Derives impls for Self: core::convert::From<T> for each non-unit variant type T. |
TryInto |
Derives impls for T: core::convert::TryFrom<Self> for each non-unit variant type T. |
AsVariant |
Derives impls for Self: enumcapsulate::AsVariant<T> for each non-unit variant type T. |
AsVariantMut |
Derives impls for Self: enumcapsulate::AsVariantMut<T> for each non-unit variant type T. |
AsVariantRef |
Derives impls for Self: enumcapsulate::AsVariantRef<T> for each non-unit variant type T. |
VariantDowncast |
Derives impl for Self: enumcapsulate::VariantDowncast. |
VariantDiscriminant |
Derives impl for Self: enumcapsulate::VariantDiscriminant. |
[!NOTE] The implementations generated by the
FromandFromVariant, as well as theTryIntoandIntoVariantderive macro pairs are semantically equivalent.
#[derive(Encapsulate)]The umbrella derive macro Encapsulate allows for conveniently deriving AsVariant, AsVariantMut, AsVariantRef, From, FromVariant, IntoVariant, TryInto, and VariantDowncast all at once.
The following two snippets are semantically equivalent:
#[derive(Encapsulate)]
enum Enum { /* ... */ }
#[derive(
From,
TryInto,
FromVariant,
IntoVariant,
AsVariant,
AsVariantMut,
AsVariantRef,
VariantDowncast,
)]
enum Enum { /* ... */ }
[!TIP] If the list of trait derives produced by
#[derive(Encapsulate)]is too broad of a stroke your your particular use case then your can selectively opt them out by use of an#[enumcapsulate(exclude(…))]attribute on the enum itself.#[derive(Encapsulate)] #[enumcapsulate(exclude(From, TryInto))] enum Enum { // Excluded from `From` and `TryInto` derives // due to existing enum-level attribute: VariantA(VariantA), // Exclude derivation of any traits // for this specific variant's type: #[enumcapsulate(exclude)] VariantB(VariantB), // Selectively exclude derivation of `From` trait // for this specific variant's type: #[enumcapsulate(exclude(From))] VariantC(VariantC), }
Most of the derive macros support helper attributes:
#[enumcapsulate(exclude(…))]Selectively opt out of enumcapsulate trait derivations.
#[enumcapsulate(exclude(…))]
Exclude variant from specific Encapsulate derive macros.
[!IMPORTANT] This attribute is only recognized by the
Encapsulateumbrella derive macro.
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:
#[derive(Encapsulate)]
#[enumcapsulate(exclude(From, TryInto))]
enum Enum { /* ... */ }
#[enumcapsulate(discriminant(name = …))]Specify a custom name for the generated discriminant type.
[!IMPORTANT] This attribute is only recognized by the
VariantDiscriminantderive 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 = <typename>))] attribute:
#[derive(VariantDiscriminant)]
#[enumcapsulate(discriminant(name = MyDiscriminant))]
enum MyEnum { /* ... */ }
#[enumcapsulate(discriminant(repr = …))]Specify a memory representation for the generated discriminant type.
[!IMPORTANT] This attribute is only recognized by the
VariantDiscriminantderive 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 = <typename>))] attribute:
#[derive(VariantDiscriminant)]
#[enumcapsulate(discriminant(repr = u8))]
enum MyEnum { /* ... */ }
[!NOTE] Variant-level attributes have a higher precedence than their equivalent enum-level attributes and thus act as a selective override if both are present.
#[enumcapsulate(exclude(…))]Exclude this variant from trait derivation.
#[enumcapsulate(exclude)]
Exclude variant from all enumcapsulate derive macros.
#[enumcapsulate(exclude(…))]
Exclude variant from specific enumcapsulate derive macros.
[!IMPORTANT] This attribute is recognized by the following variant-based derive macros:
AsVariantAsVariantMutAsVariantRefFromVariantIntoVariantFromTryInto… 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:
#[derive(Encapsulate)]
enum Enum {
// Included by default.
VariantA(VariantA),
// Excluded from all derives:
#[enumcapsulate(exclude)]
VariantB(VariantB),
// Excluded from just the `From` and `TryInto` derives:
#[enumcapsulate(exclude(From, TryInto))]
VariantC(VariantC),
}
#[enumcapsulate(field(… = …)]Select a specific variant field as target for trait derivation.
#[enumcapsulate(field = <index>)]
Select field at index <index> to be used as target.
#[enumcapsulate(field = <name>)]
Select field with name <name> to be used as target.
[!IMPORTANT] This attribute is recognized by the following variant-based derive macros:
AsVariantAsVariantMutAsVariantRefFromVariantIntoVariantFromTryInto… as well as the umbrella derive macro:
Encapsulate
#[derive(Encapsulate)]
enum Enum {
// Select field `1`, i.e. `VariantA`:
#[enumcapsulate(field(index = 1))]
VariantA(i32, VariantA),
// Select field `b`, i.e. `VariantB`:
#[enumcapsulate(field(name = b))]
VariantB { b: VariantB, c: u32 },
}
[!NOTE] When deriving traits for variants with multiple fields a field has to be explicitly specified using
#[enumcapsulate(field(… = …))].Alternatively the variant can be excluded via
#[enumcapsulate(exclude)].
#[enumcapsulate(discriminant(name = …))]Specify a custom name for the generated discriminant type.
[!IMPORTANT] This attribute is only recognized by the
VariantDiscriminantderive 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:
#[derive(VariantDiscriminant)]
enum Enum {
#[enumcapsulate(discriminant(name = CustomDiscriminant))]
VariantA(i32),
VariantB { b: u32 },
}
#[enumcapsulate(discriminant(value = …))]Specify a memory representation for the generated discriminant type.
[!IMPORTANT] This attribute is only recognized by the
VariantDiscriminantderive 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 = <expr>))] attribute:
#[derive(VariantDiscriminant)]
enum Enum {
#[enumcapsulate(discriminant(value = 42))]
VariantA(i32),
VariantB { b: u32 },
}
#[enumcapsulate(discriminant(nested = …))]Specify a nested sub-discriminant type for the generated discriminant variant.
[!IMPORTANT] This attribute is only recognized by the
VariantDiscriminantderive macro.
If you wish a discriminant variant generated by the VariantDiscriminant
derive macro to be nested, then you can do so by use
of an #[enumcapsulate(discriminant(nested))] attribute:
#[derive(VariantDiscriminant)]
enum VariantA {
VariantA1,
VariantA2,
}
#[derive(VariantDiscriminant)]
enum Enum {
#[enumcapsulate(discriminant(nested))]
VariantA(VariantA),
VariantB { b: u32 },
}
There is limited support for generic enums:
VariantDiscriminantWhen using the VariantDiscriminant derive macro with a generic enum you have to
provide an explicit type path for any nested discriminant that uses any of the parent
enum's generic parameters in its own type.
#[derive(VariantDiscriminant)]
enum VariantA<T> {
VariantA1(T),
// ...
}
#[derive(VariantDiscriminant)]
enum VariantB {
VariantB1,
// ...
}
#[derive(VariantDiscriminant)]
enum Enum<T> {
#[enumcapsulate(discriminant(nested = VariantADiscriminant))]
VariantA(VariantA<T>),
#[enumcapsulate(discriminant(nested))]
VariantB(VariantB),
// ...
}
Variants using generic const/type parameters are always excluded when deriving generic traits with enumcapsulate's derive macros.
The reason for this behavior is that implementing generic traits for variants that use any of the generic parameters of the enum tends to result in conflicting implementations in Rust, as shown by the following example program:
use enumcapsulate::FromVariant;
pub struct VariantA;
pub struct VariantB;
#[derive(FromVariant)]
// error[E0119]: conflicting implementations of trait `FromVariant<VariantB>` for type `Enum<VariantB>`
pub enum Enum<T> {
Unit,
Generic(T),
NonGeneric(VariantB),
}
fn main() {
let _: Enum<VariantA> = Enum::from_variant(VariantA);
let _: Enum<VariantA> = Enum::from_variant(VariantB);
}
The expanded version of the above makes it easier to see why: The compiler can't prove that T and VariantB are disjoint types.
pub struct VariantA;
pub struct VariantB;
pub enum Enum<T> {
Unit,
Generic(T),
NonGeneric(VariantB),
}
impl<T> FromVariant<T> for Enum<T> { // <- first implementation here
fn from_variant(variant: T) -> Self {
Self::Generic(variant)
}
}
// error[E0119]: conflicting implementations of trait `FromVariant<VariantB>` for type `Enum<VariantB>`
impl<T> FromVariant<VariantB> for Enum<T> { // <- conflicting implementation for `Enum<VariantB>`
fn from_variant(variant: VariantB) -> Self {
Self::NonGeneric(variant)
}
}
fn main() {
let _: Enum<VariantA> = Enum::from_variant(VariantA);
let _: Enum<VariantA> = Enum::from_variant(VariantB);
}
So in order to avoid such pitfalls altogether enumcapsulate's derive macros will skip impl<T> FromVariant<T> for Enum<T>, since it uses a generic type (or const) parameter of Enum<T>.
So all you have to do is provide your own non-generic implementations for specific type instances of your generic type yourself, filling any gaps left behind by the derive macro:
use enumcapsulate::FromVariant;
pub struct VariantA;
pub struct VariantB;
#[derive(FromVariant)]
pub enum Enum<T> {
Unit,
Generic(T),
NonGeneric(VariantB),
}
// Notice how the trait is implemented on
// a specific type of the `Enum<T>` kind,
// rather than on the generic kind itself:
impl From<VariantA> for Enum<VariantA> {
fn from(value: VariantA) -> Self {
Self::Generic(value)
}
}
fn main() {
let _: Enum<VariantA> = Enum::from_variant(VariantA);
let _: Enum<VariantA> = Enum::from_variant(VariantB);
}
Please refer to the documentation on docs.rs.
Please read CONTRIBUTING.md for details on our code of conduct,
and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.
This project is licensed under the MPL-2.0 – see the LICENSE.md file for details.