| ... | ... | @@ -415,6 +415,12 @@ pub const Document = struct { |
| 415 | 415 | _ = options; |
| 416 | 416 | return std.fmt.format(writer, "{}", .{this.root}); |
| 417 | 417 | } |
| 418 | |
| 419 | pub fn stringify(this: *const Document, writer: anytype, space: Space, indent: u8) @TypeOf(writer).Error!void { |
| 420 | const fill = space.fill(); |
| 421 | for (0..indent) |_| try writer.writeAll(fill); |
| 422 | return @errorCast(this.root.stringify(writer, space, indent)); |
| 423 | } |
| 418 | 424 | }; |
| 419 | 425 | |
| 420 | 426 | pub const ValueIndex = enum(u32) { |
| ... | ... | @@ -433,6 +439,10 @@ pub const ValueIndex = enum(u32) { |
| 433 | 439 | return std.fmt.format(writer, "{}", .{this.v()}); |
| 434 | 440 | } |
| 435 | 441 | |
| 442 | fn stringify(this: ValueIndex, writer: anytype, space: Space, indent: u8) !void { |
| 443 | return this.v().stringify(writer, space, indent); |
| 444 | } |
| 445 | |
| 436 | 446 | pub fn v(this: ValueIndex) Value { |
| 437 | 447 | std.debug.assert(this != .zero); |
| 438 | 448 | std.debug.assert(doc != null); // make sure to call Document.acquire() |
| ... | ... | @@ -493,6 +503,17 @@ pub const Value = union(enum(u8)) { |
| 493 | 503 | inline .object, .array, .string, .number => |t| std.fmt.format(writer, "{}", .{t}), |
| 494 | 504 | }; |
| 495 | 505 | } |
| 506 | |
| 507 | fn stringify(this: Value, writer: anytype, space: Space, indent: u8) anyerror!void { |
| 508 | return switch (this) { |
| 509 | .zero => unreachable, |
| 510 | .null => writer.writeAll("null"), |
| 511 | .true => writer.writeAll("true"), |
| 512 | .false => writer.writeAll("false"), |
| 513 | inline .object, .array => |t| t.stringify(writer, space, indent), |
| 514 | inline .string, .number => |t| t.stringify(writer), |
| 515 | }; |
| 516 | } |
| 496 | 517 | }; |
| 497 | 518 | |
| 498 | 519 | pub const Array = []align(1) const ValueIndex; |
| ... | ... | @@ -508,6 +529,12 @@ pub const StringIndex = enum(u32) { |
| 508 | 529 | try writer.writeAll("\""); |
| 509 | 530 | } |
| 510 | 531 | |
| 532 | fn stringify(this: StringIndex, writer: anytype) anyerror!void { |
| 533 | try writer.writeAll("\""); |
| 534 | try writer.writeAll(this.to()); |
| 535 | try writer.writeAll("\""); |
| 536 | } |
| 537 | |
| 511 | 538 | pub fn to(this: StringIndex) []const u8 { |
| 512 | 539 | var d = doc.?.extras.ptr[@intFromEnum(this)..]; |
| 513 | 540 | std.debug.assert(@as(Value.Tag, @enumFromInt(d[0])) == .string); |
| ... | ... | @@ -532,6 +559,21 @@ pub const ArrayIndex = enum(u32) { |
| 532 | 559 | try writer.writeAll("]"); |
| 533 | 560 | } |
| 534 | 561 | |
| 562 | fn stringify(this: ArrayIndex, writer: anytype, space: Space, indent: u8) anyerror!void { |
| 563 | const fill = space.fill(); |
| 564 | const items = this.to(); |
| 565 | try writer.writeAll("["); |
| 566 | for (items, 0..) |item, i| { |
| 567 | if (i > 0) try writer.writeAll(","); |
| 568 | if (fill.len > 0) try writer.writeAll("\n"); |
| 569 | for (0..indent + 1) |_| try writer.writeAll(fill); |
| 570 | try item.stringify(writer, space, indent + 1); |
| 571 | } |
| 572 | if (fill.len > 0) try writer.writeAll("\n"); |
| 573 | for (0..indent) |_| try writer.writeAll(fill); |
| 574 | try writer.writeAll("]"); |
| 575 | } |
| 576 | |
| 535 | 577 | pub fn to(this: ArrayIndex) Array { |
| 536 | 578 | var d = doc.?.extras.ptr[@intFromEnum(this)..]; |
| 537 | 579 | std.debug.assert(@as(Value.Tag, @enumFromInt(d[0])) == .array); |
| ... | ... | @@ -558,6 +600,23 @@ pub const ObjectIndex = enum(u32) { |
| 558 | 600 | try writer.writeAll("}"); |
| 559 | 601 | } |
| 560 | 602 | |
| 603 | fn stringify(this: ObjectIndex, writer: anytype, space: Space, indent: u8) anyerror!void { |
| 604 | const fill = space.fill(); |
| 605 | const keys, const values = this.to(); |
| 606 | try writer.writeAll("{"); |
| 607 | for (keys, values, 0..) |k, v, i| { |
| 608 | if (i > 0) try writer.writeAll(","); |
| 609 | if (fill.len > 0) try writer.writeAll("\n"); |
| 610 | for (0..indent + 1) |_| try writer.writeAll(fill); |
| 611 | try k.stringify(writer); |
| 612 | try writer.writeAll(":"); |
| 613 | try v.stringify(writer, space, indent + 1); |
| 614 | } |
| 615 | if (fill.len > 0) try writer.writeAll("\n"); |
| 616 | for (0..indent) |_| try writer.writeAll(fill); |
| 617 | try writer.writeAll("}"); |
| 618 | } |
| 619 | |
| 561 | 620 | pub fn to(this: ObjectIndex) struct { []align(1) const StringIndex, Array } { |
| 562 | 621 | var d = doc.?.extras.ptr[@intFromEnum(this)..]; |
| 563 | 622 | std.debug.assert(@as(Value.Tag, @enumFromInt(d[0])) == .object); |
| ... | ... | @@ -614,6 +673,10 @@ pub const NumberIndex = enum(u32) { |
| 614 | 673 | try writer.writeAll(this.to()); |
| 615 | 674 | } |
| 616 | 675 | |
| 676 | fn stringify(this: NumberIndex, writer: anytype) anyerror!void { |
| 677 | try writer.writeAll(this.to()); |
| 678 | } |
| 679 | |
| 617 | 680 | pub fn to(this: NumberIndex) []const u8 { |
| 618 | 681 | var d = doc.?.extras.ptr[@intFromEnum(this)..]; |
| 619 | 682 | std.debug.assert(@as(Value.Tag, @enumFromInt(d[0])) == .number); |
| ... | ... | @@ -629,3 +692,15 @@ pub const NumberIndex = enum(u32) { |
| 629 | 692 | }; |
| 630 | 693 | } |
| 631 | 694 | }; |
| 695 | |
| 696 | const Space = union(enum) { |
| 697 | count: u8, |
| 698 | custom: []const u8, |
| 699 | |
| 700 | pub fn fill(s: Space) []const u8 { |
| 701 | return switch (s) { |
| 702 | .count => |c| " "[0..@min(c, 10)], |
| 703 | .custom => |f| f[0..@min(f.len, 10)], |
| 704 | }; |
| 705 | } |
| 706 | }; |