use core::marker::PhantomData;
use crate::Participant;
pub struct Pipe<Destination: Participant, InstalledTransport> {
transport: InstalledTransport,
destination: PhantomData<fn() -> Destination>,
}
impl<Destination: Participant, InstalledTransport> Pipe<Destination, InstalledTransport> {
pub const fn new(transport: InstalledTransport) -> Self {
Self {
transport,
destination: PhantomData,
}
}
pub const fn transport(&self) -> &InstalledTransport {
&self.transport
}
pub const fn transport_mut(&mut self) -> &mut InstalledTransport {
&mut self.transport
}
pub fn into_transport(self) -> InstalledTransport {
self.transport
}
pub(crate) const fn installed_transport_mut(&mut self) -> &mut InstalledTransport {
&mut self.transport
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Inline, NoopTurnObserver, StateMachine, StepInputOf, TurnContext};
struct Recorder(usize);
impl StateMachine for Recorder {}
struct Record<'message>(&'message str);
impl<'message> StepInputOf<Recorder> for Record<'message> {
type Outcome = &'message str;
fn step(self, recorder: &mut Recorder) -> Self::Outcome {
recorder.0 = recorder.0.saturating_add(1);
self.0
}
}
struct Count;
impl StepInputOf<Recorder> for Count {
type Outcome = usize;
fn step(self, recorder: &mut Recorder) -> Self::Outcome {
recorder.0
}
}
enum RecorderIn<'message> {
Record(Record<'message>),
Count(Count),
}
enum RecorderOut<'message> {
Recorded(&'message str),
Counted(usize),
}
impl crate::Participant for Recorder {
type In<'message> = RecorderIn<'message>;
type Out<'message> = RecorderOut<'message>;
}
impl<'message> StepInputOf<Recorder> for RecorderIn<'message> {
type Outcome = RecorderOut<'message>;
fn step(self, recorder: &mut Recorder) -> Self::Outcome {
match self {
Self::Record(input) => RecorderOut::Recorded(input.step(recorder)),
Self::Count(input) => RecorderOut::Counted(input.step(recorder)),
}
}
}
#[test]
fn a_pipe_preserves_each_precise_destination_and_transport_outcome() {
let mut pipe = Pipe::<Recorder, _>::new(Inline::new(Recorder(0)));
let mut turn = TurnContext::new(NoopTurnObserver);
assert!(matches!(
turn.send_through(&mut pipe, RecorderIn::Record(Record("borrowed"))),
RecorderOut::Recorded("borrowed")
));
assert!(matches!(
turn.send_through(&mut pipe, RecorderIn::Count(Count)),
RecorderOut::Counted(1)
));
assert_eq!(pipe.transport().destination().0, 1);
assert_eq!(pipe.transport_mut().destination().0, 1);
assert_eq!(pipe.into_transport().into_destination().0, 1);
}
}