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:
parent
5095364838
commit
f54e45b77e
@ -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] ));
|
||||||
}
|
}
|
||||||
'
|
'
|
||||||
}
|
}
|
||||||
|
46
vlib/v/tests/json_serialisation_of_fixed_arrays_test.v
Normal file
46
vlib/v/tests/json_serialisation_of_fixed_arrays_test.v
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user