pipecircuit 0.0.5

Correct. Robust. Fast. Portable.
Documentation
use core::any::type_name;

use crate::{
    Participant, Pipe, StateMachine, StepInputOf, Switchboard, Transport, TurnObservation,
    TurnObserver,
};

pub struct TurnContext<Observer> {
    observer: Observer,
}

impl<Observer> TurnContext<Observer> {
    pub const fn new(observer: Observer) -> Self {
        Self { observer }
    }

    pub const fn observer(&self) -> &Observer {
        &self.observer
    }

    pub const fn observer_mut(&mut self) -> &mut Observer {
        &mut self.observer
    }

    pub fn into_observer(self) -> Observer {
        self.observer
    }
}

impl<Observer: TurnObserver> TurnContext<Observer> {
    #[must_use = "pipe outcomes must be routed or settled"]
    #[inline(always)]
    pub fn send<'transport, 'message, Destination, InstalledTransport>(
        &mut self,
        pipe: &'transport mut Pipe<Destination, InstalledTransport>,
        input: Destination::In<'message>,
    ) -> InstalledTransport::Outcome<'transport, 'message>
    where
        Destination: Participant,
        InstalledTransport: Transport<Destination>,
    {
        self.observer.observe(TurnObservation::PipeSendBegan {
            participant: type_name::<Destination>(),
            input: type_name::<Destination::In<'message>>(),
            transport: type_name::<InstalledTransport>(),
        });
        let outcome = pipe.installed_transport_mut().transport(input, self);
        self.observer.observe(TurnObservation::PipeSendCompleted {
            participant: type_name::<Destination>(),
            transport: type_name::<InstalledTransport>(),
            outcome: type_name::<InstalledTransport::Outcome<'transport, 'message>>(),
        });
        outcome
    }

    #[must_use = "participant step outcomes must be routed or settled"]
    #[inline(always)]
    pub fn step<Machine, Input>(&mut self, machine: &mut Machine, input: Input) -> Input::Outcome
    where
        Machine: StateMachine,
        Input: StepInputOf<Machine>,
    {
        self.observer
            .observe(TurnObservation::ParticipantStepBegan {
                participant: type_name::<Machine>(),
                input: type_name::<Input>(),
            });
        let outcome = machine.step(input);
        self.observer
            .observe(TurnObservation::ParticipantStepCompleted {
                participant: type_name::<Machine>(),
                outcome: type_name::<Input::Outcome>(),
            });
        outcome
    }

    #[must_use = "switchboard route outcomes must be routed or settled"]
    #[inline(always)]
    pub fn route<'message, Board: Switchboard>(
        &mut self,
        switchboard: &mut Board,
        input: <Board as Participant>::In<'message>,
    ) -> <Board as Participant>::Out<'message> {
        self.observer
            .observe(TurnObservation::SwitchboardRouteBegan {
                switchboard: type_name::<Board>(),
                input: type_name::<<Board as Participant>::In<'message>>(),
            });
        let output = switchboard.route(input);
        self.observer
            .observe(TurnObservation::SwitchboardRouteCompleted {
                switchboard: type_name::<Board>(),
                output: type_name::<<Board as Participant>::Out<'message>>(),
            });
        output
    }
}