camel-api 0.20.0

Core traits and interfaces for rust-camel
Documentation
//! Wrapper around `Box<dyn OutcomePipeline>`. Lives in camel-api (NOT
//! camel-core) so EIP segment structs in camel-processor can type their
//! fields as `camel_api::OutcomeSegment` (camel-processor depends on
//! camel-api, not camel-core). See ADR-0025.

use crate::exchange::Exchange;
use crate::outcome_pipeline::OutcomePipeline;
use crate::pipeline_outcome::PipelineOutcome;
use std::future::Future;
use std::pin::Pin;

/// Wrapper around `Box<dyn OutcomePipeline>`. Constructed via
/// `OutcomeSegment::new(...)` and run via `run(exchange)`.
#[derive(Clone)]
pub struct OutcomeSegment {
    inner: Box<dyn OutcomePipeline>,
}

impl std::fmt::Debug for OutcomeSegment {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("OutcomeSegment").finish_non_exhaustive()
    }
}

impl OutcomeSegment {
    pub fn new(inner: Box<dyn OutcomePipeline>) -> Self {
        Self { inner }
    }

    pub async fn run(&mut self, exchange: Exchange) -> PipelineOutcome {
        self.inner.run(exchange).await
    }
}

/// OutcomeSegment implements RetryableStep so it can participate in the
/// retry path alongside BoxProcessor. Lives in camel-api (where both
/// OutcomeSegment and RetryableStep are defined).
impl crate::error_handler::RetryableStep for OutcomeSegment {
    fn invoke<'a>(
        &'a mut self,
        exchange: Exchange,
    ) -> Pin<Box<dyn Future<Output = PipelineOutcome> + Send + 'a>> {
        Box::pin(async move { self.run(exchange).await })
    }
}

/// OutcomeSegment implements OutcomePipeline by delegating to its inner
/// `Box<dyn OutcomePipeline>`. `CompiledStep::Segment` can now produce
/// `segment` directly as `Box<dyn OutcomePipeline>`.
impl OutcomePipeline for OutcomeSegment {
    fn clone_box(&self) -> Box<dyn OutcomePipeline> {
        Box::new(self.clone())
    }

    fn run<'a>(
        &'a mut self,
        exchange: Exchange,
    ) -> Pin<Box<dyn Future<Output = PipelineOutcome> + Send + 'a>> {
        // Call the inherent async `run` method, NOT the trait method.
        // `OutcomeSegment::run` is unambiguous: inherent methods shadow
        // trait methods in Rust name resolution for plain method calls,
        // and the qualified `OutcomeSegment::run(self, exchange)` syntax
        // also selects the inherent fn.
        Box::pin(OutcomeSegment::run(self, exchange))
    }
}