///|
fn report_integer(value : Json, location : String) -> Result[Int32, String] {
  match value {
    Number(_, repr=Some(text)) if !text.is_empty() &&
      text.code_units().all(c => c >= 48 && c <= 57) => {
      let n = @string.parse_int(text) catch {
        _ => return Err("\{location} exceeds the nonnegative 32-bit range")
      }
      Ok(n)
    }
    _ =>
      Err(
        "\{location} must be a plain nonnegative decimal 32-bit integer (no fraction or exponent)",
      )
  }
}

///|
/// Decode the version-1 single-report JSON contract without rescanning SQL.
/// Unknown/missing fields, duplicate decoded keys, invalid Unicode, unsupported
/// versions, invalid ranges and inconsistent completion are rejected. Original
/// SQL, diagnostic order and every supported value are preserved.
/// Numeric fields require plain nonnegative decimal integer tokens: fractions,
/// exponents and negative zero are rejected before floating-point rounding.
pub fn Report::parse_json(source : String) -> Result[Report, String] {
  if !valid_unicode(source) {
    return Err("Report JSON contains invalid Unicode")
  }
  let value = @json.parse(
    source,
    reject_duplicate_keys=true,
    max_nesting_depth=16,
    preserve_number_repr=true,
  ) catch {
    e => return Err("Invalid report JSON: \{Repr(e)}")
  }
  guard value is Object(fields) && fields.length() == 5 else {
    return Err(
      "Report must contain exactly format_version, source, statements, complete and diagnostics",
    )
  }
  guard value
    is {
      "format_version": version,
      "source": String(sql),
      "statements": count,
      "complete": completion,
      "diagnostics": Array(items),
      ..
    } else {
    return Err(
      "Expected version-1 single-report fields with string source and diagnostics array",
    )
  }
  guard report_integer(version, "format_version") is Ok(1) else {
    return Err("format_version must be the plain integer 1")
  }
  let complete = match completion {
    True => true
    False => false
    _ => return Err("complete must be boolean")
  }
  let statements = match report_integer(count, "statements") {
    Ok(n) => n
    Err(e) => return Err(e)
  }
  let diagnostics = []
  for i, item in items {
    guard item is Object(fields) && fields.length() == 5 else {
      return Err(
        "diagnostics[\{i}] must contain exactly code, severity, span, message and help",
      )
    }
    guard item
      is {
        "code": String(code),
        "severity": String(level),
        "span": region,
        "message": String(message),
        "help": String(help),
        ..
      } else {
      return Err("diagnostics[\{i}] has missing fields or invalid field types")
    }
    if code.is_empty() || message.is_empty() {
      return Err("diagnostics[\{i}] code and message must not be empty")
    }
    let severity : Severity = match level {
      "Error" => Error
      "Warning" => Warning
      "Incomplete" => Incomplete
      _ =>
        return Err(
          "diagnostics[\{i}].severity must be Error, Warning or Incomplete",
        )
    }
    if complete && severity == Incomplete {
      return Err("complete=true conflicts with an incomplete diagnostic")
    }
    guard region is Object(fields) &&
      fields.length() == 2 &&
      region is { "start": start_json, "end": end_json, .. } else {
      return Err("diagnostics[\{i}].span must contain exactly start and end")
    }
    let start = match
      report_integer(start_json, "diagnostics[\{i}].span.start") {
      Ok(n) => n
      Err(e) => return Err(e)
    }
    let end = match report_integer(end_json, "diagnostics[\{i}].span.end") {
      Ok(n) => n
      Err(e) => return Err(e)
    }
    if end < start || !source_boundary(sql, start) || !source_boundary(sql, end) {
      return Err(
        "diagnostics[\{i}].span is outside the source, reversed or splits a surrogate pair",
      )
    }
    diagnostics.push({ code, severity, span: { start, end, }, message, help, })
  }
  Ok({ source: sql, statements, complete, diagnostics, })
}