x.json2.decoder: support sumtypes fully (#22694)

This commit is contained in:
Hitalo Souza 2024-10-30 03:01:39 -04:00 committed by GitHub
parent 6e9a66dbf3
commit 54a6915f02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 214 additions and 63 deletions

View file

@ -549,19 +549,6 @@ pub fn decode[T](val string) !T {
return result
}
fn (mut decoder Decoder) get_decoded_sumtype_workaround[T](initialized_sumtype T) !T {
$if initialized_sumtype is $sumtype {
$for v in initialized_sumtype.variants {
if initialized_sumtype is v {
mut val := initialized_sumtype
decoder.decode_value(mut val)!
return T(val)
}
}
}
return initialized_sumtype
}
// decode_value decodes a value from the JSON nodes.
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
$if T is $option {
@ -620,38 +607,7 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
val = string_buffer.bytestr()
}
} $else $if T.unaliased_typ is $sumtype {
value_info := decoder.current_node.value
$for v in val.variants {
if value_info.value_kind == .string_ {
$if v.typ in [string, time.Time] {
val = T(v)
}
} else if value_info.value_kind == .number {
$if v.typ in [$float, $int, $enum] {
val = T(v)
}
} else if value_info.value_kind == .boolean {
$if v.typ is bool {
val = T(v)
}
} else if value_info.value_kind == .object {
$if v.typ is $map {
val = T(v)
} $else $if v.typ is $struct {
// Will only be supported when json object has field "_type"
error('cannot encode value with ${typeof(val).name} type')
}
} else if value_info.value_kind == .array {
$if v.typ is $array {
val = T(v)
}
}
}
decoded_sumtype := decoder.get_decoded_sumtype_workaround(val)!
unsafe {
*val = decoded_sumtype
}
decoder.decode_sumtype(mut val)!
} $else $if T.unaliased_typ is time.Time {
time_info := decoder.current_node.value
@ -768,7 +724,7 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! {
unsafe {
val = vmemcmp(decoder.json.str + value_info.position, 'true'.str, 4) == 0
}
} $else $if T.unaliased_typ in [$int, $float, $enum] {
} $else $if T.unaliased_typ in [$float, $int, $enum] {
value_info := decoder.current_node.value
if value_info.value_kind == .number {
@ -953,7 +909,7 @@ pub fn string_buffer_to_generic_number[T](result &T, data []u8) {
} $else $if T.unaliased_typ is $float {
mut is_negative := false
mut decimal_seen := false
mut decimal_divider := int(1)
mut decimal_divider := T(1)
for ch in data {
if ch == `-` {
@ -965,13 +921,13 @@ pub fn string_buffer_to_generic_number[T](result &T, data []u8) {
continue
}
digit := T(ch - `0`)
digit := T(ch - u8(`0`))
if decimal_seen {
decimal_divider *= 10
*result += T(digit / decimal_divider)
} else {
*result = *result * 10 + digit
*result = T(*result * 10 + digit)
}
}
if is_negative {