| Crates.io | amass |
| lib.rs | amass |
| version | 0.1.1 |
| created_at | 2024-04-11 04:24:00.446143+00 |
| updated_at | 2025-07-04 00:51:27.848769+00 |
| description | Automatically generate `From` impls for nested enums, even across crates |
| homepage | |
| repository | https://github.com/colinjneville/amass |
| max_upload_size | |
| id | 1204383 |
| size | 17,605 |
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.