///|
fn csv_record(cells : Array[String]) -> String {
cells
.map(cell => "\"" + cell.replace_all(old="\"", new="\"\"") + "\"")
.join(",") +
"\r\n"
}
///|
fn json_cell(value : Json) -> String {
"json:" + canonical_json(value)
}
///|
/// RFC 4180 quoted UTF-8 review projection; dynamic cells contain tagged JSON.
/// Absence (false), null (true/json:null) and unresolved (empty presence) differ.
/// Rejects output above 16 Mi UTF-16 units rather than returning partial rows.
pub fn AuditReport::to_review_csv(
self : AuditReport,
keys : Array[String],
) -> String raise TraceError {
let fields = review_fields(keys)
let headers = ["query_index", "data_path", "status", "diagnostic"]
for key in fields {
let tag = canonical_json(Json::string(key))
for column in ["present:", "value:", "winning_source:", "trace:"] {
headers.push(column + tag)
}
}
let header = csv_record(headers)
let lines = [header]
let mut length = header.length()
if length > 16777216 {
reject(
"review_csv_limit", "", "CSV exceeds 16 Mi UTF-16 units; reduce requested fields or scans.",
)
}
for i, entry in self.entries {
let cells = [i.to_string(), json_cell(Json::string(entry.path))]
match (entry.result, entry.error) {
(Some(result), None) => {
cells.push("resolved")
cells.push("")
for key in fields {
match result.values.get(key) {
None => {
cells.push("false")
for _ in 0..<3 {
cells.push("")
}
}
Some(value) => {
let history = result.origins[key]
cells.push("true")
cells.push(json_cell(value))
cells.push(
json_cell(Json::string(history[history.length() - 1].path)),
)
cells.push(json_cell(history_value(history)))
}
}
}
}
(None, Some(error)) => {
cells.push("error")
cells.push(json_cell(error.to_json()))
for _ in fields {
for _ in 0..<4 {
cells.push("")
}
}
}
_ => abort("AuditEntry invariant")
}
let line = csv_record(cells)
if line.length() > 16777216 - length {
reject(
"review_csv_limit",
entry.path,
"CSV exceeds 16 Mi UTF-16 units; reduce requested fields or scans.",
)
}
length += line.length()
lines.push(line)
}
lines.join("")
}