Macro phantom_enum::phantom_enum [] [src]

macro_rules! phantom_enum {
    (
        $(#[$enum_attr:meta])*
        pub enum $name:ident {
            $(
                $(#[$variant_attr:meta])+
                $variant:ident
             ),*$(,)*
        }
    ) => { ... };
    (
        $(#[$enum_attr:meta])*
        enum $name:ident {
            $(
                $(#[$variant_attr:meta])+
                $variant:ident
             ),*$(,)*
        }
    ) => { ... };
}

Create a phantom type enum.

A phantom type enum is an enum-like arrangement where the enum is a module and trait and the variants are (uninstantiable) types.

This is very good for the static representation of state machines in which nothing can go wrong.

#[macro_use] #[no_link]
extern crate phantom_enum;

phantom_enum! {
    /// Put things here, of course
    pub enum TableItem {
        /// A bottle with a paper label reading “DRINK ME”.
        Potion,
        /// A cake with the words “EAT ME” marked in currants.
        Cake,
    }
}

// Note how this restricts the methods to only meaningful types.
struct Person<T: TableItem::Impl> {
    name: &'static str,
    phantom: std::marker::PhantomData<T>,
}

impl<T: TableItem::Impl> Person<T> {
    fn new(name: &'static str) -> Person<T> {
        Person {
            name: name,
            phantom: std::marker::PhantomData,
        }
    }
}

impl Person<TableItem::Potion> {
    fn drink_it(self) -> Person<TableItem::Cake> {
        println!("Shrinking! Oh look, there’s a box down here!");
        Person {
            name: self.name,
            phantom: std::marker::PhantomData,
        }
    }
}

impl Person<TableItem::Cake> {
    fn eat_it(self) -> () {
        println!("Growing! OK, that’s enough of the story.");
        // Who can remember what comes next, anyway?
    }
}

fn main() {
    let person = Person::new("Alice");
    let person = person.drink_it();
    person.eat_it();
}

As you will observe with this example, if you have a Person<Potion>, you simply cannot call .eat_it(); for that, you must have a Person<Cake>. Similarly, once you have drunk that potion, you can’t drink it again.