Skip to main content

varar_core/
doc_string_diff.rs

1//! Doc-string comparison — port of `doc-string-diff.ts` / `DocStringDiff.java`.
2
3use crate::cell_diff::CellDiff;
4use crate::error::{StepError, quote};
5use crate::span::Span;
6use crate::value::Value;
7
8/// The column label a doc-string cell carries in a [`CellDiff`], so its mismatch
9/// message reads `doc string: expected … but was …`.
10pub const DOC_STRING_COLUMN: &str = "doc string";
11
12/// Compares a doc-string step's return against the fence body (exact equality,
13/// trailing newline included).
14///
15/// A doc string is ONE CELL, compared whole, so a difference is an ordinary
16/// [`CellDiff`] and the executor raises the same [`StepError::CellMismatch`] as
17/// any other cell. `expected`/`actual` are quoted: a doc string routinely
18/// differs only in whitespace, and bare text would render a missing trailing
19/// newline as no difference at all.
20///
21/// `None` → no check. A non-string return → [`StepError::ReturnShape`].
22pub fn compare_doc_string(
23    returned: Option<&Value>,
24    content: &str,
25    span: Span,
26) -> Result<Option<CellDiff>, StepError> {
27    let s = match returned {
28        None => return Ok(None),
29        Some(Value::String(s)) => s,
30        Some(other) => {
31            return Err(StepError::ReturnShape(format!(
32                "expected a doc string (string), got {}",
33                other.type_name()
34            )));
35        }
36    };
37    if s == content {
38        Ok(None)
39    } else {
40        Ok(Some(CellDiff {
41            column: DOC_STRING_COLUMN.to_string(),
42            span,
43            expected: quote(content),
44            actual: quote(s),
45            ok: false,
46            expected_value: None,
47            actual_value: None,
48            formatted: false,
49        }))
50    }
51}