//! Criterion microbench for the `inkferro-rt` line-diff transport.
//!
//! Bench id `rt_diff` (paired by the 5x gate with `bench/js-baseline/`'s
//! `rt_diff` entry, which drives ink's `createIncremental` over the same two
//! frames).
//!
//! The "previous" frame is the shared pipeline golden (`bench/fixtures/
//! pipeline_golden.txt`); the "next" frame mutates one interior text line
//! ("status: ok" -> "status: busy"). Each iteration runs a primed
//! `LineDiff::diff` so the timed work is the per-frame incremental diff (the
//! steady-state render path), not the one-time bootstrap.

use std::hint::black_box;

use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
use inkferro_rt::LineDiff;

fn fixture_path(name: &str) -> std::path::PathBuf {
    std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("../../bench/fixtures")
        .join(name)
}

fn bench_rt_diff(c: &mut Criterion) {
    let previous = std::fs::read_to_string(fixture_path("pipeline_golden.txt"))
        .expect("read pipeline_golden.txt");
    // Mutate one interior line so the diff has real work: the steady-state
    // single-line update that the line-diff path is optimised for.
    let next = previous.replace("status: ok", "status: busy");
    assert_ne!(
        previous, next,
        "rt_diff next frame must differ from previous"
    );

    c.bench_function("rt_diff", |b| {
        // `diff` mutates state (after one call, `next` becomes the baseline and a
        // second call early-returns empty), so each timed sample needs a freshly
        // primed transport. `iter_batched` builds it in the (untimed) setup
        // closure; only `diff(next)` is measured.
        b.iter_batched(
            || {
                // Prime with `previous` via `sync` — sets the baseline, emits no
                // bytes — so the measured `diff` is a steady-state incremental.
                let mut transport = LineDiff::new();
                transport.sync(&previous);
                transport
            },
            |mut transport| black_box(transport.diff(black_box(&next))),
            BatchSize::SmallInput,
        );
    });
}

criterion_group!(benches, bench_rt_diff);
criterion_main!(benches);
