#type-state #macro #proc-macro #marker #linked #enums #multiple

typemarker

通过过程宏轻松创建多个链接标记类型

2 个版本

0.1.1 2023 年 8 月 22 日
0.1.0 2023 年 8 月 22 日

#533 in 过程宏

MIT/Apache

11KB
131

Typemarker

通过过程宏轻松创建多个链接标记类型,适用于类型状态模式。

示例

默认情况下,typemarker 会为名为 "Trait" 和 "Dynamic" 的标记枚举添加相应的特性和动态值。

use core::marker::PhantomData;

use typemarker::typemarker;

#[typemarker]
enum LightColor {
    Red,
    Yellow,
    Green,
}

struct TrafficLight<Color: LightColor::Trait>(PhantomData<Color>);
impl TrafficLight<LightColor::Red> {
    fn turn_green(self) -> TrafficLight<LightColor::Green> {
        TrafficLight::<LightColor::Green>(PhantomData)
    }
}

impl<Color: LightColor::Trait> TrafficLight<Color> {
    fn can_go(&self) -> bool {
        Color::dynamic() == LightColor::Dynamic::Green
    }
}

let light = TrafficLight::<LightColor::Red>(PhantomData);
assert!(!light.can_go());

let light = light.turn_green();
assert!(light.can_go());

可以使用 no_valueno_trait 分别禁用特性和动态值。

use core::marker::PhantomData;

use typemarker::typemarker;

#[typemarker(no_value, no_trait)]
enum LightColor {
    Red,
    Yellow,
    Green,
}

// Compile error, LightColor::Trait does not exist on no_trait.
// struct TrafficLight<Color: LightColor::Trait>(PhantomData<Color>);

struct TrafficLight<Color>(PhantomData<Color>);
impl TrafficLight<LightColor::Red> {
    fn turn_green(self) -> TrafficLight<LightColor::Green> {
        TrafficLight::<LightColor::Green>(PhantomData)
    }
}

// Compile error, dynamic doesn't exist on no_value.
// impl<Color: LightColor::Trait> TrafficLight<Color> {
//     fn can_go(&self) -> bool {
//         Color::dynamic() == LightColor::Dynamic::Green
//     }
// }

let light = TrafficLight::<LightColor::Red>(PhantomData);
light.turn_green();

它们也可以使用 trait_name = ...value_name = ... 进行重命名。

use core::marker::PhantomData;

use typemarker::typemarker;

#[typemarker(trait_name = TraitName, value_name = ValueName)]
enum LightColor {
    Red,
    Yellow,
    Green,
}

struct TrafficLight<Color: LightColor::TraitName>(PhantomData<Color>);
impl TrafficLight<LightColor::Red> {
    fn turn_green(self) -> TrafficLight<LightColor::Green> {
        TrafficLight::<LightColor::Green>(PhantomData)
    }
}

impl<Color: LightColor::TraitName> TrafficLight<Color> {
    fn can_go(&self) -> bool {
        Color::dynamic() == LightColor::ValueName::Green
    }
}

let light = TrafficLight::<LightColor::Red>(PhantomData);
assert!(!light.can_go());

let light = light.turn_green();
assert!(light.can_go());

依赖

~0.6–1MB
~25K SLoC