use super::super::{
CursorEndpoint, OfferScopeProfile, OfferScopeSelection, ScopeArmMaterializationMeta, Transport,
profile::{
OfferArmRecvEvidence, OfferControllerCursorArm, OfferControllerLocalEvidence,
OfferControllerLocalReadiness, OfferCursorReadiness, OfferEntryPosition,
OfferMaterializationReadiness, OfferPassiveEvidence, OfferPassiveReadiness,
OfferPassiveReadySignal, OfferPassiveRecvEvidence,
},
};
use super::evidence::OfferIngressEvidence;
struct OfferIngressPlannerInput {
selection: OfferScopeSelection,
entry: OfferEntryPosition,
materialization: ScopeArmMaterializationMeta,
cursor: OfferCursorReadiness,
}
impl<'r, const ROLE: u8, T> CursorEndpoint<'r, ROLE, T>
where
T: Transport + 'r,
{
pub(super) fn offer_ingress_evidence(
&mut self,
selection: OfferScopeSelection,
entry: OfferEntryPosition,
profile: OfferScopeProfile,
) -> OfferIngressEvidence {
let input = OfferIngressPlannerInput {
selection,
entry,
materialization: self.selection_materialization_meta(selection),
cursor: if self.cursor.is_recv() {
OfferCursorReadiness::Recv
} else {
OfferCursorReadiness::NonRecv
},
};
match profile {
OfferScopeProfile::ControllerIntrinsic => {
self.controller_intrinsic_ingress_evidence(input)
}
OfferScopeProfile::ControllerDynamic => self.controller_dynamic_ingress_evidence(input),
OfferScopeProfile::PassiveIntrinsic => self.passive_intrinsic_ingress_evidence(input),
OfferScopeProfile::PassiveDynamic => self.passive_dynamic_ingress_evidence(input),
}
}
pub(super) fn offer_scope_profile(
&self,
scope_id: crate::global::const_dsl::ScopeId,
) -> OfferScopeProfile {
let is_controller = self.cursor.is_route_controller(scope_id);
let is_dynamic = self.cursor.route_scope_resolver(scope_id).is_some();
match (is_controller, is_dynamic) {
(true, true) => OfferScopeProfile::ControllerDynamic,
(true, false) => OfferScopeProfile::ControllerIntrinsic,
(false, true) => OfferScopeProfile::PassiveDynamic,
(false, false) => OfferScopeProfile::PassiveIntrinsic,
}
}
fn controller_intrinsic_ingress_evidence(
&self,
input: OfferIngressPlannerInput,
) -> OfferIngressEvidence {
OfferIngressEvidence {
profile: OfferScopeProfile::ControllerIntrinsic,
entry: input.entry,
cursor: input.cursor,
controller: self.controller_intrinsic_readiness(&input),
passive: OfferPassiveReadiness::NeedsTransport,
}
}
fn controller_dynamic_ingress_evidence(
&self,
input: OfferIngressPlannerInput,
) -> OfferIngressEvidence {
OfferIngressEvidence {
profile: OfferScopeProfile::ControllerDynamic,
entry: input.entry,
cursor: input.cursor,
controller: self.controller_dynamic_readiness(&input),
passive: OfferPassiveReadiness::NeedsTransport,
}
}
fn passive_intrinsic_ingress_evidence(
&self,
input: OfferIngressPlannerInput,
) -> OfferIngressEvidence {
OfferIngressEvidence {
profile: OfferScopeProfile::PassiveIntrinsic,
entry: input.entry,
cursor: input.cursor,
controller: OfferControllerLocalReadiness::NeedsTransport,
passive: self.passive_intrinsic_readiness(&input),
}
}
fn passive_dynamic_ingress_evidence(
&self,
input: OfferIngressPlannerInput,
) -> OfferIngressEvidence {
OfferIngressEvidence {
profile: OfferScopeProfile::PassiveDynamic,
entry: input.entry,
cursor: input.cursor,
controller: OfferControllerLocalReadiness::NeedsTransport,
passive: self.passive_dynamic_readiness(&input),
}
}
fn controller_intrinsic_readiness(
&self,
input: &OfferIngressPlannerInput,
) -> OfferControllerLocalReadiness {
let profile = OfferScopeProfile::ControllerIntrinsic;
profile.controller_local_readiness(self.controller_local_evidence(input))
}
fn controller_dynamic_readiness(
&self,
input: &OfferIngressPlannerInput,
) -> OfferControllerLocalReadiness {
let profile = OfferScopeProfile::ControllerDynamic;
profile.controller_local_readiness(self.controller_local_evidence(input))
}
fn controller_local_evidence(
&self,
input: &OfferIngressPlannerInput,
) -> OfferControllerLocalEvidence {
OfferControllerLocalEvidence::new(
input.cursor,
self.controller_cursor_arm(input),
self.controller_materialization_readiness(input),
)
}
fn controller_cursor_arm(&self, input: &OfferIngressPlannerInput) -> OfferControllerCursorArm {
if self
.controller_arm_at_cursor(input.selection.scope_id)
.is_some()
{
OfferControllerCursorArm::AtArm
} else {
OfferControllerCursorArm::OutsideArm
}
}
fn controller_materialization_readiness(
&self,
input: &OfferIngressPlannerInput,
) -> OfferMaterializationReadiness {
let Some(arm) = self.selected_arm_for_scope(input.selection.scope_id) else {
return OfferMaterializationReadiness::Ready;
};
if self.arm_requires_materialization_ready_evidence(input.selection.scope_id, arm)
&& !self.scope_has_ready_arm(input.selection.scope_id, arm)
{
OfferMaterializationReadiness::Pending
} else {
OfferMaterializationReadiness::Ready
}
}
fn passive_intrinsic_readiness(
&self,
input: &OfferIngressPlannerInput,
) -> OfferPassiveReadiness {
OfferScopeProfile::PassiveIntrinsic.passive_readiness(OfferPassiveEvidence::new(
self.passive_ready_signal(input),
self.passive_recv_evidence(input),
))
}
fn passive_dynamic_readiness(&self, input: &OfferIngressPlannerInput) -> OfferPassiveReadiness {
OfferScopeProfile::PassiveDynamic.passive_readiness(OfferPassiveEvidence::new(
self.passive_ready_signal(input),
self.passive_recv_evidence(input),
))
}
fn passive_ready_signal(&self, input: &OfferIngressPlannerInput) -> OfferPassiveReadySignal {
if self.scope_has_ready_arm_evidence(input.selection.scope_id) {
OfferPassiveReadySignal::Observed
} else {
OfferPassiveReadySignal::Absent
}
}
fn passive_recv_evidence(&self, input: &OfferIngressPlannerInput) -> OfferPassiveRecvEvidence {
if matches!(
self.arm_recv_evidence(input, 0),
OfferArmRecvEvidence::HasRecv
) || matches!(
self.arm_recv_evidence(input, 1),
OfferArmRecvEvidence::HasRecv
) {
OfferPassiveRecvEvidence::HasRecv
} else {
OfferPassiveRecvEvidence::Recvless
}
}
fn arm_recv_evidence(&self, input: &OfferIngressPlannerInput, arm: u8) -> OfferArmRecvEvidence {
let scope_id = input.selection.scope_id;
if self.arm_has_recv_with_materialization(scope_id, arm, input.materialization)
|| self
.compute_passive_arm_recv_meta(scope_id, arm, input.selection.offer_lane)
.is_recv_step()
{
OfferArmRecvEvidence::HasRecv
} else {
OfferArmRecvEvidence::Recvless
}
}
}