#enums #nested #automatic #proc #impl #across #amass

macro amass-macro

amass的过程宏。不建议公开使用。

1 个不稳定版本

0.1.0 2024年4月11日

#81#impl


用于 amass

MIT/Apache

25KB
674

amass

自动为嵌套枚举生成 From 实现,甚至跨crate。

只需要对每个嵌套枚举应用一个属性。

示例

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 由 telety 驱动,它在其支持的语言功能上仍有 限制。 您可以单独使用 #[amass]#[telety(...)] 属性,或者简单地使用组合的 #[amass_telety(...)] 属性。

指定实现

amass 对适用的字段有可定制的行为。以下选项存在

  • 忽略 - 不会为字段类型或该类型包含的字段类型创建任何 From 实现。
  • 浅 - 将为字段类型创建一个 From 实现,但不会为该类型包含的字段类型创建实现。
  • 深 - 将为字段类型创建一个 From 实现,如果该类型已启用 telety,则为该类型包含的字段类型创建实现。
  • 强制 - 将为字段类型及其包含的字段类型创建 From 实现。如果类型未启用 telety,将生成编译错误。

可以在主属性上指定默认操作:#[amass(default = force)]。如果该属性未提供默认值,则默认操作为deep
可以通过#[amass_action(...)]辅助属性来覆盖特定变体的默认值。

#[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),
}

请注意,目前无法在上游枚举上覆盖行为。
在这个例子中,为From<DiamondTop> for DiamondBottom生成了两个impl,导致编译错误。

# 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() { }

为了解决这个问题,必须使DiamondLeftDiamondRight忽略Top变体,或者DiamondBottom必须为LeftRight变体使用shallow。无法仅跳过DiamondTop -> DiamondLeft/DiamondRight -> DiamondBottom的impl。

依赖

~0.4–1MB
~22K SLoC