#proc-macro #marker #enums #testing #typemarker #light-color #traffic-light

typemarker_core

Core module of typemarker that includes all the code for the macro and tests

2 releases

0.1.1 Aug 22, 2023
0.1.0 Aug 22, 2023

#1348 in Procedural macros

Download history 1/week @ 2024-02-17 22/week @ 2024-02-24 1/week @ 2024-03-02 1/week @ 2024-03-09 28/week @ 2024-03-30 3/week @ 2024-04-06 30/week @ 2024-04-13

61 downloads per month
Used in typemarker

MIT/Apache

6KB
124 lines

Typemarker

Procedural macro for easily creating multiple linked marker types, useful for the typestate pattern.

Examples

By default, typemarker adds both a trait and a dynamic value for the marker enum called "Trait" and "Dynamic" respectively.

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());

Both the trait and the dynamic value can be disabled using no_value and no_trait respectively.

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();

They can also be renamed using trait_name = ... and 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());

lib.rs:

Core module of typemarker that includes all the code for the macro and tests.

For documentation on how to use typemarker, see the typemarker crate.

Dependencies

~0.7–1.1MB
~26K SLoC