Skip to content

Add pretty printing #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions json.c3
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ macro from_str($Type, Allocator alloc, String s) {
return deserialize::parse($Type, alloc, &lex);
}

macro String? to_json(expr, Allocator alloc) {
macro String? to_json(expr, Allocator alloc, bool pretty = false, int spaces = 4) {
@pool() {
DString s;
s.tinit();
serialize::add_json(expr, &s)!;
serialize::add_json(expr, &s, pretty, spaces)!;
return s.copy_str(alloc);
};
}
86 changes: 73 additions & 13 deletions serialize.c3
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module json::serialize;
import std::core;

macro void? add_json(src, DString* dest) {
macro void? add_json(src, DString* dest, bool pretty = false, int spaces = 4, int indent = 0) {
$if ($defined($typeof(src).to_json)):
src.to_json(dest)!;
src.to_json(dest, pretty, spaces, indent)!;
return;
$endif

Expand Down Expand Up @@ -40,20 +40,22 @@ macro void? add_json(src, DString* dest) {
// Check Maybe first
$if ($typeof(src).nameof == "Maybe"):
if (src.has_value) {
add_json(src.$eval($typeof(src).membersof[0].nameof), dest)!!;
add_json(src.$eval($typeof(src).membersof[0].nameof), dest, pretty, spaces, indent)!!;
} else {
dest.appendf("null");
}
return;
$endif

$if ($typeof(src).nameof == "HashMap"):
add_hashmap(src, dest)!!;
add_hashmap(src, dest, pretty, spaces, indent)!!;
return;
$endif

// Not Maybe, just regular struct
dest.append("{");
if (pretty) dest.append("\n");
indent++;
int members_written;
$foreach $member : $typeof(src).membersof:
$if ($member.kindof == TypeKind.UNION):
Expand All @@ -76,33 +78,79 @@ macro void? add_json(src, DString* dest) {
} else {
if (members_written > 0) {
dest.append(",");
if (pretty) dest.append("\n");
}
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
dest.appendf(`"%s":`, $member.nameof);
add_json(src.$eval($member.nameof), dest)!!;
if (pretty) dest.append(" ");
add_json(src.$eval($member.nameof), dest, pretty, spaces, indent)!!;
members_written += 1;
}
$else
if (members_written > 0) {
dest.append(",");
if (pretty) dest.append("\n");
}
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
dest.appendf(`"%s":`, $member.nameof);
add_json(src.$eval($member.nameof), dest)!!;
if (pretty) dest.append(" ");
add_json(src.$eval($member.nameof), dest, pretty, spaces, indent)!!;
members_written += 1;
$endif
$endif
$endforeach
dest.append("}");
if (pretty) dest.append("\n");
indent--;
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
dest.append("}");
return;
$case TypeKind.SLICE:
dest.append("[");
if (pretty) dest.append("\n");
indent++;
foreach (idx, element : src) {
if (idx > 0) {
dest.append(",");
if (pretty) dest.append("\n");
}
add_json(element, dest)!!;
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
add_json(element, dest, pretty, spaces, indent)!!;
}
dest.append("]");
return;
if (pretty) dest.append("\n");
indent--;
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
dest.append("]");
return;
$case TypeKind.UNION:
return UNION_NOT_SUPPORTED?;
$endswitch
Expand All @@ -112,12 +160,13 @@ macro void? add_json(src, DString* dest) {

// Using iter; with the @each_entry, didn't like using var
// in the macro body call.
macro void? add_hashmap(src, DString* dest) {
macro void? add_hashmap(src, DString* dest, bool pretty, int spaces, int indent) {
$if ($typeof(src).nameof != "HashMap"):
return EXPECTED_HASHMAP?;
$endif

dest.append("{");
if (pretty) dest.append("\n");
usz idx;
var iter = src.iter();
while (idx < iter.len()) {
Expand All @@ -126,13 +175,24 @@ macro void? add_hashmap(src, DString* dest) {
var value = entry.value;
if (idx > 0) {
dest.append(",");
if (pretty) dest.append("\n");
}
add_json(key, dest)!;
if (pretty)
{
for (int i = 0; i < indent * spaces; i++)
{
dest.append(" ");
}
}
add_json(key, dest, pretty, spaces, indent)!;
dest.append(":");
add_json(value, dest)!;
if (pretty) dest.append(" ");
add_json(value, dest, pretty, spaces, indent)!;
idx += 1;
};
if (pretty) dest.append("\n");
dest.append("}");
if (pretty) dest.append("\n");
}

faultdef UNION_NOT_SUPPORTED, EXPECTED_HASHMAP;
13 changes: 10 additions & 3 deletions serialize_test.c3
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ struct Foo {

fn void test_struct() @test {
Foo foo = { .is_bar = true, .baz = 1 };
test::eq(json::to_json(foo, allocator::temp())!!, `{"is_bar":true,"baz":1}`);
test::eq(json::to_json(foo, allocator::temp())!!, `{"is_bar":true,"baz":1}`);
}

struct Complex
{
String s;
String[] s1;
Foo[] f;
}

fn void test_array() @test {
Expand Down Expand Up @@ -94,9 +101,9 @@ struct StructWithUnionCustom {
Foo foo;
}
}
fn void? StructWithUnionCustom.to_json(self, DString* dest) {
fn void? StructWithUnionCustom.to_json(self, DString* dest, bool pretty, int spaces, int indent) {
// Unions not supported, must handle each variant manually
serialize::add_json(self.foo, dest)!;
serialize::add_json(self.foo, dest, pretty, spaces, indent)!;
}
fn void test_struct_with_union_custom() @test {
StructWithUnionCustom s = { .foo = { .is_bar = true} };
Expand Down