Check for more errors in json.unmarshal

This commit is contained in:
gingerBill
2024-12-01 11:54:54 +11:00
committed by flysand7
parent 95731aceac
commit 6963b0f3f2
+34 -15
View File
@@ -172,20 +172,33 @@ assign_float :: proc(val: any, f: $T) -> bool {
@(private) @(private)
unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool { unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> (ok: bool, err: Error) {
val := val val := val
switch &dst in val { switch &dst in val {
case string: case string:
dst = str dst = str
return true return true, nil
case cstring: case cstring:
if str == "" { if str == "" {
dst = strings.clone_to_cstring("", p.allocator) a_err: runtime.Allocator_Error
dst, a_err = strings.clone_to_cstring("", p.allocator)
#partial switch a_err {
case nil:
// okay
case .Out_Of_Memory:
err = .Out_Of_Memory
case:
err = .Invalid_Allocator
}
if err != nil {
return
}
} else { } else {
// NOTE: This is valid because 'clone_string' appends a NUL terminator // NOTE: This is valid because 'clone_string' appends a NUL terminator
dst = cstring(raw_data(str)) dst = cstring(raw_data(str))
} }
return true ok = true
return
} }
#partial switch variant in ti.variant { #partial switch variant in ti.variant {
@@ -193,31 +206,37 @@ unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.T
for name, i in variant.names { for name, i in variant.names {
if name == str { if name == str {
assign_int(val, variant.values[i]) assign_int(val, variant.values[i])
return true return true, nil
} }
} }
// TODO(bill): should this be an error or not? // TODO(bill): should this be an error or not?
return true return true, nil
case reflect.Type_Info_Integer: case reflect.Type_Info_Integer:
i := strconv.parse_i128(str) or_return i, pok := strconv.parse_i128(str)
if !pok {
return false, nil
}
if assign_int(val, i) { if assign_int(val, i) {
return true return true, nil
} }
if assign_float(val, i) { if assign_float(val, i) {
return true return true, nil
} }
case reflect.Type_Info_Float: case reflect.Type_Info_Float:
f := strconv.parse_f64(str) or_return f, pok := strconv.parse_f64(str)
if !pok {
return false, nil
}
if assign_int(val, f) { if assign_int(val, f) {
return true return true, nil
} }
if assign_float(val, f) { if assign_float(val, f) {
return true return true, nil
} }
} }
return false return false, nil
} }
@@ -304,7 +323,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
case .Ident: case .Ident:
advance_token(p) advance_token(p)
if p.spec == .MJSON { if p.spec == .MJSON {
if unmarshal_string_token(p, any{v.data, ti.id}, token.text, ti) { if unmarshal_string_token(p, any{v.data, ti.id}, token.text, ti) or_return {
return nil return nil
} }
} }
@@ -314,7 +333,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
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
dest := any{v.data, ti.id} dest := any{v.data, ti.id}
if !unmarshal_string_token(p, dest, str, ti) { if !(unmarshal_string_token(p, dest, str, ti) or_return) {
delete(str, p.allocator) delete(str, p.allocator)
return UNSUPPORTED_TYPE return UNSUPPORTED_TYPE
} }