use crate::descriptor::{ClaimRef, TablePosture};
use crate::muterprater::proposal::types::{
ClaimPinnedGround, Demonstration, DischargeEvidence, DuplicateRefusal, FailureComparison,
MutantKilledGround, NoComparison, NoComparisonReason, ObligationComparison,
ObligationDischargedGround, OwedClaim, ProofDelta, ProofDeltaRefusal, ProofRefusal,
};
use crate::muterprater::{ActivationDisposition, DemonstratedRejection, MutationTarget};
use crate::report::{
Fingerprint, ReplayCapsule, RunAttempt, RunReport, TrialConclusion, TrialId, TrialReport,
};
impl Demonstration {
pub fn read(report: RunReport, candidate: TrialId) -> Result<Self, ProofRefusal> {
require_staged(&report)?;
let trial_report = candidate_report(&report, candidate)?;
let rejection = demonstrated_rejection(&trial_report, candidate)?;
Ok(Self {
report,
trial_report,
rejection,
})
}
#[must_use]
pub const fn report(&self) -> &RunReport {
&self.report
}
#[must_use]
pub const fn trial_report(&self) -> &TrialReport {
&self.trial_report
}
#[must_use]
pub const fn rejection(&self) -> &DemonstratedRejection {
&self.rejection
}
}
fn require_staged(report: &RunReport) -> Result<(), ProofRefusal> {
match report.posture() {
TablePosture::Staged { parent: _ } => Ok(()),
TablePosture::Authored => Err(ProofRefusal::NotStaged),
}
}
fn candidate_report(report: &RunReport, candidate: TrialId) -> Result<TrialReport, ProofRefusal> {
let Some(entry) = report
.census()
.iter()
.find(|accounting| accounting.trial() == candidate)
else {
return Err(ProofRefusal::CandidateNotInCensus);
};
let Some(executed) = entry.disposition().report() else {
return Err(ProofRefusal::CandidateNotSelected);
};
Ok(executed.clone())
}
fn demonstrated_rejection(
report: &TrialReport,
candidate: TrialId,
) -> Result<DemonstratedRejection, ProofRefusal> {
match report.attempt() {
RunAttempt::Executed(TrialConclusion::Refused(finding)) => Ok(
DemonstratedRejection::demonstrated(candidate, finding.clone()),
),
RunAttempt::Executed(TrialConclusion::Passed) => Err(ProofRefusal::CandidateDidNotRefuse),
RunAttempt::SkippedWithReason(_)
| RunAttempt::TimedOut
| RunAttempt::InfrastructureFailed(_) => Err(ProofRefusal::CandidateDidNotExecute),
}
}
impl ProofDelta {
pub const fn between(before: usize, after: usize) -> Result<Self, ProofDeltaRefusal> {
if after <= before {
return Err(ProofDeltaRefusal::NoProofAdded { before, after });
}
Ok(Self { before, after })
}
#[must_use]
pub const fn before(self) -> usize {
self.before
}
#[must_use]
pub const fn after(self) -> usize {
self.after
}
}
impl FailureComparison {
pub fn compared(
candidate: Fingerprint,
known: Vec<Fingerprint>,
) -> Result<Self, DuplicateRefusal> {
if known.contains(&candidate) {
return Err(DuplicateRefusal::FingerprintAlreadyKnown(candidate));
}
Ok(Self { candidate, known })
}
#[must_use]
pub const fn candidate(&self) -> Fingerprint {
self.candidate
}
pub fn known(&self) -> impl Iterator<Item = &Fingerprint> {
self.known.iter()
}
}
impl ObligationComparison {
pub fn compared(owed: ClaimRef, discharges: &[TrialId]) -> Result<Self, DuplicateRefusal> {
if let Some(first) = discharges.first() {
return Err(DuplicateRefusal::ObligationAlreadyDischarged(*first));
}
Ok(Self { owed })
}
#[must_use]
pub const fn owed(&self) -> ClaimRef {
self.owed
}
}
impl NoComparison {
#[must_use]
pub const fn stated(reason: NoComparisonReason) -> Self {
Self { reason }
}
#[must_use]
pub const fn reason(self) -> NoComparisonReason {
self.reason
}
}
impl MutantKilledGround {
#[must_use]
pub(in crate::muterprater) const fn shown(
target: MutationTarget,
activation: ActivationDisposition,
capsule: ReplayCapsule,
demonstration: Demonstration,
) -> Self {
Self {
target,
activation,
capsule,
demonstration,
}
}
#[must_use]
pub const fn target(&self) -> &MutationTarget {
&self.target
}
#[must_use]
pub const fn activation(&self) -> ActivationDisposition {
self.activation
}
#[must_use]
pub const fn capsule(&self) -> &ReplayCapsule {
&self.capsule
}
#[must_use]
pub const fn demonstration(&self) -> &Demonstration {
&self.demonstration
}
}
impl ClaimPinnedGround {
#[must_use]
pub const fn moved(claim: ClaimRef, capsule: ReplayCapsule, delta: ProofDelta) -> Self {
Self {
claim,
capsule,
delta,
}
}
#[must_use]
pub const fn claim(&self) -> ClaimRef {
self.claim
}
#[must_use]
pub const fn capsule(&self) -> &ReplayCapsule {
&self.capsule
}
#[must_use]
pub const fn delta(&self) -> ProofDelta {
self.delta
}
}
impl ObligationDischargedGround {
#[must_use]
pub const fn discharged(owed: OwedClaim, discharge: DischargeEvidence) -> Self {
Self { owed, discharge }
}
#[must_use]
pub const fn owed(&self) -> &OwedClaim {
&self.owed
}
#[must_use]
pub const fn discharge(&self) -> &DischargeEvidence {
&self.discharge
}
}