mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
Allow for union{T} like types in json.unmarshal
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package json
|
package json
|
||||||
|
|
||||||
import "core:fmt"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:reflect"
|
import "core:reflect"
|
||||||
@@ -37,7 +36,6 @@ unmarshal_any :: proc(data: []byte, v: any, spec := DEFAULT_SPECIFICATION, alloc
|
|||||||
return .Non_Pointer_Parameter
|
return .Non_Pointer_Parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if !is_valid(data, spec, true) {
|
if !is_valid(data, spec, true) {
|
||||||
return .Invalid_Data
|
return .Invalid_Data
|
||||||
}
|
}
|
||||||
@@ -47,6 +45,8 @@ unmarshal_any :: proc(data: []byte, v: any, spec := DEFAULT_SPECIFICATION, alloc
|
|||||||
if v.data == nil {
|
if v.data == nil {
|
||||||
return .Invalid_Parameter
|
return .Invalid_Parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.allocator = p.allocator
|
||||||
return unmarsal_value(&p, data)
|
return unmarsal_value(&p, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,11 +64,11 @@ unmarshal_string :: proc(data: string, ptr: ^$T, spec := DEFAULT_SPECIFICATION,
|
|||||||
assign_bool :: proc(val: any, b: bool) -> bool {
|
assign_bool :: proc(val: any, b: bool) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch dst in &v {
|
||||||
case bool: dst = auto_cast b
|
case bool: dst = bool(b)
|
||||||
case b8: dst = auto_cast b
|
case b8: dst = b8 (b)
|
||||||
case b16: dst = auto_cast b
|
case b16: dst = b16 (b)
|
||||||
case b32: dst = auto_cast b
|
case b32: dst = b32 (b)
|
||||||
case b64: dst = auto_cast b
|
case b64: dst = b64 (b)
|
||||||
case: return false
|
case: return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -77,35 +77,35 @@ assign_bool :: proc(val: any, b: bool) -> bool {
|
|||||||
assign_int :: proc(val: any, i: $T) -> bool {
|
assign_int :: proc(val: any, i: $T) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch dst in &v {
|
||||||
case i8: dst = auto_cast i
|
case i8: dst = i8 (i)
|
||||||
case i16: dst = auto_cast i
|
case i16: dst = i16 (i)
|
||||||
case i16le: dst = auto_cast i
|
case i16le: dst = i16le (i)
|
||||||
case i16be: dst = auto_cast i
|
case i16be: dst = i16be (i)
|
||||||
case i32: dst = auto_cast i
|
case i32: dst = i32 (i)
|
||||||
case i32le: dst = auto_cast i
|
case i32le: dst = i32le (i)
|
||||||
case i32be: dst = auto_cast i
|
case i32be: dst = i32be (i)
|
||||||
case i64: dst = auto_cast i
|
case i64: dst = i64 (i)
|
||||||
case i64le: dst = auto_cast i
|
case i64le: dst = i64le (i)
|
||||||
case i64be: dst = auto_cast i
|
case i64be: dst = i64be (i)
|
||||||
case i128: dst = auto_cast i
|
case i128: dst = i128 (i)
|
||||||
case i128le: dst = auto_cast i
|
case i128le: dst = i128le (i)
|
||||||
case i128be: dst = auto_cast i
|
case i128be: dst = i128be (i)
|
||||||
case u8: dst = auto_cast i
|
case u8: dst = u8 (i)
|
||||||
case u16: dst = auto_cast i
|
case u16: dst = u16 (i)
|
||||||
case u16le: dst = auto_cast i
|
case u16le: dst = u16le (i)
|
||||||
case u16be: dst = auto_cast i
|
case u16be: dst = u16be (i)
|
||||||
case u32: dst = auto_cast i
|
case u32: dst = u32 (i)
|
||||||
case u32le: dst = auto_cast i
|
case u32le: dst = u32le (i)
|
||||||
case u32be: dst = auto_cast i
|
case u32be: dst = u32be (i)
|
||||||
case u64: dst = auto_cast i
|
case u64: dst = u64 (i)
|
||||||
case u64le: dst = auto_cast i
|
case u64le: dst = u64le (i)
|
||||||
case u64be: dst = auto_cast i
|
case u64be: dst = u64be (i)
|
||||||
case u128: dst = auto_cast i
|
case u128: dst = u128 (i)
|
||||||
case u128le: dst = auto_cast i
|
case u128le: dst = u128le (i)
|
||||||
case u128be: dst = auto_cast i
|
case u128be: dst = u128be (i)
|
||||||
case int: dst = auto_cast i
|
case int: dst = int (i)
|
||||||
case uint: dst = auto_cast i
|
case uint: dst = uint (i)
|
||||||
case uintptr: dst = auto_cast i
|
case uintptr: dst = uintptr(i)
|
||||||
case: return false
|
case: return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -114,15 +114,15 @@ assign_int :: proc(val: any, i: $T) -> bool {
|
|||||||
assign_float :: proc(val: any, i: $T) -> bool {
|
assign_float :: proc(val: any, i: $T) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch dst in &v {
|
||||||
case f16: dst = auto_cast i
|
case f16: dst = f16 (i)
|
||||||
case f16le: dst = auto_cast i
|
case f16le: dst = f16le(i)
|
||||||
case f16be: dst = auto_cast i
|
case f16be: dst = f16be(i)
|
||||||
case f32: dst = auto_cast i
|
case f32: dst = f32 (i)
|
||||||
case f32le: dst = auto_cast i
|
case f32le: dst = f32le(i)
|
||||||
case f32be: dst = auto_cast i
|
case f32be: dst = f32be(i)
|
||||||
case f64: dst = auto_cast i
|
case f64: dst = f64 (i)
|
||||||
case f64le: dst = auto_cast i
|
case f64le: dst = f64le(i)
|
||||||
case f64be: dst = auto_cast i
|
case f64be: dst = f64be(i)
|
||||||
case: return false
|
case: return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -133,11 +133,24 @@ assign_float :: proc(val: any, i: $T) -> bool {
|
|||||||
@(private)
|
@(private)
|
||||||
unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
||||||
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
|
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
|
||||||
|
|
||||||
token := 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 !(u.maybe && reflect.is_pointer(variant)) {
|
||||||
|
tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id}
|
||||||
|
assign_int(tag, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#partial switch token.kind {
|
#partial switch token.kind {
|
||||||
case .Null:
|
case .Null:
|
||||||
ti := type_info_of(v.id)
|
|
||||||
mem.zero(v.data, ti.size)
|
mem.zero(v.data, ti.size)
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
return
|
return
|
||||||
@@ -175,7 +188,7 @@ unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
|||||||
case .String:
|
case .String:
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
str := unquote_string(token, p.spec, p.allocator) or_return
|
str := unquote_string(token, p.spec, p.allocator) or_return
|
||||||
val := reflect.any_base(v)
|
val := any{v.data, ti.id}
|
||||||
switch dst in &val {
|
switch dst in &val {
|
||||||
case string:
|
case string:
|
||||||
dst = str
|
dst = str
|
||||||
@@ -191,7 +204,6 @@ unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
|||||||
}
|
}
|
||||||
defer delete(str, p.allocator)
|
defer delete(str, p.allocator)
|
||||||
|
|
||||||
ti := type_info_of(val.id)
|
|
||||||
#partial switch variant in ti.variant {
|
#partial switch variant in ti.variant {
|
||||||
case reflect.Type_Info_Enum:
|
case reflect.Type_Info_Enum:
|
||||||
for name, i in variant.names {
|
for name, i in variant.names {
|
||||||
@@ -280,7 +292,6 @@ unmarsal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_locat
|
|||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
unmarsal_object :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
unmarsal_object :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
||||||
original_val := v
|
|
||||||
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
|
UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token}
|
||||||
|
|
||||||
assert(expect_token(p, .Open_Brace) == nil)
|
assert(expect_token(p, .Open_Brace) == nil)
|
||||||
@@ -374,11 +385,7 @@ unmarsal_object :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
|||||||
|
|
||||||
map_backing_value := any{raw_data(elem_backing), t.value.id}
|
map_backing_value := any{raw_data(elem_backing), t.value.id}
|
||||||
|
|
||||||
pass := 0
|
|
||||||
|
|
||||||
map_loop: for p.curr_token.kind != .Close_Brace {
|
map_loop: for p.curr_token.kind != .Close_Brace {
|
||||||
defer pass += 1
|
|
||||||
|
|
||||||
key, _ := parse_object_key(p, p.allocator)
|
key, _ := parse_object_key(p, p.allocator)
|
||||||
unmarsal_expect_token(p, .Colon)
|
unmarsal_expect_token(p, .Colon)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user