Crates.io | amass |
lib.rs | amass |
version | 0.1.0 |
source | src |
created_at | 2024-04-11 04:24:00.446143 |
updated_at | 2024-04-11 04:24:00.446143 |
description | Automatically generate `From` impls for nested enums, even across crates |
homepage | |
repository | https://github.com/colinjneville/telety |
max_upload_size | |
id | 1204383 |
size | 15,098 |
Automatically generate From
impls for nested enums, even across crates.
All that is required is an attribute applied to each nesting enum:
pub mod letter {
pub struct A;
pub struct B;
pub struct C;
#[amass::amass_telety(crate::letter)]
pub enum Letter {
A(A),
B(B),
C(C),
}
}
pub mod number {
pub struct One;
pub struct Two;
pub struct Three;
#[amass::amass_telety(crate::number)]
pub enum Number {
One(One),
Two(Two),
Three(Three),
}
}
use letter::Letter;
use number::Number;
#[amass::amass_telety(crate)]
pub enum Alphanumeric {
Letter(Letter),
Number(Number),
}
pub struct Underscore;
#[amass::amass_telety(crate)]
pub enum IdentifierChar {
Alphanumeric(Alphanumeric),
Underscore(Underscore),
}
fn main() {
let _: &[IdentifierChar] = &[
letter::A.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Letter(Letter::A(A)))
letter::B.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Letter(Letter::B(B)))
letter::C.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Letter(Letter::C(C)))
Underscore.into(), // IdentifierChar::Underscore(Underscore)
number::One.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Number(Number::One(One)))
number::Two.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Number(Number::Two(Two)))
number::Three.into(), // IdentifierChar::Alphanumeric(Alphanumeric::Number(Number::Three(Three)))
];
}
amass is powered by telety,
which still has limitations in the language features it supports.
You can use the #[amass]
and #[telety(...)]
attributes separately,
or simply use the combined #[amass_telety(...)]
attribute.
amass has customizable behavior for applicable fields. The following options exist:
A default action can be specified on the main attribute: #[amass(default = force)]
.
If no default is provided on the attribute, deep
is the default action.
This default can be overriden on specific variants with the #[amass_action(...)]
helper attribute.
#[amass_telety(crate)]
pub enum ConflictingVariants {
Default(i32),
#[amass_action(ignore)]
Alternate(i32),
}
#[amass_telety(crate, default = ignore)]
pub enum ConflictingVariants {
#[amass_action(shallow)]
Default(i32),
Alternate(i32),
}
Note that is not currently possible to override behavior on an upstream enum.
In this example, two impls for From<DiamondTop> for DiamondBottom
are generated, causing a compile error.
# use amass::amass_telety;
pub struct DiamondTop;
#[amass_telety(crate)]
pub struct DiamondLeft {
Top(DiamondTop)
}
#[amass_telety(crate)]
pub struct DiamondRight {
Top(DiamondTop)
}
#[amass_telety(crate)]
pub struct DiamondBottom {
Left(DiamondLeft),
Right(DiamondRight),
}
# fn main() { }
To solve this, either DiamondLeft
or DiamondRight
must ignore
the Top
variant,
or DiamondBottom
must use shallow
for the Left
or Right
variant. It is not possible to only skip
the DiamondTop
-> DiamondLeft
/DiamondRight
-> DiamondBottom
impl.