mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
json: make enums work with json encode+decode (serialised as string names by default; the old integer one is supported too, using [json_as_number]
) (#17696)
This commit is contained in:
parent
c9345be6de
commit
278e747c7a
134
vlib/json/json_encode_enum_test.v
Normal file
134
vlib/json/json_encode_enum_test.v
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
[json_as_number]
|
||||||
|
pub enum MessageType {
|
||||||
|
error = 1
|
||||||
|
warning = 2
|
||||||
|
info = 3
|
||||||
|
log = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MessageType2 {
|
||||||
|
error = 1
|
||||||
|
warning = 2
|
||||||
|
info = 3
|
||||||
|
log = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TestEnum {
|
||||||
|
one = 1
|
||||||
|
two
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestAlias = TestEnum
|
||||||
|
type TestSum = TestEnum | string
|
||||||
|
type TestSum2 = MessageType | string
|
||||||
|
type TestAliasAttr = MessageType
|
||||||
|
|
||||||
|
struct TestStruct {
|
||||||
|
test []TestEnum
|
||||||
|
test2 TestEnum
|
||||||
|
test3 TestAlias
|
||||||
|
test4 TestSum
|
||||||
|
test5 MessageType
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestStruct2 {
|
||||||
|
a TestAliasAttr
|
||||||
|
b TestSum2
|
||||||
|
c TestSum2
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test {
|
||||||
|
ab ?int
|
||||||
|
a ?MessageType
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test2 {
|
||||||
|
a ?MessageType2
|
||||||
|
}
|
||||||
|
|
||||||
|
type TSum = MessageType | string
|
||||||
|
type TSum2 = MessageType2 | string
|
||||||
|
|
||||||
|
struct Test3 {
|
||||||
|
a ?TSum
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test4 {
|
||||||
|
a ?TSum2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_with_enum() {
|
||||||
|
out := json.encode(TestStruct{
|
||||||
|
test: [TestEnum.one, TestEnum.one]
|
||||||
|
test2: TestEnum.two
|
||||||
|
test3: TestEnum.one
|
||||||
|
test4: TestEnum.two
|
||||||
|
test5: .log
|
||||||
|
})
|
||||||
|
assert out == '{"test":["one","one"],"test2":"two","test3":"one","test4":"two","test5":4}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_direct_enum() {
|
||||||
|
assert json.encode(TestEnum.one) == '"one"'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_alias_and_sumtype() {
|
||||||
|
assert json.decode(TestStruct, '{"test":["one","one"],"test2":"two","test3": "one", "test4": "two", "test5":4}')! == TestStruct{
|
||||||
|
test: [.one, .one]
|
||||||
|
test2: .two
|
||||||
|
test3: TestAlias(.one)
|
||||||
|
test4: TestSum('two')
|
||||||
|
test5: .log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_enum_attr() {
|
||||||
|
assert dump(json.encode(MessageType.log)) == '4'
|
||||||
|
assert dump(json.encode(MessageType.error)) == '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_enum_attr_decode() {
|
||||||
|
assert json.decode(TestStruct2, '{"a": 1, "b":4, "c": "test"}')! == TestStruct2{
|
||||||
|
a: .error
|
||||||
|
b: MessageType.log
|
||||||
|
c: 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_enum_attr_encode() {
|
||||||
|
assert json.encode(TestStruct2{
|
||||||
|
a: .error
|
||||||
|
b: MessageType.log
|
||||||
|
c: 'test'
|
||||||
|
}) == '{"a":1,"b":4,"c":"test"}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_option_enum() {
|
||||||
|
assert dump(json.encode(Test{none, none})) == '{}'
|
||||||
|
assert dump(json.encode(Test{none, MessageType.log})) == '{"a":4}'
|
||||||
|
t := dump(json.decode(Test, '{"a":4}')!)
|
||||||
|
assert t.ab == none
|
||||||
|
assert t.a? == .log
|
||||||
|
|
||||||
|
t2 := dump(json.decode(Test, '{"a":null}')!)
|
||||||
|
assert t2.a == none
|
||||||
|
|
||||||
|
assert json.encode(Test2{none}) == '{}'
|
||||||
|
assert dump(json.encode(Test2{MessageType2.log})) == '{"a":"log"}'
|
||||||
|
z := dump(json.decode(Test2, '{"a":"log"}')!)
|
||||||
|
assert z.a? == .log
|
||||||
|
a := dump(json.decode(Test2, '{"a": null}')!)
|
||||||
|
assert a.a == none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_option_sumtype_enum() {
|
||||||
|
assert dump(json.encode(Test3{none})) == '{}'
|
||||||
|
assert dump(json.encode(Test3{ a: 'foo' })) == '{"a":"foo"}'
|
||||||
|
assert dump(json.encode(Test3{ a: MessageType.warning })) == '{"a":2}'
|
||||||
|
|
||||||
|
assert dump(json.encode(Test4{none})) == '{}'
|
||||||
|
assert dump(json.encode(Test4{ a: 'foo' })) == '{"a":"foo"}'
|
||||||
|
assert dump(json.encode(Test4{ a: MessageType2.warning })) == '{"a":"warning"}'
|
||||||
|
}
|
@ -18,7 +18,7 @@ fn test_simple() {
|
|||||||
x := Employee{'Peter', 28, 95000.5, .worker}
|
x := Employee{'Peter', 28, 95000.5, .worker}
|
||||||
s := json.encode(x)
|
s := json.encode(x)
|
||||||
// eprintln('Employee x: $s')
|
// eprintln('Employee x: $s')
|
||||||
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
|
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":"worker"}'
|
||||||
y := json.decode(Employee, s)!
|
y := json.decode(Employee, s)!
|
||||||
// eprintln('Employee y: $y')
|
// eprintln('Employee y: $y')
|
||||||
assert y.name == 'Peter'
|
assert y.name == 'Peter'
|
||||||
@ -95,14 +95,15 @@ fn test_encode_decode_sumtype() {
|
|||||||
enc := json.encode(game)
|
enc := json.encode(game)
|
||||||
// eprintln('Encoded Game: $enc')
|
// eprintln('Encoded Game: $enc')
|
||||||
|
|
||||||
assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},1,"Stool",{"_type":"Time","value":${t.unix_time()}}]}'
|
assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},"cat","Stool",{"_type":"Time","value":${t.unix_time()}}]}'
|
||||||
|
|
||||||
dec := json.decode(SomeGame, enc)!
|
dec := json.decode(SomeGame, enc)!
|
||||||
// eprintln('Decoded Game: $dec')
|
// eprintln('Decoded Game: $dec')
|
||||||
|
|
||||||
assert game.title == dec.title
|
assert game.title == dec.title
|
||||||
assert game.player == dec.player
|
assert game.player == dec.player
|
||||||
assert (game.other[2] as Animal) == (dec.other[2] as Animal)
|
assert (game.other[2] as Animal) == .cat
|
||||||
|
assert dec.other[2] == Entity('cat')
|
||||||
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time()
|
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6144,16 +6144,21 @@ fn (mut g Gen) size_of(node ast.SizeOf) {
|
|||||||
g.write('sizeof(${util.no_dots(styp)})')
|
g.write('sizeof(${util.no_dots(styp)})')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) enum_val(node ast.EnumVal) {
|
[inline]
|
||||||
styp := g.typ(g.table.unaliased_type(node.typ))
|
fn (mut g Gen) gen_enum_prefix(typ ast.Type) string {
|
||||||
if g.pref.translated && node.typ.is_number() {
|
if g.pref.translated && typ.is_number() {
|
||||||
// Mostly in translated code, when C enums are used as ints in switches
|
// Mostly in translated code, when C enums are used as ints in switches
|
||||||
g.write('_const_main__${node.val}')
|
return '_const_main__'
|
||||||
} else {
|
} else {
|
||||||
g.write('${styp}__${node.val}')
|
styp := g.typ(g.table.unaliased_type(typ))
|
||||||
|
return '${styp}__'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) enum_val(node ast.EnumVal) {
|
||||||
|
g.write('${g.gen_enum_prefix(node.typ)}${node.val}')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) as_cast(node ast.AsCast) {
|
fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||||
// Make sure the sum type can be cast to this type (the types
|
// Make sure the sum type can be cast to this type (the types
|
||||||
// are the same), otherwise panic.
|
// are the same), otherwise panic.
|
||||||
|
@ -26,7 +26,7 @@ import strings
|
|||||||
fn (mut g Gen) gen_json_for_type(typ ast.Type) {
|
fn (mut g Gen) gen_json_for_type(typ ast.Type) {
|
||||||
utyp := g.unwrap_generic(typ)
|
utyp := g.unwrap_generic(typ)
|
||||||
sym := g.table.sym(utyp)
|
sym := g.table.sym(utyp)
|
||||||
if (is_js_prim(sym.name) && !utyp.has_flag(.option)) || sym.kind == .enum_ {
|
if is_js_prim(sym.name) && !utyp.has_flag(.option) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.json_types << utyp
|
g.json_types << utyp
|
||||||
@ -145,9 +145,11 @@ ${enc_fn_dec} {
|
|||||||
g.gen_json_for_type(parent_typ)
|
g.gen_json_for_type(parent_typ)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
enc.writeln('\to = cJSON_CreateObject();')
|
|
||||||
if psym.info is ast.Struct {
|
if psym.info is ast.Struct {
|
||||||
|
enc.writeln('\to = cJSON_CreateObject();')
|
||||||
g.gen_struct_enc_dec(utyp, psym.info, ret_styp, mut enc, mut dec)
|
g.gen_struct_enc_dec(utyp, psym.info, ret_styp, mut enc, mut dec)
|
||||||
|
} else if psym.kind == .enum_ {
|
||||||
|
g.gen_enum_enc_dec(utyp, psym, mut enc, mut dec)
|
||||||
} else if psym.kind == .sum_type {
|
} else if psym.kind == .sum_type {
|
||||||
verror('json: ${sym.name} aliased sumtypes does not work at the moment')
|
verror('json: ${sym.name} aliased sumtypes does not work at the moment')
|
||||||
} else {
|
} else {
|
||||||
@ -160,6 +162,8 @@ ${enc_fn_dec} {
|
|||||||
verror('json: ${sym.name} is not a sumtype')
|
verror('json: ${sym.name} is not a sumtype')
|
||||||
}
|
}
|
||||||
g.gen_sumtype_enc_dec(utyp, sym, mut enc, mut dec, ret_styp)
|
g.gen_sumtype_enc_dec(utyp, sym, mut enc, mut dec, ret_styp)
|
||||||
|
} else if sym.kind == .enum_ {
|
||||||
|
g.gen_enum_enc_dec(utyp, sym, mut enc, mut dec)
|
||||||
} else if utyp.has_flag(.option) && sym.info !is ast.Struct {
|
} else if utyp.has_flag(.option) && sym.info !is ast.Struct {
|
||||||
g.gen_option_enc_dec(utyp, mut enc, mut dec)
|
g.gen_option_enc_dec(utyp, mut enc, mut dec)
|
||||||
} else {
|
} else {
|
||||||
@ -183,6 +187,73 @@ ${enc_fn_dec} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut g Gen) gen_enum_to_str(utyp ast.Type, sym ast.TypeSymbol, enum_var string, result_var string, ident string, mut enc strings.Builder) {
|
||||||
|
enum_prefix := g.gen_enum_prefix(utyp.clear_flag(.option))
|
||||||
|
enc.writeln('${ident}switch (${enum_var}) {')
|
||||||
|
for val in (sym.info as ast.Enum).vals {
|
||||||
|
enc.write_string('${ident}\tcase ${enum_prefix}${val}:\t')
|
||||||
|
enc.writeln('${result_var} = json__encode_string(_SLIT("${val}")); break;')
|
||||||
|
}
|
||||||
|
enc.writeln('${ident}}')
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut g Gen) gen_str_to_enum(utyp ast.Type, sym ast.TypeSymbol, val_var string, result_var string, ident string, mut dec strings.Builder) {
|
||||||
|
enum_prefix := g.gen_enum_prefix(utyp.clear_flag(.option))
|
||||||
|
is_option := utyp.has_flag(.option)
|
||||||
|
for k, val in (sym.info as ast.Enum).vals {
|
||||||
|
if k == 0 {
|
||||||
|
dec.write_string('${ident}if (string__eq(_SLIT("${val}"), ${val_var}))\t')
|
||||||
|
} else {
|
||||||
|
dec.write_string('${ident}else if (string__eq(_SLIT("${val}"), ${val_var}))\t')
|
||||||
|
}
|
||||||
|
if is_option {
|
||||||
|
base_typ := g.base_type(utyp)
|
||||||
|
dec.writeln('_option_ok(&(${base_typ}[]){ ${enum_prefix}${val} }, ${result_var}, sizeof(${base_typ}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('${result_var} = ${enum_prefix}${val};')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut g Gen) is_enum_as_int(sym ast.TypeSymbol) bool {
|
||||||
|
if enum_decl := g.table.enum_decls[sym.name] {
|
||||||
|
if _ := enum_decl.attrs.find_first('json_as_number') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut g Gen) gen_enum_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc strings.Builder, mut dec strings.Builder) {
|
||||||
|
is_option := utyp.has_flag(.option)
|
||||||
|
|
||||||
|
if g.is_enum_as_int(sym) {
|
||||||
|
if is_option {
|
||||||
|
base_typ := g.typ(utyp.clear_flag(.option))
|
||||||
|
enc.writeln('\to = ${js_enc_name('u64')}(*val.data);')
|
||||||
|
dec.writeln('\t_option_ok(&(${base_typ}[]){ ${js_dec_name('u64')}(root) }, &res, sizeof(${base_typ}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('\tres = ${js_dec_name('u64')}(root);')
|
||||||
|
enc.writeln('\to = ${js_enc_name('u64')}(val);')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
dec.writeln('\tstring ${tmp} = ${js_dec_name('string')}(root);')
|
||||||
|
if is_option {
|
||||||
|
g.gen_str_to_enum(utyp, sym, tmp, '&res', '\t', mut dec)
|
||||||
|
g.gen_enum_to_str(utyp, sym, '*(${g.base_type(utyp)}*)val.data', 'o', '\t\t', mut
|
||||||
|
enc)
|
||||||
|
} else {
|
||||||
|
g.gen_str_to_enum(utyp, sym, tmp, 'res', '\t', mut dec)
|
||||||
|
g.gen_enum_to_str(utyp, sym, 'val', 'o', '\t', mut enc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec strings.Builder) {
|
fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec strings.Builder) {
|
||||||
enc.writeln('\tif (val.state == 2) {')
|
enc.writeln('\tif (val.state == 2) {')
|
||||||
@ -191,6 +262,9 @@ fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec
|
|||||||
type_str := g.typ(typ.clear_flag(.option))
|
type_str := g.typ(typ.clear_flag(.option))
|
||||||
encode_name := js_enc_name(type_str)
|
encode_name := js_enc_name(type_str)
|
||||||
enc.writeln('\to = ${encode_name}(*(${type_str}*)val.data);')
|
enc.writeln('\to = ${encode_name}(*(${type_str}*)val.data);')
|
||||||
|
|
||||||
|
dec_name := js_dec_name(type_str)
|
||||||
|
dec.writeln('\t_option_ok(&(${type_str}[]){ ${dec_name}(root) }, &res, sizeof(${type_str}));')
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
@ -200,6 +274,8 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||||||
typ := g.table.type_idxs[sym.name]
|
typ := g.table.type_idxs[sym.name]
|
||||||
prefix := if utyp.is_ptr() { '*' } else { '' }
|
prefix := if utyp.is_ptr() { '*' } else { '' }
|
||||||
field_op := if utyp.is_ptr() { '->' } else { '.' }
|
field_op := if utyp.is_ptr() { '->' } else { '.' }
|
||||||
|
is_option := utyp.has_flag(.option)
|
||||||
|
var_data := if is_option { '(*(${g.base_type(utyp)}*)val.data)' } else { 'val' }
|
||||||
|
|
||||||
// DECODING (inline)
|
// DECODING (inline)
|
||||||
$if !json_no_inline_sumtypes ? {
|
$if !json_no_inline_sumtypes ? {
|
||||||
@ -231,20 +307,38 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||||||
g.definitions.writeln('static inline ${sym.cname} ${variant_typ}_to_sumtype_${sym.cname}(${variant_typ}* x);')
|
g.definitions.writeln('static inline ${sym.cname} ${variant_typ}_to_sumtype_${sym.cname}(${variant_typ}* x);')
|
||||||
|
|
||||||
// ENCODING
|
// ENCODING
|
||||||
enc.writeln('\tif (val${field_op}_typ == ${variant.idx()}) {')
|
if is_option {
|
||||||
|
enc.writeln('\tif (${var_data}${field_op}_typ == ${variant.idx()}) {')
|
||||||
|
} else {
|
||||||
|
enc.writeln('\tif (val${field_op}_typ == ${variant.idx()}) {')
|
||||||
|
}
|
||||||
$if json_no_inline_sumtypes ? {
|
$if json_no_inline_sumtypes ? {
|
||||||
if variant_sym.kind == .enum_ {
|
if variant_sym.kind == .enum_ {
|
||||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('u64')}(*val${field_op}_${variant_typ}));')
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('u64')}(*${var_data}${field_op}_${variant_typ}));')
|
||||||
} else if variant_sym.name == 'time.Time' {
|
} else if variant_sym.name == 'time.Time' {
|
||||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('i64')}(val${field_op}_${variant_typ}->_v_unix));')
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('i64')}(${var_data}${field_op}_${variant_typ}->_v_unix));')
|
||||||
} else {
|
} else {
|
||||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name(variant_typ)}(*val${field_op}_${variant_typ}));')
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name(variant_typ)}(*${var_data}${field_op}_${variant_typ}));')
|
||||||
}
|
}
|
||||||
} $else {
|
} $else {
|
||||||
if is_js_prim(variant_typ) {
|
if is_js_prim(variant_typ) {
|
||||||
enc.writeln('\t\to = ${js_enc_name(variant_typ)}(*val${field_op}_${variant_typ});')
|
enc.writeln('\t\tcJSON_free(o); return ${js_enc_name(variant_typ)}(*${var_data}${field_op}_${variant_typ});')
|
||||||
} else if variant_sym.kind == .enum_ {
|
} else if variant_sym.kind == .enum_ {
|
||||||
enc.writeln('\t\to = ${js_enc_name('u64')}(*val${field_op}_${variant_typ});')
|
if g.is_enum_as_int(variant_sym) {
|
||||||
|
enc.writeln('\t\tcJSON_free(o); return ${js_enc_name('u64')}(*${var_data}${field_op}_${variant_typ});')
|
||||||
|
} else {
|
||||||
|
enc.writeln('\t\tcJSON_free(o);')
|
||||||
|
tmp2 := g.new_tmp_var()
|
||||||
|
if utyp.has_flag(.option) {
|
||||||
|
enc.writeln('\t\tu64 ${tmp2} = *${var_data}${field_op}_${variant_typ};')
|
||||||
|
g.gen_enum_to_str(variant, variant_sym, tmp2, 'o', '\t\t', mut
|
||||||
|
enc)
|
||||||
|
} else {
|
||||||
|
enc.writeln('\t\tu64 ${tmp2} = *${var_data}${field_op}_${variant_typ};')
|
||||||
|
g.gen_enum_to_str(variant, variant_sym, tmp2, 'o', '\t\t', mut
|
||||||
|
enc)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if variant_sym.name == 'time.Time' {
|
} else if variant_sym.name == 'time.Time' {
|
||||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "_type", cJSON_CreateString("${unmangled_variant_name}"));')
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "_type", cJSON_CreateString("${unmangled_variant_name}"));')
|
||||||
enc.writeln('\t\tcJSON_AddItemToObject(o, "value", ${js_enc_name('i64')}(val${field_op}_${variant_typ}->_v_unix));')
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "value", ${js_enc_name('i64')}(val${field_op}_${variant_typ}->_v_unix));')
|
||||||
@ -260,25 +354,38 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||||||
$if json_no_inline_sumtypes ? {
|
$if json_no_inline_sumtypes ? {
|
||||||
dec.writeln('\tif (strcmp("${unmangled_variant_name}", root->child->string) == 0) {')
|
dec.writeln('\tif (strcmp("${unmangled_variant_name}", root->child->string) == 0) {')
|
||||||
if is_js_prim(variant_typ) {
|
if is_js_prim(variant_typ) {
|
||||||
gen_js_get(variant_typ, tmp, unmangled_variant_name, mut dec, true)
|
gen_js_get(ret_styp, tmp, unmangled_variant_name, mut dec, true)
|
||||||
dec.writeln('\t\t${variant_typ} value = ${js_dec_name(variant_typ)}(jsonroot_${tmp});')
|
dec.writeln('\t\t${variant_typ} value = ${js_dec_name(variant_typ)}(jsonroot_${tmp});')
|
||||||
} else if variant_sym.kind == .enum_ {
|
} else if variant_sym.kind == .enum_ {
|
||||||
gen_js_get(variant_typ, tmp, unmangled_variant_name, mut dec, true)
|
if g.is_enum_as_int(variant_sym) {
|
||||||
dec.writeln('\t\t${variant_typ} value = ${js_dec_name('u64')}(jsonroot_${tmp});')
|
gen_js_get(ret_styp, tmp, unmangled_variant_name, mut dec, true)
|
||||||
|
dec.writeln('\t\t${variant_typ} value = ${js_dec_name('u64')}(jsonroot_${tmp});')
|
||||||
|
} else {
|
||||||
|
gen_js_get(ret_styp, tmp, unmangled_variant_name, mut dec, true)
|
||||||
|
dec.writeln('\t\t${variant_typ} value;')
|
||||||
|
tmp2 := g.new_tmp_var()
|
||||||
|
dec.writeln('\t\tstring ${tmp2} = json__decode_string(jsonroot_${tmp});')
|
||||||
|
g.gen_enum_to_str(variant, variant_sym, tmp2, 'value', '\t\t', mut
|
||||||
|
dec)
|
||||||
|
}
|
||||||
} else if variant_sym.name == 'time.Time' {
|
} else if variant_sym.name == 'time.Time' {
|
||||||
gen_js_get(variant_typ, tmp, unmangled_variant_name, mut dec, true)
|
gen_js_get(ret_styp, tmp, unmangled_variant_name, mut dec, true)
|
||||||
dec.writeln('\t\t${variant_typ} value = time__unix(${js_dec_name('i64')}(jsonroot_${tmp}));')
|
dec.writeln('\t\t${variant_typ} value = time__unix(${js_dec_name('i64')}(jsonroot_${tmp}));')
|
||||||
} else {
|
} else {
|
||||||
gen_js_get_opt(js_dec_name(variant_typ), variant_typ, sym.cname, tmp,
|
gen_js_get_opt(js_dec_name(variant_typ), variant_typ, ret_styp, tmp, unmangled_variant_name, mut
|
||||||
unmangled_variant_name, mut dec, true)
|
dec, true)
|
||||||
dec.writeln('\t\t${variant_typ} value = *(${variant_typ}*)(${tmp}.data);')
|
dec.writeln('\t\t${variant_typ} value = *(${variant_typ}*)(${tmp}.data);')
|
||||||
}
|
}
|
||||||
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${sym.cname}(&value);')
|
if is_option {
|
||||||
|
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}(&value) }, &res, sizeof(${sym.cname}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${ret_styp}(&value);')
|
||||||
|
}
|
||||||
dec.writeln('\t}')
|
dec.writeln('\t}')
|
||||||
} $else {
|
} $else {
|
||||||
if variant_sym.name == 'time.Time' {
|
if variant_sym.name == 'time.Time' {
|
||||||
dec.writeln('\t\t\tif (strcmp("Time", ${type_var}) == 0) {')
|
dec.writeln('\t\t\tif (strcmp("Time", ${type_var}) == 0) {')
|
||||||
gen_js_get(sym.cname, tmp, 'value', mut dec, true)
|
gen_js_get(ret_styp, tmp, 'value', mut dec, true)
|
||||||
dec.writeln('\t\t\t\t${variant_typ} ${tmp} = time__unix(${js_dec_name('i64')}(jsonroot_${tmp}));')
|
dec.writeln('\t\t\t\t${variant_typ} ${tmp} = time__unix(${js_dec_name('i64')}(jsonroot_${tmp}));')
|
||||||
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp});')
|
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp});')
|
||||||
dec.writeln('\t\t\t}')
|
dec.writeln('\t\t\t}')
|
||||||
@ -325,7 +432,11 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||||||
last_number_type = var_t
|
last_number_type = var_t
|
||||||
dec.writeln('\t\tif (cJSON_IsNumber(root)) {')
|
dec.writeln('\t\tif (cJSON_IsNumber(root)) {')
|
||||||
dec.writeln('\t\t\t${var_t} value = ${js_dec_name('u64')}(root);')
|
dec.writeln('\t\t\t${var_t} value = ${js_dec_name('u64')}(root);')
|
||||||
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
|
if utyp.has_flag(.option) {
|
||||||
|
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value) }, &${prefix}res, sizeof(${sym.cname}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
|
||||||
|
}
|
||||||
dec.writeln('\t\t}')
|
dec.writeln('\t\t}')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +448,11 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
|||||||
string_is_met = true
|
string_is_met = true
|
||||||
dec.writeln('\t\tif (cJSON_IsString(root)) {')
|
dec.writeln('\t\tif (cJSON_IsString(root)) {')
|
||||||
dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
|
dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
|
||||||
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
|
if utyp.has_flag(.option) {
|
||||||
|
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value) }, &${prefix}res, sizeof(${sym.cname}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
|
||||||
|
}
|
||||||
dec.writeln('\t\t}')
|
dec.writeln('\t\t}')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,12 +552,36 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
|
|||||||
dec.writeln('\t}')
|
dec.writeln('\t}')
|
||||||
} else if field_sym.kind == .enum_ {
|
} else if field_sym.kind == .enum_ {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
gen_js_get(styp, tmp, name, mut dec, is_required)
|
is_option_field := field.typ.has_flag(.option)
|
||||||
dec.writeln('\tif (jsonroot_${tmp}) {')
|
if field.typ.has_flag(.option) {
|
||||||
dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = json__decode_u64(jsonroot_${tmp});')
|
gen_js_get_opt(js_dec_name(field_type), field_type, styp, tmp, name, mut
|
||||||
|
dec, true)
|
||||||
|
dec.writeln('\tif (jsonroot_${tmp} && !cJSON_IsNull(jsonroot_${tmp})) {')
|
||||||
|
} else {
|
||||||
|
gen_js_get(styp, tmp, name, mut dec, is_required)
|
||||||
|
dec.writeln('\tif (jsonroot_${tmp}) {')
|
||||||
|
}
|
||||||
|
if g.is_enum_as_int(field_sym) {
|
||||||
|
if is_option_field {
|
||||||
|
base_typ := g.base_type(field.typ)
|
||||||
|
dec.writeln('\t\t_option_ok(&(${base_typ}[]) { ${js_dec_name('u64')}(jsonroot_${tmp}) }, &${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));')
|
||||||
|
} else {
|
||||||
|
dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = ${js_dec_name('u64')}(jsonroot_${tmp});')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if is_option_field {
|
||||||
|
base_typ := g.base_type(field.typ)
|
||||||
|
dec.writeln('\t\t_option_ok(&(${base_typ}[]) { *(${base_typ}*)((${g.typ(field.typ)}*)${tmp}.data)->data }, &${prefix}${op}${c_name(field.name)}, sizeof(${base_typ}));')
|
||||||
|
} else {
|
||||||
|
tmp2 := g.new_tmp_var()
|
||||||
|
dec.writeln('\t\tstring ${tmp2} = json__decode_string(jsonroot_${tmp});')
|
||||||
|
g.gen_str_to_enum(field.typ, field_sym, tmp2, '${prefix}${op}${c_name(field.name)}',
|
||||||
|
'\t\t', mut dec)
|
||||||
|
}
|
||||||
|
}
|
||||||
if field.has_default_expr {
|
if field.has_default_expr {
|
||||||
dec.writeln('\t} else {')
|
dec.writeln('\t} else {')
|
||||||
dec.writeln('\t\t${prefix}.${c_name(field.name)} = ${g.expr_string(field.default_expr)};')
|
dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = ${g.expr_string(field.default_expr)};')
|
||||||
}
|
}
|
||||||
dec.writeln('\t}')
|
dec.writeln('\t}')
|
||||||
} else if field_sym.name == 'time.Time' {
|
} else if field_sym.name == 'time.Time' {
|
||||||
@ -507,8 +646,9 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
|
|||||||
} else {
|
} else {
|
||||||
'val'
|
'val'
|
||||||
}
|
}
|
||||||
if field.typ.has_flag(.option) {
|
is_option := field.typ.has_flag(.option)
|
||||||
enc.writeln('\tif (val${op}${c_name(field.name)}.state != 2)')
|
if is_option {
|
||||||
|
enc.writeln('\tif (val${op}${c_name(field.name)}.state != 2) {')
|
||||||
}
|
}
|
||||||
if is_omit_empty {
|
if is_omit_empty {
|
||||||
enc.writeln('\t if (val${op}${c_name(field.name)} != ${g.type_default(field.typ)})')
|
enc.writeln('\t if (val${op}${c_name(field.name)} != ${g.type_default(field.typ)})')
|
||||||
@ -520,7 +660,29 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field_sym.kind == .enum_ {
|
if field_sym.kind == .enum_ {
|
||||||
enc.writeln('\tcJSON_AddItemToObject(o, "${name}", json__encode_u64(${prefix_enc}${op}${c_name(field.name)}));\n')
|
if g.is_enum_as_int(field_sym) {
|
||||||
|
if field.typ.has_flag(.option) {
|
||||||
|
enc.writeln('\tcJSON_AddItemToObject(o, "${name}", json__encode_u64(*${prefix_enc}${op}${c_name(field.name)}.data));\n')
|
||||||
|
} else {
|
||||||
|
enc.writeln('\tcJSON_AddItemToObject(o, "${name}", json__encode_u64(${prefix_enc}${op}${c_name(field.name)}));\n')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if field.typ.has_flag(.option) {
|
||||||
|
enc.writeln('\t{')
|
||||||
|
enc.writeln('\t\tcJSON *enum_val;')
|
||||||
|
g.gen_enum_to_str(field.typ, field_sym, '*(${g.base_type(field.typ)}*)${prefix_enc}${op}${c_name(field.name)}.data',
|
||||||
|
'enum_val', '\t\t', mut enc)
|
||||||
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "${name}", enum_val);')
|
||||||
|
enc.writeln('\t}')
|
||||||
|
} else {
|
||||||
|
enc.writeln('\t{')
|
||||||
|
enc.writeln('\t\tcJSON *enum_val;')
|
||||||
|
g.gen_enum_to_str(field.typ, field_sym, '${prefix_enc}${op}${c_name(field.name)}',
|
||||||
|
'enum_val', '\t\t', mut enc)
|
||||||
|
enc.writeln('\t\tcJSON_AddItemToObject(o, "${name}", enum_val);')
|
||||||
|
enc.writeln('\t}')
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if field_sym.name == 'time.Time' {
|
if field_sym.name == 'time.Time' {
|
||||||
// time struct requires special treatment
|
// time struct requires special treatment
|
||||||
@ -542,6 +704,10 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_option {
|
||||||
|
enc.writeln('\t} // !none')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,7 +723,7 @@ fn gen_js_get(styp string, tmp string, name string, mut dec strings.Builder, is_
|
|||||||
fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, name string, mut dec strings.Builder, is_required bool) {
|
fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, name string, mut dec strings.Builder, is_required bool) {
|
||||||
gen_js_get(styp, tmp, name, mut dec, is_required)
|
gen_js_get(styp, tmp, name, mut dec, is_required)
|
||||||
value_field_type := field_type.replace('*', '_ptr')
|
value_field_type := field_type.replace('*', '_ptr')
|
||||||
dec.writeln('\t${result_name}_${value_field_type.replace('*', '_ptr')} ${tmp};')
|
dec.writeln('\t${result_name}_${value_field_type.replace('*', '_ptr')} ${tmp} = {0};')
|
||||||
dec.writeln('\tif (jsonroot_${tmp}) {')
|
dec.writeln('\tif (jsonroot_${tmp}) {')
|
||||||
dec.writeln('\t\t${tmp} = ${dec_name}(jsonroot_${tmp});')
|
dec.writeln('\t\t${tmp} = ${dec_name}(jsonroot_${tmp});')
|
||||||
dec.writeln('\t\tif (${tmp}.is_error) {')
|
dec.writeln('\t\tif (${tmp}.is_error) {')
|
||||||
|
Loading…
Reference in New Issue
Block a user