use crate::{Inline, Pipe, ReceiveFromOutcome, StepsPipeInputToOutput, TransportTo};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum IntakeAdmission {
Ready,
Paused,
}
pub trait IntakeGate<Context, Failure = core::convert::Infallible> {
fn admit(&mut self, context: Context) -> Result<IntakeAdmission, Failure>;
}
pub trait AdmissionHandler<Context>: Sized {
type Policy;
type Peers;
fn admission_context(&self) -> (&Self::Policy, &Self::Peers);
type WithAdmission<Gate>: IntakeGate<Context>
where
Gate: FnMut(&Self::Policy, &Self::Peers, Context) -> IntakeAdmission;
fn with_fallible_admission<Gate, Failure>(self, gate: Gate) -> FallibleAdmission<Self, Gate>
where
Gate: FnMut(&Self::Policy, &Self::Peers, Context) -> Result<IntakeAdmission, Failure>,
{
FallibleAdmission::new(self, gate)
}
fn with_admission<Gate>(self, gate: Gate) -> Self::WithAdmission<Gate>
where
Gate: FnMut(&Self::Policy, &Self::Peers, Context) -> IntakeAdmission;
}
pub trait PipeSender<Protocol: Pipe> {
type Outcome<'message>;
#[must_use = "submission must be admitted, retained, or explicitly refused"]
fn send<'message>(&mut self, input: Protocol::In<'message>) -> Self::Outcome<'message>;
}
pub trait ScopedSender<'message, Protocol: Pipe>: PipeSender<Protocol> {
#[must_use = "submission must be admitted, retained, or explicitly refused"]
fn submit(&mut self, input: Protocol::In<'message>) -> Self::Outcome<'message>;
}
pub trait PipeOutputHandler<Protocol: Pipe, Driver: PipeDriver<Protocol> + ?Sized> {
type Failure;
fn output<'message, Sender>(
&mut self,
output: Protocol::Out<'message>,
outgoing: &mut Sender,
) -> Result<(), Self::Failure>
where
Sender: ScopedSender<'message, Protocol>
+ for<'input> PipeSender<Protocol, Outcome<'input> = Driver::Submission<'input>>;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DriveFailure<Physical, Conduct> {
Physical(Physical),
Conduct(Conduct),
PhysicalAndConduct {
physical: Physical,
conduct: Conduct,
},
}
impl<Physical, Conduct> DriveFailure<Physical, Conduct> {
pub fn map_physical<Mapped>(
self,
map: impl FnOnce(Physical) -> Mapped,
) -> DriveFailure<Mapped, Conduct> {
match self {
Self::Physical(physical) => DriveFailure::Physical(map(physical)),
Self::Conduct(conduct) => DriveFailure::Conduct(conduct),
Self::PhysicalAndConduct { physical, conduct } => DriveFailure::PhysicalAndConduct {
physical: map(physical),
conduct,
},
}
}
}
pub trait PipeDriver<Protocol: Pipe> {
type Activation;
type Failure;
type Submission<'message>;
type Outgoing<'transport>: for<'message> ScopedSender<
'message,
Protocol,
Outcome<'message> = Self::Submission<'message>,
>
where
Self: 'transport;
fn outgoing(&mut self) -> Self::Outgoing<'_>;
fn drive<Handler>(
&mut self,
activation: Self::Activation,
handler: &mut Handler,
) -> ReceiveFromOutcome<(), Self::Activation, DriveFailure<Self::Failure, Handler::Failure>>
where
Handler: PipeOutputHandler<Protocol, Self>;
}
pub trait AdmittedPipeDriver<Protocol: Pipe>: PipeDriver<Protocol> {
type IntakeContext;
fn drive_admitted<Handler>(
&mut self,
activation: Self::Activation,
handler: &mut Handler,
) -> ReceiveFromOutcome<(), Self::Activation, DriveFailure<Self::Failure, Handler::Failure>>
where
Handler:
PipeOutputHandler<Protocol, Self> + IntakeGate<Self::IntakeContext, Handler::Failure>;
}
pub enum NoActivation {}
impl<Protocol, Implementation> PipeSender<Protocol> for &mut Inline<Implementation, Protocol>
where
Protocol: Pipe,
Implementation: for<'input> StepsPipeInputToOutput<'input, Protocol>,
{
type Outcome<'message> = Protocol::Out<'message>;
fn send<'message>(&mut self, input: Protocol::In<'message>) -> Self::Outcome<'message> {
TransportTo::send(*self, input)
}
}
impl<'message, Protocol, Implementation> ScopedSender<'message, Protocol>
for &mut Inline<Implementation, Protocol>
where
Protocol: Pipe,
Implementation: for<'input> StepsPipeInputToOutput<'input, Protocol>,
{
fn submit(&mut self, input: Protocol::In<'message>) -> Self::Outcome<'message> {
PipeSender::send(self, input)
}
}
impl<Protocol, Implementation> PipeDriver<Protocol> for Inline<Implementation, Protocol>
where
Protocol: Pipe,
Implementation: for<'message> StepsPipeInputToOutput<'message, Protocol>,
{
type Activation = NoActivation;
type Failure = core::convert::Infallible;
type Submission<'message> = Protocol::Out<'message>;
type Outgoing<'transport>
= &'transport mut Self
where
Self: 'transport;
fn outgoing(&mut self) -> Self::Outgoing<'_> {
self
}
fn drive<Handler>(
&mut self,
activation: NoActivation,
_handler: &mut Handler,
) -> ReceiveFromOutcome<(), NoActivation, DriveFailure<Self::Failure, Handler::Failure>>
where
Handler: PipeOutputHandler<Protocol, Self>,
{
match activation {}
}
}
mod admission;
pub use admission::{AdmissionFailure, FallibleAdmission};