diff --git a/tests.jai b/tests.jai index 03d6125..ec4730b 100644 --- a/tests.jai +++ b/tests.jai @@ -229,6 +229,52 @@ main :: () { } log("Report after complex stuff:"); + report_memory_leaks(); + + { + // Variant parsing + JSON :: #string EOF + { + "val1": 5, + "val2": 10, + "val3": 20, + "val4": "Hello,", + "val5": "World!" + } + EOF + + Variant1 :: #type int; + Variant2 :: #type,isa u8; + Variant3 :: #type,distinct s16; + Variant4 :: #type string; + Variant5 :: #type,distinct Variant4; + + Parse_Struct :: struct { + val1: Variant1; + val2: Variant2; + val3: Variant3; + + val4: Variant4; + val5: Variant5; + } + + success, result := json_parse_string(JSON, Parse_Struct); + assert(success); + assert(result.val1 == 5 && result.val2 == 10 && result.val3 == 20); + assert(result.val4 == "Hello," && result.val5 == "World!"); + + free(result.val4); + free(result.val5.data); + + // Variant writing + sb: String_Builder; + x: Variant5 = "Hello!"; // 2-level deep variant of string + json_write_native(*sb, *x, type_info(type_of(x)), indent_char="", float_handling=.SUPPORT_NULL); + + json := builder_to_string(*sb,, temp); + assert(json == "\"Hello!\"", json); + } + log("Report after variant parsing and writing:"); report_memory_leaks(); for 0..200 { diff --git a/typed.jai b/typed.jai index a50ee81..9b67ca8 100644 --- a/typed.jai +++ b/typed.jai @@ -37,6 +37,9 @@ json_parse_file :: (filename: string, $T: Type, ignore_unknown := true, rename : } json_write_native :: (builder: *String_Builder, data: *void, info: *Type_Info, indent_char := "\t", ignore := ignore_by_note, rename := rename_by_note, float_handling: Special_Float_Handling, level := 0) { + + info = variant_to_base_type_info(info); + if info.type == { case .BOOL; append(builder, ifx (.*)(cast(*bool) data) "true" else "false"); @@ -133,6 +136,18 @@ json_write_native :: (builder: *String_Builder, data: *void, info: *Type_Info, i #scope_file +variant_to_base_type_info :: inline (info: *Type_Info) -> *Type_Info { + + // Info can be null sometimes so make sure before checking type + if !info return null; + + while info.type == .VARIANT { + info = info.(*Type_Info_Variant).variant_of; + } + + return info; +} + json_write_native_members :: (builder: *String_Builder, data: *void, members: [] Type_Info_Struct_Member, indent_char := "\t", ignore := ignore_by_note, rename: Rename_Proc, float_handling: Special_Float_Handling, level := 0, first: *bool) { for * member: members { if member.flags & .CONSTANT continue; @@ -174,10 +189,13 @@ is_generic_json_value :: (info: *Type_Info) -> bool { } parse_value :: (to_parse: string, slot: *u8, info: *Type_Info, ignore_unknown: bool, field_name: string, rename: Rename_Proc, float_handling: Special_Float_Handling) -> remainder: string, success: bool { + remainder := trim_left(to_parse, WHITESPACE_CHARS); if !remainder return "", false; success := true; + info = variant_to_base_type_info(info); + prepare_slot :: (expected_type: Type_Info_Tag, info: *Type_Info, slot: *u8, to_parse: string) -> *u8, success: bool, is_generic: bool, info: *Type_Info { value_info := info; if info.type == .POINTER {