mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
x.json2.decoder: support sumtypes fully (#22694)
This commit is contained in:
parent
6e9a66dbf3
commit
54a6915f02
6 changed files with 214 additions and 63 deletions
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue