1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

json: support field &Type (#17655)

This commit is contained in:
Felipe Pena 2023-03-16 16:15:14 -03:00 committed by GitHub
parent 5eb331ed89
commit b345d77805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 54 deletions

View File

@ -0,0 +1,28 @@
import json
struct User {
name string
}
struct MyStruct {
user &User //
users map[string]User
users2 map[string]&User
}
fn test_json_encode_with_ptr() {
user := User{
name: 'foo'
}
data := MyStruct{
user: &user
users: {
'keyfoo': user
}
users2: {
'keyfoo': &user
}
}
assert json.encode(data) == '{"user":{"name":"foo"},"users":{"keyfoo":{"name":"foo"}},"users2":{"keyfoo":{"name":"foo"}}}'
}

View File

@ -1339,9 +1339,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
g.empty_line = true g.empty_line = true
g.writeln('// json.encode') g.writeln('// json.encode')
g.write('cJSON* ${json_obj} = ${encode_name}(') g.write('cJSON* ${json_obj} = ${encode_name}(')
if node.args[0].typ.is_ptr() {
g.write('*')
}
g.call_args(node) g.call_args(node)
g.writeln(');') g.writeln(');')
tmp2 = g.new_tmp_var() tmp2 = g.new_tmp_var()

View File

@ -24,7 +24,7 @@ import strings
// Codegen json_decode/encode funcs // Codegen json_decode/encode funcs
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).set_nr_muls(0) 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)) || sym.kind == .enum_ {
return return
@ -44,12 +44,13 @@ fn (mut g Gen) gen_jsons() {
mut enc := strings.new_builder(100) mut enc := strings.new_builder(100)
sym := g.table.sym(utyp) sym := g.table.sym(utyp)
styp := g.typ(utyp) styp := g.typ(utyp)
ret_styp := styp.replace('*', '_ptr')
g.register_result(utyp) g.register_result(utyp)
// decode_TYPE funcs receive an actual cJSON* object to decode // decode_TYPE funcs receive an actual cJSON* object to decode
// cJSON_Parse(str) call is added by the compiler // cJSON_Parse(str) call is added by the compiler
// Codegen decoder // Codegen decoder
dec_fn_name := js_dec_name(styp) dec_fn_name := js_dec_name(styp)
dec_fn_dec := '${result_name}_${styp} ${dec_fn_name}(cJSON* root)' dec_fn_dec := '${result_name}_${ret_styp} ${dec_fn_name}(cJSON* root)'
mut init_styp := '${styp} res' mut init_styp := '${styp} res'
if utyp.has_flag(.option) { if utyp.has_flag(.option) {
@ -104,7 +105,7 @@ ${dec_fn_dec} {
int maxchars = vstrlen_char(prevline_ptr); int maxchars = vstrlen_char(prevline_ptr);
vmemcpy(buf, prevline_ptr, (maxchars < maxcontext_chars ? maxchars : maxcontext_chars)); vmemcpy(buf, prevline_ptr, (maxchars < maxcontext_chars ? maxchars : maxcontext_chars));
} }
return (${result_name}_${styp}){.is_error = true,.err = _v_error(tos2(buf)),.data = {0}}; return (${result_name}_${ret_styp}){.is_error = true,.err = _v_error(tos2(buf)),.data = {0}};
} }
} }
') ')
@ -146,7 +147,7 @@ ${enc_fn_dec} {
} }
enc.writeln('\to = cJSON_CreateObject();') enc.writeln('\to = cJSON_CreateObject();')
if psym.info is ast.Struct { if psym.info is ast.Struct {
g.gen_struct_enc_dec(utyp, psym.info, styp, mut enc, mut dec) g.gen_struct_enc_dec(utyp, psym.info, ret_styp, 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 {
@ -158,7 +159,7 @@ ${enc_fn_dec} {
if sym.info !is ast.SumType { if sym.info !is ast.SumType {
verror('json: ${sym.name} is not a sumtype') verror('json: ${sym.name} is not a sumtype')
} }
g.gen_sumtype_enc_dec(sym, mut enc, mut dec) g.gen_sumtype_enc_dec(utyp, sym, mut enc, mut dec, ret_styp)
} 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 {
@ -167,10 +168,10 @@ ${enc_fn_dec} {
if sym.info !is ast.Struct { if sym.info !is ast.Struct {
verror('json: ${sym.name} is not struct') verror('json: ${sym.name} is not struct')
} }
g.gen_struct_enc_dec(utyp, sym.info, styp, mut enc, mut dec) g.gen_struct_enc_dec(utyp, sym.info, ret_styp, mut enc, mut dec)
} }
// cJSON_delete // cJSON_delete
dec.writeln('\t${result_name}_${styp} ret;') dec.writeln('\t${result_name}_${ret_styp} ret;')
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));') dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
if utyp.has_flag(.option) { if utyp.has_flag(.option) {
dec.writeln('\t_option_ok(&res.data, &ret.data, sizeof(${g.base_type(utyp)}));') dec.writeln('\t_option_ok(&res.data, &ret.data, sizeof(${g.base_type(utyp)}));')
@ -193,10 +194,12 @@ fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec
} }
[inline] [inline]
fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder, mut dec strings.Builder) { fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc strings.Builder, mut dec strings.Builder, ret_styp string) {
info := sym.info as ast.SumType info := sym.info as ast.SumType
type_var := g.new_tmp_var() type_var := g.new_tmp_var()
typ := g.table.type_idxs[sym.name] typ := g.table.type_idxs[sym.name]
prefix := if utyp.is_ptr() { '*' } else { '' }
field_op := if utyp.is_ptr() { '->' } else { '.' }
// DECODING (inline) // DECODING (inline)
$if !json_no_inline_sumtypes ? { $if !json_no_inline_sumtypes ? {
@ -228,25 +231,25 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
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._typ == ${variant.idx()}) {') 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._${variant_typ}));') enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('u64')}(*val${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._${variant_typ}->_v_unix));') enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name('i64')}(val${field_op}_${variant_typ}->_v_unix));')
} else { } else {
enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name(variant_typ)}(*val._${variant_typ}));') enc.writeln('\t\tcJSON_AddItemToObject(o, "${unmangled_variant_name}", ${js_enc_name(variant_typ)}(*val${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._${variant_typ});') enc.writeln('\t\to = ${js_enc_name(variant_typ)}(*val${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._${variant_typ});') enc.writeln('\t\to = ${js_enc_name('u64')}(*val${field_op}_${variant_typ});')
} 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._${variant_typ}->_v_unix));') enc.writeln('\t\tcJSON_AddItemToObject(o, "value", ${js_enc_name('i64')}(val${field_op}_${variant_typ}->_v_unix));')
} else { } else {
enc.writeln('\t\to = ${js_enc_name(variant_typ)}(*val._${variant_typ});') enc.writeln('\t\to = ${js_enc_name(variant_typ)}(*val${field_op}_${variant_typ});')
enc.writeln('\t\tcJSON_AddItemToObject(o, "_type", cJSON_CreateString("${unmangled_variant_name}"));') enc.writeln('\t\tcJSON_AddItemToObject(o, "_type", cJSON_CreateString("${unmangled_variant_name}"));')
} }
} }
@ -277,15 +280,16 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
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(sym.cname, 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\tres = ${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}')
} else if !is_js_prim(variant_typ) && variant_sym.kind != .enum_ { } else if !is_js_prim(variant_typ) && variant_sym.kind != .enum_ {
dec.writeln('\t\t\tif (strcmp("${unmangled_variant_name}", ${type_var}) == 0) {') dec.writeln('\t\t\tif (strcmp("${unmangled_variant_name}", ${type_var}) == 0) {')
dec.writeln('\t\t\t\t${result_name}_${variant_typ} ${tmp} = ${js_dec_name(variant_typ)}(root);') dec.writeln('\t\t\t\t${result_name}_${variant_typ} ${tmp} = ${js_dec_name(variant_typ)}(root);')
dec.writeln('\t\t\t\tif (${tmp}.is_error) {') dec.writeln('\t\t\t\tif (${tmp}.is_error) {')
dec.writeln('\t\t\t\t\treturn (${result_name}_${sym.cname}){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t\t\treturn (${result_name}_${ret_styp}){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t\t}') dec.writeln('\t\t\t\t}')
dec.writeln('\t\t\t\tres = ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data);') dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data);')
dec.writeln('\t\t\t}') dec.writeln('\t\t\t}')
} }
} }
@ -306,7 +310,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
var_t := 'bool' var_t := 'bool'
dec.writeln('\t\tif (cJSON_IsBool(root)) {') dec.writeln('\t\tif (cJSON_IsBool(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\tres = ${var_t}_to_sumtype_${sym.cname}(&value);') dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t}') dec.writeln('\t\t}')
} }
@ -321,7 +325,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
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\tres = ${var_t}_to_sumtype_${sym.cname}(&value);') dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t}') dec.writeln('\t\t}')
} }
@ -333,7 +337,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
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\tres = ${var_t}_to_sumtype_${sym.cname}(&value);') dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t}') dec.writeln('\t\t}')
} }
@ -351,7 +355,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
dec.writeln('\t\t\tif (${tmp}.is_error) {') dec.writeln('\t\t\tif (${tmp}.is_error) {')
dec.writeln('\t\t\t\treturn (${result_name}_${sym.cname}){ .is_error = true, .err = ${tmp}.err, .data = {0} };') dec.writeln('\t\t\t\treturn (${result_name}_${sym.cname}){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t}') dec.writeln('\t\t\t}')
dec.writeln('\t\t\tres = ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data);') dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data);')
dec.writeln('\t\t}') dec.writeln('\t\t}')
} }
@ -366,7 +370,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
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(var_t)}(root);') dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
dec.writeln('\t\t\tres = ${var_t}_to_sumtype_${sym.cname}(&value);') dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t}') dec.writeln('\t\t}')
} }
} }
@ -410,10 +414,11 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
} }
field_type := g.typ(field.typ) field_type := g.typ(field.typ)
field_sym := g.table.sym(field.typ) field_sym := g.table.sym(field.typ)
op := if utyp.is_ptr() { '->' } else { '.' }
prefix := if utyp.has_flag(.option) { '(*(${g.base_type(utyp)}*)res.data)' } else { 'res' } prefix := if utyp.has_flag(.option) { '(*(${g.base_type(utyp)}*)res.data)' } else { 'res' }
// First generate decoding // First generate decoding
if is_raw { if is_raw {
dec.writeln('\tres.${c_name(field.name)} = tos5(cJSON_PrintUnformatted(' + dec.writeln('\tres${op}${c_name(field.name)} = tos5(cJSON_PrintUnformatted(' +
'js_get(root, "${name}")));') 'js_get(root, "${name}")));')
} else { } else {
// Now generate decoders for all field types in this struct // Now generate decoders for all field types in this struct
@ -424,17 +429,17 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
gen_js_get(styp, tmp, name, mut dec, is_required) gen_js_get(styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
dec.writeln('\t\t${prefix}.${c_name(field.name)} = ${dec_name}(jsonroot_${tmp});') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = ${dec_name}(jsonroot_${tmp});')
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.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) gen_js_get(styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
dec.writeln('\t\t${prefix}.${c_name(field.name)} = json__decode_u64(jsonroot_${tmp});') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = json__decode_u64(jsonroot_${tmp});')
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}.${c_name(field.name)} = ${g.expr_string(field.default_expr)};')
@ -446,10 +451,10 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
gen_js_get(styp, tmp, name, mut dec, is_required) gen_js_get(styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
dec.writeln('\t\t${prefix}.${c_name(field.name)} = time__unix(json__decode_u64(jsonroot_${tmp}));') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = time__unix(json__decode_u64(jsonroot_${tmp}));')
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.kind == .alias { } else if field_sym.kind == .alias {
@ -460,10 +465,10 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
gen_js_get(styp, tmp, name, mut dec, is_required) gen_js_get(styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
dec.writeln('\t\t${prefix}.${c_name(field.name)} = ${parent_dec_name} (jsonroot_${tmp});') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = ${parent_dec_name} (jsonroot_${tmp});')
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 { } else {
@ -471,10 +476,10 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
gen_js_get_opt(dec_name, field_type, styp, tmp, name, mut dec, is_required) gen_js_get_opt(dec_name, field_type, styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
dec.writeln('\t\t${prefix}.${c_name(field.name)} = *(${field_type}*) ${tmp}.data;') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = *(${field_type}*) ${tmp}.data;')
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}')
} }
@ -484,13 +489,13 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
dec.writeln('\tif (jsonroot_${tmp}) {') dec.writeln('\tif (jsonroot_${tmp}) {')
if field_sym.kind == .array_fixed { if field_sym.kind == .array_fixed {
dec.writeln('\t\tvmemcpy(${prefix}.${c_name(field.name)},*(${field_type}*)${tmp}.data,sizeof(${field_type}));') dec.writeln('\t\tvmemcpy(${prefix}${op}${c_name(field.name)},*(${field_type}*)${tmp}.data,sizeof(${field_type}));')
} else { } else {
dec.writeln('\t\t${prefix}.${c_name(field.name)} = *(${field_type}*) ${tmp}.data;') dec.writeln('\t\t${prefix}${op}${c_name(field.name)} = *(${field_type}*) ${tmp}.data;')
} }
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}')
} }
@ -503,10 +508,10 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
'val' 'val'
} }
if field.typ.has_flag(.option) { if field.typ.has_flag(.option) {
enc.writeln('\tif (val.${c_name(field.name)}.state != 2)') enc.writeln('\tif (val${op}${c_name(field.name)}.state != 2)')
} }
if is_omit_empty { if is_omit_empty {
enc.writeln('\t if (val.${c_name(field.name)} != ${g.type_default(field.typ)})') enc.writeln('\t if (val${op}${c_name(field.name)} != ${g.type_default(field.typ)})')
} }
if !is_js_prim(field_type) { if !is_js_prim(field_type) {
if field_sym.kind == .alias { if field_sym.kind == .alias {
@ -523,11 +528,12 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
enc.writeln('\tcJSON_AddItemToObject(o, "${name}", json__encode_u64(${prefix_enc}.${c_name(field.name)}._v_unix));') enc.writeln('\tcJSON_AddItemToObject(o, "${name}", json__encode_u64(${prefix_enc}.${c_name(field.name)}._v_unix));')
} else { } else {
if !field.typ.is_real_pointer() { if !field.typ.is_real_pointer() {
enc.writeln('\tcJSON_AddItemToObject(o, "${name}", ${enc_name}(${prefix_enc}.${c_name(field.name)})); /*A*/') enc.writeln('\tcJSON_AddItemToObject(o, "${name}", ${enc_name}(${prefix_enc}${op}${c_name(field.name)})); /*A*/')
} else { } else {
sptr_value := '${prefix_enc}.${c_name(field.name)}' arg_prefix := if field.typ.is_ptr() { '' } else { '*' }
sptr_value := '${prefix_enc}${op}${c_name(field.name)}'
enc.writeln('\tif (${sptr_value} != 0) {') enc.writeln('\tif (${sptr_value} != 0) {')
enc.writeln('\t\tcJSON_AddItemToObject(o, "${name}", ${enc_name}(*${sptr_value}));') enc.writeln('\t\tcJSON_AddItemToObject(o, "${name}", ${enc_name}(${arg_prefix}${sptr_value}));')
enc.writeln('\t}\n') enc.writeln('\t}\n')
} }
} }
@ -546,24 +552,24 @@ 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.trim_right('*') value_field_type := field_type.replace('*', '_ptr')
dec.writeln('\t${result_name}_${value_field_type} ${tmp};') dec.writeln('\t${result_name}_${value_field_type.replace('*', '_ptr')} ${tmp};')
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) {')
dec.writeln('\t\t\treturn (${result_name}_${styp}){ .is_error = true, .err = ${tmp}.err, .data = {0} };') dec.writeln('\t\t\treturn (${result_name}_${styp}){ /*A*/ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t}') dec.writeln('\t\t}')
dec.writeln('\t}') dec.writeln('\t}')
} }
fn js_enc_name(typ string) string { fn js_enc_name(typ string) string {
suffix := if typ.ends_with('*') { typ.trim_right('*') } else { typ } suffix := typ.replace('*', '_ptr')
name := 'json__encode_${suffix}' name := 'json__encode_${suffix}'
return util.no_dots(name) return util.no_dots(name)
} }
fn js_dec_name(typ string) string { fn js_dec_name(typ string) string {
suffix := if typ.ends_with('*') { typ.trim_right('*') } else { typ } suffix := typ.replace('*', '_ptr')
name := 'json__decode_${suffix}' name := 'json__decode_${suffix}'
return util.no_dots(name) return util.no_dots(name)
} }
@ -643,7 +649,8 @@ fn (mut g Gen) encode_array(value_type ast.Type, fixed_array_size int) string {
fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type) string { fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type) string {
styp := g.typ(key_type) styp := g.typ(key_type)
styp_v := g.typ(value_type) mut styp_v := g.typ(value_type)
ret_styp := styp_v.replace('*', '_ptr')
key_type_symbol := g.table.sym(key_type) key_type_symbol := g.table.sym(key_type)
hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_type_symbol) hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_type_symbol)
fn_name_v := js_dec_name(styp_v) fn_name_v := js_dec_name(styp_v)
@ -652,17 +659,17 @@ fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type) string {
s = '${styp_v} val = ${fn_name_v} (js_get(root, jsval->string));' s = '${styp_v} val = ${fn_name_v} (js_get(root, jsval->string));'
} else { } else {
s = ' s = '
${result_name}_${styp_v} val2 = ${fn_name_v} (js_get(root, jsval->string)); ${result_name}_${ret_styp} val2 = ${fn_name_v} (js_get(root, jsval->string));
if(val2.is_error) { if(val2.is_error) {
map_free(&res); map_free(&res);
return *(${result_name}_Map_${styp}_${styp_v}*)&val2; return *(${result_name}_Map_${styp}_${ret_styp}*)&val2;
} }
${styp_v} val = *(${styp_v}*)val2.data; ${styp_v} val = *(${styp_v}*)val2.data;
' '
} }
return ' return '
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) { if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
return (${result_name}_Map_${styp}_${styp_v}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}}; return (${result_name}_Map_${styp}_${ret_styp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
} }
res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn}); res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn});
cJSON *jsval = NULL; cJSON *jsval = NULL;