pipecircuit 0.0.20

Correct. Robust. Fast. Portable. Pick four.
Documentation
use core::convert::Infallible;

use crate::CircuitSendOutcome;

/// Classifies a concrete transport submission without choosing a semantic route.
/// The output is the installed pipe's output family, not an addressed destination.
/// Application completion remains a separate, explicit conduction policy.
pub trait SubmissionPolicy<Submission, Output> {
    type Failure;
    fn settle(
        &mut self,
        submission: Submission,
    ) -> Result<CircuitSendOutcome<Output, Infallible>, Self::Failure>;
}

impl<Submission, Output, Policy: SubmissionPolicy<Submission, Output> + ?Sized>
    SubmissionPolicy<Submission, Output> for &mut Policy
{
    type Failure = Policy::Failure;

    fn settle(
        &mut self,
        submission: Submission,
    ) -> Result<CircuitSendOutcome<Output, Infallible>, Self::Failure> {
        (**self).settle(submission)
    }
}

/// The inline step has already produced exactly one semantic output.
pub struct InlineSubmission;
impl<Output> SubmissionPolicy<Output, Output> for InlineSubmission {
    type Failure = Infallible;
    fn settle(
        &mut self,
        output: Output,
    ) -> Result<CircuitSendOutcome<Output, Infallible>, Infallible> {
        Ok(CircuitSendOutcome::Immediate { from: output })
    }
}

/// Explicitly settle an active transport's submission. Success ends this
/// synchronous circulation; it does not claim peer consumption or completion.
pub struct SubmitWith<Policy>(pub Policy);
impl<Submission, Output, Policy, Failure> SubmissionPolicy<Submission, Output>
    for SubmitWith<Policy>
where
    Policy: FnMut(Submission) -> Result<(), Failure>,
{
    type Failure = Failure;
    fn settle(
        &mut self,
        submission: Submission,
    ) -> Result<CircuitSendOutcome<Output, Infallible>, Failure> {
        (self.0)(submission)?;
        Ok(CircuitSendOutcome::Submitted)
    }
}