Skip to main content

varar_core/
param_diff.rs

1//! Parameter comparison — port of `param-diff.ts` / `ParamDiff.java`. Compares a
2//! sensor's returned inline actuals against the values captured from the document.
3
4use crate::cell_diff::CellDiff;
5use crate::registry::FormatFn;
6use crate::span::Span;
7use crate::value::Value;
8
9/// Compares `returned` against `expected` with no display formatters.
10pub fn compare_params(
11    returned: &[Value],
12    expected: &[Value],
13    param_spans: &[Span],
14    source_texts: &[String],
15) -> Vec<CellDiff> {
16    compare_params_with_formats(returned, expected, param_spans, source_texts, None)
17}
18
19/// Compares `returned` against `expected` (the captured args), one [`CellDiff`]
20/// per parameter. `source_texts` supplies each diff's `expected` display;
21/// `formats` (aligned 1:1, `None` entries where a type has none) renders display
22/// strings only, never the verdict (which is structural [`Value`] equality).
23pub fn compare_params_with_formats(
24    returned: &[Value],
25    expected: &[Value],
26    param_spans: &[Span],
27    source_texts: &[String],
28    formats: Option<&[Option<FormatFn>]>,
29) -> Vec<CellDiff> {
30    let mut diffs = Vec::with_capacity(expected.len());
31    for i in 0..expected.len() {
32        // Structural equality is the verdict (`Objects.equals` parity).
33        let ok = returned[i] == expected[i];
34        let format = formats.and_then(|f| f.get(i)).and_then(|opt| opt.as_ref());
35        let expected_text = if i < source_texts.len() {
36            source_texts[i].clone()
37        } else {
38            render_param_value(&expected[i], format).0
39        };
40        let (actual_text, via_format) = render_param_value(&returned[i], format);
41        diffs.push(CellDiff {
42            column: format!("cell {}", i + 1),
43            span: param_spans[i],
44            expected: expected_text,
45            actual: actual_text,
46            ok,
47            expected_value: Some(expected[i].clone()),
48            actual_value: Some(returned[i].clone()),
49            formatted: via_format,
50        });
51    }
52    diffs
53}
54
55/// Renders one side of a parameter diff: the type's `format` when it has one
56/// (and it produces a value), else the shared string/primitive chain.
57fn render_param_value(value: &Value, format: Option<&FormatFn>) -> (String, bool) {
58    if let Some(f) = format {
59        if let Some(rendered) = f(value) {
60            return (rendered, true);
61        }
62    }
63    (crate::cell_diff::render_cell_value(value), false)
64}