vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Progress reporting primitives and checkpoint triggering for streaming execution.

use super::regression_sinking::write_checkpoint;

/// Snapshot emitted to a progress sink while streaming.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StreamingProgress {
    /// Total cases observed so far.
    pub tested: u64,
    /// Total successfully matched cases so far.
    pub passed: u64,
    /// Total failed cases so far.
    pub failed: u64,
    /// Current operation id being processed when the snapshot was emitted.
    pub current_op: String,
}

/// Aggregate counters emitted after a streaming run.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct StreamingSummary {
    /// Number of processed test inputs.
    pub tested: u64,
    /// Number of successful comparisons.
    pub passed: u64,
    /// Number of failed comparisons and execution failures.
    pub failed: u64,
}

/// Receiver for streaming progress updates.
pub trait ProgressSink: Send {
    /// Receives a progress snapshot when the runner decides to report.
    fn on_progress(&mut self, progress: StreamingProgress);
}

/// No-op sink used by the default runner configuration.
#[derive(Clone, Default)]
pub struct NoProgress;

impl ProgressSink for NoProgress {
    fn on_progress(&mut self, _: StreamingProgress) {}
}

/// Adapters that convert any callback into a [`ProgressSink`].
pub struct FnProgress<F>(pub F);

impl<F: FnMut(StreamingProgress) + Send + 'static> ProgressSink for FnProgress<F> {
    fn on_progress(&mut self, progress: StreamingProgress) {
        self.0(progress);
    }
}

#[inline]
pub(crate) fn report_progress<P: ProgressSink>(
    sink: &mut P,
    summary: &StreamingSummary,
    current_op: &str,
    next_test_id: u64,
    progress_interval: u64,
    checkpoint_interval: u64,
    shard_id: u64,
    shard_count: u64,
) {
    let should_report =
        summary.tested == 0 || summary.tested % progress_interval == 0 || summary.failed > 0;
    if should_report {
        sink.on_progress(StreamingProgress {
            tested: summary.tested,
            passed: summary.passed,
            failed: summary.failed,
            current_op: current_op.to_string(),
        });
    }

    if checkpoint_interval > 0 && summary.tested > 0 && summary.tested % checkpoint_interval == 0 {
        let _ = write_checkpoint(shard_id, next_test_id, shard_count);
    }
}