use crate::{InPipe, OutPipe, StateMachine, StepInputOf};
mod private {
use super::{InPipe, OutPipe, StateMachine, StepInputOf};
pub(super) trait RoutingLaw<'message> {}
impl<'message, Board> RoutingLaw<'message> for Board
where
Board: StateMachine + InPipe + OutPipe,
<Board as InPipe>::In<'message>:
StepInputOf<Board, Outcome = <Board as OutPipe>::Out<'message>>,
{
}
}
#[doc(hidden)]
#[allow(private_bounds)]
pub trait RoutesInPipeToOutPipe<'message>:
StateMachine + InPipe + OutPipe + private::RoutingLaw<'message>
{
#[must_use = "switchboard outputs must be routed or settled"]
#[doc(hidden)]
fn route_turn(
&mut self,
input: <Self as InPipe>::In<'message>,
) -> <Self as OutPipe>::Out<'message>;
}
impl<'message, Board> RoutesInPipeToOutPipe<'message> for Board
where
Board: StateMachine + InPipe + OutPipe,
<Board as InPipe>::In<'message>:
StepInputOf<Board, Outcome = <Board as OutPipe>::Out<'message>>,
{
#[inline(always)]
fn route_turn(
&mut self,
input: <Self as InPipe>::In<'message>,
) -> <Self as OutPipe>::Out<'message> {
self.step(input)
}
}
pub trait Switchboard:
StateMachine + InPipe + OutPipe + for<'message> RoutesInPipeToOutPipe<'message>
{
#[must_use = "switchboard outputs must be routed or settled"]
#[inline(always)]
fn route<'message>(
&mut self,
input: <Self as InPipe>::In<'message>,
) -> <Self as OutPipe>::Out<'message> {
<Self as RoutesInPipeToOutPipe<'message>>::route_turn(self, input)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct Router;
impl StateMachine for Router {}
impl InPipe for Router {
type In<'message> = &'message str;
}
impl OutPipe for Router {
type Out<'message> = usize;
}
impl Switchboard for Router {}
impl StepInputOf<Router> for &str {
type Outcome = usize;
fn step(self, _router: &mut Router) -> Self::Outcome {
self.len()
}
}
#[test]
fn switchboard_routes_its_declared_input_to_its_declared_output() {
assert_eq!(Router.route("route me"), 8);
}
}