use crate::descriptor::ClaimRef;
use crate::report::{
CensusDelta, CensusDirection, ClaimCoverage, ClaimExercise, ConclusionFlip,
ExecutionRevisionChange, ExecutionRevisions, InvocationProfile, InvocationProfileChange,
OutcomeClass, ReportDiff, ReportExecutionDiff, ReportPopulationDiff, RowRevisionChange,
RowRevisionId, TargetBinding, TargetBindingChange, TrialId,
};
use core::cmp::Ordering;
impl CensusDelta {
#[must_use]
pub(in crate::report) fn between(before: usize, after: usize) -> Self {
let direction = match after.cmp(&before) {
Ordering::Greater => CensusDirection::Grew,
Ordering::Equal => CensusDirection::Unchanged,
Ordering::Less => CensusDirection::Shrank,
};
Self {
before,
after,
direction,
}
}
#[must_use]
pub const fn before(self) -> usize {
self.before
}
#[must_use]
pub const fn after(self) -> usize {
self.after
}
#[must_use]
pub const fn direction(self) -> CensusDirection {
self.direction
}
}
crate::report::implement_copy_change_pair! {
RowRevisionChange {
context { trial: TrialId => "The trial.", }
value: RowRevisionId,
construction: "One trial whose authored row was edited between the two runs.",
before: "The row revision the baseline recorded.",
after: "The row revision the current report records.",
}
}
crate::report::implement_copy_change_pair! {
ExecutionRevisionChange {
context { trial: TrialId => "The trial.", }
value: ExecutionRevisions,
construction: "One trial whose subject or check revision standing moved between the two runs.",
before: "The baseline's subject and check revisions.",
after: "The current report's subject and check revisions.",
}
}
crate::report::implement_copy_change_pair! {
InvocationProfileChange {
context {}
value: InvocationProfile,
construction: "One changed conclusion-relevant invocation profile.",
before: "The baseline's invocation profile.",
after: "The current report's invocation profile.",
}
}
crate::report::implement_borrowed_change_pair! {
TargetBindingChange {
context {}
value: TargetBinding,
construction: "One changed target and toolchain pair.",
before: "The baseline's target and toolchain.",
after: "The current report's target and toolchain.",
}
}
crate::report::implement_copy_change_pair! {
ConclusionFlip {
context { trial: TrialId => "The trial.", }
value: OutcomeClass,
construction: "One trial whose outcome differs between the two runs.",
before: "What the baseline recorded.",
after: "What the current report records.",
}
}
impl ReportPopulationDiff {
#[must_use]
pub(in crate::report) fn stated(
added: Vec<TrialId>,
removed: Vec<TrialId>,
revised: Vec<RowRevisionChange>,
census: CensusDelta,
) -> Self {
Self {
added,
removed,
revised,
census,
}
}
#[must_use]
pub fn added(&self) -> &[TrialId] {
&self.added
}
#[must_use]
pub fn removed(&self) -> &[TrialId] {
&self.removed
}
#[must_use]
pub fn revised(&self) -> &[RowRevisionChange] {
&self.revised
}
#[must_use]
pub const fn census(&self) -> CensusDelta {
self.census
}
}
impl ReportExecutionDiff {
#[must_use]
pub(in crate::report) fn stated(
revisions: Vec<ExecutionRevisionChange>,
flips: Vec<ConclusionFlip>,
invocation: Option<InvocationProfileChange>,
target: Option<TargetBindingChange>,
) -> Self {
Self {
revisions,
flips,
invocation,
target: target.map(Box::new),
}
}
#[must_use]
pub fn revisions(&self) -> &[ExecutionRevisionChange] {
&self.revisions
}
#[must_use]
pub fn flips(&self) -> &[ConclusionFlip] {
&self.flips
}
#[must_use]
pub const fn invocation(&self) -> Option<InvocationProfileChange> {
self.invocation
}
#[must_use]
pub fn target(&self) -> Option<&TargetBindingChange> {
self.target.as_deref()
}
}
impl ReportDiff {
#[must_use]
pub(in crate::report) const fn stated(
population: ReportPopulationDiff,
execution: ReportExecutionDiff,
) -> Self {
Self {
population,
execution,
}
}
#[must_use]
pub const fn population(&self) -> &ReportPopulationDiff {
&self.population
}
#[must_use]
pub const fn execution(&self) -> &ReportExecutionDiff {
&self.execution
}
}
impl ClaimExercise {
#[must_use]
pub(in crate::report) const fn counted(
claim: ClaimRef,
exercised: usize,
unexercised: usize,
) -> Self {
Self {
claim,
exercised,
unexercised,
}
}
#[must_use]
pub const fn claim(self) -> ClaimRef {
self.claim
}
#[must_use]
pub const fn exercised(self) -> usize {
self.exercised
}
#[must_use]
pub const fn unexercised(self) -> usize {
self.unexercised
}
#[must_use]
pub const fn denominator(self) -> usize {
self.exercised.saturating_add(self.unexercised)
}
}
impl ClaimCoverage {
#[must_use]
pub(in crate::report) fn read(entries: Vec<ClaimExercise>) -> Self {
Self { entries }
}
#[must_use]
pub fn entries(&self) -> &[ClaimExercise] {
&self.entries
}
#[must_use]
pub fn exercise_or_zero(&self, claim: ClaimRef) -> ClaimExercise {
self.entries
.iter()
.copied()
.find(|entry| entry.claim() == claim)
.unwrap_or_else(|| ClaimExercise::counted(claim, 0usize, 0usize))
}
}