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

json: fix array_fixed encode/decode (#15398)

This commit is contained in:
Nikolai 2022-08-11 03:52:56 +03:00 committed by GitHub
parent 5095364838
commit f54e45b77e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 15 deletions

View File

@ -102,13 +102,18 @@ $dec_fn_dec {
enc.writeln(' enc.writeln('
$enc_fn_dec { $enc_fn_dec {
\tcJSON *o;') \tcJSON *o;')
if sym.kind == .array { if sym.kind == .array || sym.kind == .array_fixed {
array_size := if sym.kind == .array_fixed {
(sym.info as ast.ArrayFixed).size
} else {
-1
}
// Handle arrays // Handle arrays
value_type := g.table.value_type(utyp) value_type := g.table.value_type(utyp)
// If we have `[]Profile`, have to register a Profile en(de)coder first // If we have `[]Profile`, have to register a Profile en(de)coder first
g.gen_json_for_type(value_type) g.gen_json_for_type(value_type)
dec.writeln(g.decode_array(value_type)) dec.writeln(g.decode_array(value_type, array_size))
enc.writeln(g.encode_array(value_type)) enc.writeln(g.encode_array(value_type, array_size))
} else if sym.kind == .map { } else if sym.kind == .map {
// Handle maps // Handle maps
m := sym.info as ast.Map m := sym.info as ast.Map
@ -446,7 +451,11 @@ fn (mut g Gen) gen_struct_enc_dec(type_info ast.TypeInfo, styp string, mut enc s
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\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;') if field_sym.kind == .array_fixed {
dec.writeln('\t\tvmemcpy(res.${c_name(field.name)},*($field_type*)${tmp}.data,sizeof($field_type));')
} else {
dec.writeln('\t\tres.${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\tres.${c_name(field.name)} = ${g.expr_string(field.default_expr)};') dec.writeln('\t\tres.${c_name(field.name)} = ${g.expr_string(field.default_expr)};')
@ -515,9 +524,25 @@ fn is_js_prim(typ string) bool {
'u32', 'u64', 'byte'] 'u32', 'u64', 'byte']
} }
fn (mut g Gen) decode_array(value_type ast.Type) string { fn (mut g Gen) decode_array(value_type ast.Type, fixed_array_size int) string {
styp := g.typ(value_type) styp := g.typ(value_type)
fn_name := js_dec_name(styp) fn_name := js_dec_name(styp)
noscan := g.check_noscan(value_type)
fixed_array_str, fixed_array_size_str, res_str, array_free_str := if fixed_array_size > -1 {
// fixed array
'fixed_', '_$fixed_array_size', '', ''
} else {
'', '', 'res = __new_array${noscan}(0, 0, sizeof($styp));', 'array_free(&res);'
}
fixed_array_idx, array_element_assign, fixed_array_idx_increment := if fixed_array_size > -1 {
// fixed array
'int fixed_array_idx = 0;', 'res[fixed_array_idx] = val;', 'fixed_array_idx++;'
} else {
'', 'array_push${noscan}((array*)&res, &val);', ''
}
mut s := '' mut s := ''
if is_js_prim(styp) { if is_js_prim(styp) {
s = '$styp val = ${fn_name}((cJSON *)jsval); ' s = '$styp val = ${fn_name}((cJSON *)jsval); '
@ -525,34 +550,44 @@ fn (mut g Gen) decode_array(value_type ast.Type) string {
s = ' s = '
${option_name}_$styp val2 = $fn_name ((cJSON *)jsval); ${option_name}_$styp val2 = $fn_name ((cJSON *)jsval);
if(val2.state != 0) { if(val2.state != 0) {
array_free(&res); $array_free_str
return *(${option_name}_Array_$styp*)&val2; return *(${option_name}_Array_$fixed_array_str$styp$fixed_array_size_str*)&val2;
} }
$styp val = *($styp*)val2.data; $styp val = *($styp*)val2.data;
' '
} }
noscan := g.check_noscan(value_type)
return ' return '
if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) { if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) {
return (${option_name}_Array_$styp){.state = 2, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}}; return (${option_name}_Array_$fixed_array_str$styp$fixed_array_size_str){.state = 2, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
} }
res = __new_array${noscan}(0, 0, sizeof($styp)); $res_str
const cJSON *jsval = NULL; const cJSON *jsval = NULL;
$fixed_array_idx
cJSON_ArrayForEach(jsval, root) cJSON_ArrayForEach(jsval, root)
{ {
$s $s
array_push${noscan}((array*)&res, &val); $array_element_assign
$fixed_array_idx_increment
} }
' '
} }
fn (mut g Gen) encode_array(value_type ast.Type) string { fn (mut g Gen) encode_array(value_type ast.Type, fixed_array_size int) string {
styp := g.typ(value_type) styp := g.typ(value_type)
fn_name := js_enc_name(styp) fn_name := js_enc_name(styp)
data_str, size_str := if fixed_array_size > -1 {
// fixed array
'', '$fixed_array_size'
} else {
'.data', 'val.len'
}
return ' return '
o = cJSON_CreateArray(); o = cJSON_CreateArray();
for (int i = 0; i < val.len; i++){ for (int i = 0; i < $size_str; i++){
cJSON_AddItemToArray(o, $fn_name ( (($styp*)val.data)[i] )); cJSON_AddItemToArray(o, $fn_name ( (($styp*)val$data_str)[i] ));
} }
' '
} }

View File

@ -0,0 +1,46 @@
import json
struct Abc {
my_ints [6]int
my_strs [2]string
my_arr []int
}
struct Fixed_Array {
abc [5]Abc
}
fn test_json_serialisation_of_fixed_arrays() ? {
a := Fixed_Array{[
Abc{
my_ints: [1, 2, 3, 4, 5, 6]!
my_strs: ['zzzddddddddddd', 'www']!
my_arr: [1, 2, 3]
},
Abc{
my_ints: [7, 8, 9, 10, 11, 12]!
my_strs: ['zzz', 'www']!
my_arr: [1, 2, 3]
},
Abc{
my_ints: [13, 14, 15, 16, 17, 18]!
my_strs: ['zzzaaaaaaaa', 'www111111112333']!
my_arr: [1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 5, 7, 1, 2, 3, 4, 5]
},
Abc{
my_ints: [19, 21, 23, 10, 50444, 3331]!
my_strs: ['zzz', 'www']!
my_arr: [1, 2, 3]
},
Abc{
my_ints: [20, 22, 24, 44, 560, 640]!
my_strs: ['zzz', 'www']!
my_arr: [1, 2, 3]
},
]!}
s := json.encode(a)
dump(s)
b := json.decode(Fixed_Array, s)?
dump(b)
assert a == b
}