From 8c10f4cdde2a796d2480703a16c8a34cfee5375f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 3 Jan 2024 19:02:30 +0100 Subject: [PATCH] encoding/json: try to unmarshal into union variants --- core/encoding/json/unmarshal.odin | 37 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index 678f2dcfa..afcc43c0c 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -201,20 +201,37 @@ unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.T unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token} token := p.curr_token - + v := v ti := reflect.type_info_base(type_info_of(v.id)) - // NOTE: If it's a union with only one variant, then treat it as that variant - if u, ok := ti.variant.(reflect.Type_Info_Union); ok && len(u.variants) == 1 && token.kind != .Null { - variant := u.variants[0] - v.id = variant.id - ti = reflect.type_info_base(variant) - if !reflect.is_pointer_internally(variant) { - tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} - assign_int(tag, 1) + if u, ok := ti.variant.(reflect.Type_Info_Union); ok && token.kind != .Null { + // NOTE: If it's a union with only one variant, then treat it as that variant + if len(u.variants) == 1 { + variant := u.variants[0] + v.id = variant.id + ti = reflect.type_info_base(variant) + if !reflect.is_pointer_internally(variant) { + tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} + assign_int(tag, 1) + } + } else if v.id != Value { + for variant, i in u.variants { + variant_any := any{v.data, variant.id} + variant_p := p^ + if err = unmarshal_value(&variant_p, variant_any); err == nil { + p^ = variant_p + + raw_tag := i + if !u.no_nil { raw_tag += 1 } + tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id} + assign_int(tag, raw_tag) + return + } + } + return UNSUPPORTED_TYPE } } - + switch &dst in v { // Handle json.Value as an unknown type case Value: