use crate::wire::{
AttachEnvelope, BindingEpoch, DeliverySeq, DetachEnvelope, EnrollmentEnvelope, LeaveEnvelope,
ObserverBackpressure, ObserverBackpressureState, RecordAdmissionEnvelope,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ObserverCheckedOperation {
Enrollment(EnrollmentEnvelope),
CredentialAttach(AttachEnvelope),
InitialDetach {
request: DetachEnvelope,
committed_binding_epoch: BindingEpoch,
},
Leave {
request: LeaveEnvelope,
prior_terminal_cell_exists: bool,
},
RecordAdmission(RecordAdmissionEnvelope),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ObserverFloorPermit {
observer_progress: DeliverySeq,
cap_floor: u128,
}
impl ObserverFloorPermit {
#[must_use]
pub const fn observer_progress(self) -> DeliverySeq {
self.observer_progress
}
#[must_use]
pub const fn cap_floor(self) -> u128 {
self.cap_floor
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ObserverFloorDecision {
Eligible(ObserverFloorPermit),
Respond(ObserverBackpressure),
}
#[must_use]
pub fn check_observer_floor(
operation: ObserverCheckedOperation,
observer_progress: DeliverySeq,
cap_floor: u128,
) -> ObserverFloorDecision {
let observer_limit = u128::from(observer_progress) + 1;
if cap_floor <= observer_limit {
return ObserverFloorDecision::Eligible(ObserverFloorPermit {
observer_progress,
cap_floor,
});
}
let state = ObserverBackpressureState::initial(observer_progress);
let response = match operation {
ObserverCheckedOperation::Enrollment(request) => {
ObserverBackpressure::Enrollment { request, state }
}
ObserverCheckedOperation::CredentialAttach(request) => {
ObserverBackpressure::CredentialAttach { request, state }
}
ObserverCheckedOperation::InitialDetach {
request,
committed_binding_epoch,
} => ObserverBackpressure::Detach {
request,
committed_binding_epoch,
state,
},
ObserverCheckedOperation::Leave {
request,
prior_terminal_cell_exists,
} => ObserverBackpressure::Leave {
request,
state,
prior_terminal_cell_exists,
},
ObserverCheckedOperation::RecordAdmission(request) => {
ObserverBackpressure::RecordAdmission { request, state }
}
};
ObserverFloorDecision::Respond(response)
}