Something went wrong. Try again.
fork of gitlab.com/devnw/zig/json for zig 0.17
Something went wrong. Try again.
5.2 kB · 159 lines
Zig
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160// SPDX-License-Identifier: Apache-2.0// Copyright (c) 2024-2025 CodePros
//! Debug Utilities//!//! Provides formatting for validation reports and other debug output.
const std = @import("std");const json = @import("json.zig");
const ValidationError = json.ValidationError;const ValidationReport = json.ValidationReport;
/// Format a validation report as human-readable textpub fn formatReport(a: std.mem.Allocator, r: ValidationReport) ![]u8 { var buf: std.ArrayList(u8) = .empty; errdefer buf.deinit(a);
if (r.ok) { try buf.appendSlice(a, "Validation: OK\n"); } else { try buf.appendSlice(a, "Validation: FAILED\n"); try buf.appendSlice(a, "Errors:\n");
for (r.errors, 0..) |err, i| { try buf.appendSlice(a, " "); var num_buf: [10]u8 = undefined; const num_str = std.fmt.bufPrint(&num_buf, "{d}", .{i + 1}) catch "?"; try buf.appendSlice(a, num_str); try buf.appendSlice(a, ". ");
// Instance pointer try buf.appendSlice(a, "at "); if (err.instance_ptr.len == 0) { try buf.appendSlice(a, "(root)"); } else { try buf.appendSlice(a, err.instance_ptr); }
// Keyword try buf.appendSlice(a, " ["); try buf.appendSlice(a, err.keyword); try buf.appendSlice(a, "]: ");
// Message try buf.appendSlice(a, err.message); try buf.append(a, '\n');
// Schema location try buf.appendSlice(a, " schema: "); if (err.schema_ptr.len == 0) { try buf.appendSlice(a, "(root)"); } else { try buf.appendSlice(a, err.schema_ptr); } try buf.append(a, '\n'); } }
return buf.toOwnedSlice(a);}
/// Format validation errors as JSON arraypub fn formatReportJson(a: std.mem.Allocator, r: ValidationReport) ![]u8 { var buf: std.ArrayList(u8) = .empty; errdefer buf.deinit(a);
try buf.append(a, '[');
for (r.errors, 0..) |err, i| { if (i > 0) try buf.append(a, ','); try buf.append(a, '{');
try buf.appendSlice(a, "\"instancePointer\":"); try writeJsonString(a, &buf, err.instance_ptr); try buf.append(a, ',');
try buf.appendSlice(a, "\"schemaPointer\":"); try writeJsonString(a, &buf, err.schema_ptr); try buf.append(a, ',');
try buf.appendSlice(a, "\"keyword\":"); try writeJsonString(a, &buf, err.keyword); try buf.append(a, ',');
try buf.appendSlice(a, "\"message\":"); try writeJsonString(a, &buf, err.message);
try buf.append(a, '}'); }
try buf.append(a, ']');
return buf.toOwnedSlice(a);}
fn writeJsonString(a: std.mem.Allocator, buf: *std.ArrayList(u8), s: []const u8) !void { try buf.append(a, '"'); for (s) |c| { switch (c) { '"' => try buf.appendSlice(a, "\\\""), '\\' => try buf.appendSlice(a, "\\\\"), '\n' => try buf.appendSlice(a, "\\n"), '\r' => try buf.appendSlice(a, "\\r"), '\t' => try buf.appendSlice(a, "\\t"), else => { if (c < 0x20) { try buf.appendSlice(a, "\\u00"); const hex = "0123456789ABCDEF"; try buf.append(a, hex[(c >> 4) & 0xF]); try buf.append(a, hex[c & 0xF]); } else { try buf.append(a, c); } }, } } try buf.append(a, '"');}
test "format empty report" { var errors = [_]ValidationError{}; const report = ValidationReport{ .ok = true, .errors = &errors }; const result = try formatReport(std.testing.allocator, report); defer std.testing.allocator.free(result); try std.testing.expect(std.mem.indexOf(u8, result, "OK") != null);}
test "format report with errors" { var errors = [_]ValidationError{ .{ .instance_ptr = "/name", .schema_ptr = "/properties/name", .keyword = "type", .message = "expected string", }, }; const report = ValidationReport{ .ok = false, .errors = &errors }; const result = try formatReport(std.testing.allocator, report); defer std.testing.allocator.free(result); try std.testing.expect(std.mem.indexOf(u8, result, "FAILED") != null); try std.testing.expect(std.mem.indexOf(u8, result, "/name") != null);}
test "format report json" { var errors = [_]ValidationError{ .{ .instance_ptr = "/x", .schema_ptr = "/properties/x", .keyword = "minimum", .message = "too small", }, }; const report = ValidationReport{ .ok = false, .errors = &errors }; const result = try formatReportJson(std.testing.allocator, report); defer std.testing.allocator.free(result); try std.testing.expect(std.mem.startsWith(u8, result, "[{")); try std.testing.expect(std.mem.indexOf(u8, result, "\"keyword\":\"minimum\"") != null);}