Marker Types

Let's make use of Marker Types by a little help from PhantomData which use for make compiler happy.

use std::marker::PhantomData;

// Unit types to represent each state.
struct Standby;
struct Running;

// 1️⃣ Standby state.
impl PlayStation<Standby> {
    // Can be turn on.
    pub fn turn_on(self) -> PlayStation<Running> {
        PlayStation::<Running> {
            state: PhantomData::<Running>,
        }
    }
}

// 2️⃣ Running state.
impl PlayStation<Running> {
    // Can be play.
    pub fn play(&mut self) {}
}

// *️⃣ PlayStation default to Standby state.
struct PlayStation<State = Standby> {
    state: PhantomData<State>,
}

impl Default for PlayStation<Standby> {
    fn default() -> Self {
        Self {
            state: Default::default(),
        }
    }
}

// This can be access in any state.
impl<State> PlayStation<State> {
    pub fn version(&self) -> u8 {
        5
    }
}

fn main() {
    // Cool! We just got new PS5!
    let ps5 = PlayStation::default();

    // Can access only version.
    println!("ps5.version:{}", ps5.version());

    // Can play after turn on.
    ps5.turn_on().play();
}