pipecircuit 0.0.2

Correct. Robust. Fast. Portable.
Documentation
//! Delivery mechanisms for values flowing into typed input pipes.
//!
//! [`Inline`] places a state machine in the current circuit turn and thread.

pub use crate::Transport;

use crate::{InPipe, StateMachine, StepInputOf};

/// Places a state machine in the current circuit turn and thread.
pub struct Inline<Machine> {
    destination: Machine,
}

impl<Machine> Inline<Machine> {
    #[inline(always)]
    pub const fn new(destination: Machine) -> Self {
        Self { destination }
    }

    #[inline(always)]
    pub const fn destination(&self) -> &Machine {
        &self.destination
    }

    #[inline(always)]
    pub fn into_destination(self) -> Machine {
        self.destination
    }
}

impl<Machine, Destination> Transport<Destination> for Inline<Machine>
where
    Machine: StateMachine,
    Destination: InPipe,
    for<'message> Destination::In<'message>: StepInputOf<Machine>,
{
    type Outcome<'transport, 'message>
        = <Destination::In<'message> as StepInputOf<Machine>>::Outcome
    where
        Self: 'transport;

    #[inline(always)]
    fn transport<'transport, 'message>(
        &'transport mut self,
        input: Destination::In<'message>,
    ) -> Self::Outcome<'transport, 'message> {
        self.destination.step(input)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct Counter(u8);

    impl StateMachine for Counter {}

    struct Add(u8);

    struct CounterInPipe;

    impl InPipe for CounterInPipe {
        type In<'message> = Add;
    }

    impl StepInputOf<Counter> for Add {
        type Outcome = u8;

        fn step(self, counter: &mut Counter) -> Self::Outcome {
            counter.0 = counter.0.saturating_add(self.0);
            counter.0
        }
    }

    #[test]
    fn inline_transport_completes_the_precise_step() {
        let mut transport = Inline::new(Counter(3));

        assert_eq!(
            Transport::<CounterInPipe>::transport(&mut transport, Add(4)),
            7
        );
        assert_eq!(transport.into_destination().0, 7);
    }
}