@@ -86,10 +86,13 @@ $enc_fn_dec {
8686 return
8787 }
8888 enc.writeln ('\t o = cJSON_CreateObject();' )
89- if psym.info ! is ast.Struct {
89+ if psym.info is ast.Struct {
90+ g.gen_struct_enc_dec (psym.info, styp, mut enc, mut dec)
91+ } else if psym.kind == .sum_type {
92+ verror ('json: $sym.name aliased sumtypes does not work at the moment' )
93+ } else {
9094 verror ('json: $sym.name is not struct' )
9195 }
92- g.gen_struct_enc_dec (psym.info, styp, mut enc, mut dec)
9396 } else if sym.kind == .sum_type {
9497 enc.writeln ('\t o = cJSON_CreateObject();' )
9598 // Sumtypes. Range through variants of sumtype
@@ -118,46 +121,164 @@ $enc_fn_dec {
118121[inline ]
119122fn (mut g Gen) gen_sumtype_enc_dec (sym ast.TypeSymbol, mut enc strings.Builder, mut dec strings.Builder) {
120123 info := sym.info as ast.SumType
124+ type_var := g.new_tmp_var ()
121125 typ := sym.idx
122126
127+ // DECODING (inline)
128+ $if ! json_no_inline_sumtypes ? {
129+ type_tmp := g.new_tmp_var ()
130+ dec.writeln ('\t if (cJSON_IsObject(root)) {' )
131+ dec.writeln ('\t\t cJSON* $type_tmp = js_get(root, "_type");' )
132+ dec.writeln ('\t\t if ($type_tmp != 0) {' )
133+ dec.writeln ('\t\t\t char* $type_var = cJSON_GetStringValue($type_tmp );' )
134+ // dec.writeln('\t\t\tcJSON_DeleteItemFromObjectCaseSensitive(root, "_type");')
135+ }
136+
137+ mut variant_types := []string {}
138+ mut variant_symbols := []ast.TypeSymbol{}
139+ mut at_least_one_prim := false
123140 for variant in info.variants {
124141 variant_typ := g.typ (variant)
142+ variant_types << variant_typ
125143 variant_sym := g.table.get_type_symbol (variant)
144+ variant_symbols << variant_sym
145+ at_least_one_prim = at_least_one_prim || is_js_prim (variant_typ)
146+ || variant_sym.kind == .enum_ || variant_sym.name == 'time.Time'
126147 unmangled_variant_name := variant_sym.name.split ('.' ).last ()
127148
149+ // TODO: Do not generate dec/enc for 'time.Time', because we handle it by saving it as u64
128150 g.gen_json_for_type (variant)
151+
152+ // Helpers for decoding
129153 g.write_sumtype_casting_fn (variant, typ)
130154 g.definitions.writeln ('static inline $sym.cname ${variant_typ} _to_sumtype_${sym.cname} ($variant_typ * x);' )
131155
132156 // ENCODING
133157 enc.writeln ('\t if (val._typ == $variant ) {' )
134- if variant_sym.kind == .enum_ {
135- enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", json__encode_u64(*val._$variant_typ ));' )
136- } else if variant_sym.name == 'time.Time' {
137- enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", json__encode_i64(val._$variant_typ ->_v_unix));' )
138- } else {
139- enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", json__encode_${variant_typ} (*val._$variant_typ ));' )
158+ $if json_no_inline_sumtypes ? {
159+ if variant_sym.kind == .enum_ {
160+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", ${js_enc_name('u64')} (*val._$variant_typ ));' )
161+ } else if variant_sym.name == 'time.Time' {
162+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", ${js_enc_name('i64')} (val._$variant_typ ->_v_unix));' )
163+ } else {
164+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "$unmangled_variant_name ", ${js_enc_name(variant_typ)} (*val._$variant_typ ));' )
165+ }
166+ } $else {
167+ if is_js_prim (variant_typ) {
168+ enc.writeln ('\t\t o = ${js_enc_name(variant_typ)} (*val._$variant_typ );' )
169+ } else if variant_sym.kind == .enum_ {
170+ enc.writeln ('\t\t o = ${js_enc_name('u64')} (*val._$variant_typ );' )
171+ } else if variant_sym.name == 'time.Time' {
172+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "_type", cJSON_CreateString("$unmangled_variant_name "));' )
173+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "value", ${js_enc_name('i64')} (val._$variant_typ ->_v_unix));' )
174+ } else {
175+ enc.writeln ('\t\t o = ${js_enc_name(variant_typ)} (*val._$variant_typ );' )
176+ enc.writeln ('\t\t cJSON_AddItemToObject(o, "_type", cJSON_CreateString("$unmangled_variant_name "));' )
177+ }
140178 }
141179 enc.writeln ('\t }' )
142180
143181 // DECODING
144- dec.writeln ('\t if (strcmp("$unmangled_variant_name ", root->child->string) == 0) {' )
145182 tmp := g.new_tmp_var ()
146- if is_js_prim (variant_typ) {
147- gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, false )
148- dec.writeln ('\t\t $variant_typ value = (${js_dec_name(variant_typ)} )(jsonroot_$tmp );' )
149- } else if variant_sym.kind == .enum_ {
150- gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, false )
151- dec.writeln ('\t\t $variant_typ value = json__decode_u64(jsonroot_$tmp );' )
152- } else if variant_sym.name == 'time.Time' {
153- gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, false )
154- dec.writeln ('\t\t $variant_typ value = time__unix(json__decode_i64(jsonroot_$tmp ));' )
155- } else {
156- gen_js_get_opt (js_dec_name (variant_typ), variant_typ, sym.cname, tmp, unmangled_variant_name, mut
157- dec, false )
158- dec.writeln ('\t\t $variant_typ value = *($variant_typ *)(${tmp} .data);' )
183+ $if json_no_inline_sumtypes ? {
184+ dec.writeln ('\t if (strcmp("$unmangled_variant_name ", root->child->string) == 0) {' )
185+ if is_js_prim (variant_typ) {
186+ gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, true )
187+ dec.writeln ('\t\t $variant_typ value = ${js_dec_name(variant_typ)} (jsonroot_$tmp );' )
188+ } else if variant_sym.kind == .enum_ {
189+ gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, true )
190+ dec.writeln ('\t\t $variant_typ value = ${js_dec_name('u64')} (jsonroot_$tmp );' )
191+ } else if variant_sym.name == 'time.Time' {
192+ gen_js_get (variant_typ, tmp, unmangled_variant_name, mut dec, true )
193+ dec.writeln ('\t\t $variant_typ value = time__unix(${js_dec_name('i64')} (jsonroot_$tmp ));' )
194+ } else {
195+ gen_js_get_opt (js_dec_name (variant_typ), variant_typ, sym.cname, tmp,
196+ unmangled_variant_name, mut dec, true )
197+ dec.writeln ('\t\t $variant_typ value = *($variant_typ *)(${tmp} .data);' )
198+ }
199+ dec.writeln ('\t\t res = ${variant_typ} _to_sumtype_${sym.cname} (&value);' )
200+ dec.writeln ('\t }' )
201+ } $else {
202+ if variant_sym.name == 'time.Time' {
203+ dec.writeln ('\t\t\t if (strcmp("Time", $type_var ) == 0) {' )
204+ gen_js_get (sym.cname, tmp, 'value' , mut dec, true )
205+ dec.writeln ('\t\t\t\t $variant_typ $tmp = time__unix(${js_dec_name('i64')} (jsonroot_$tmp ));' )
206+ dec.writeln ('\t\t\t\t res = ${variant_typ} _to_sumtype_${sym.cname} (&$tmp );' )
207+ dec.writeln ('\t\t\t }' )
208+ } else if ! is_js_prim (variant_typ) && variant_sym.kind != .enum_ {
209+ dec.writeln ('\t\t\t if (strcmp("$unmangled_variant_name ", $type_var ) == 0) {' )
210+ dec.writeln ('\t\t\t\t Option_$variant_typ $tmp = ${js_dec_name(variant_typ)} (root);' )
211+ dec.writeln ('\t\t\t\t if (${tmp} .state != 0) {' )
212+ dec.writeln ('\t\t\t\t\t return (Option_$sym.cname ){ .state = ${tmp} .state, .err = ${tmp} .err, .data = {0} };' )
213+ dec.writeln ('\t\t\t\t }' )
214+ dec.writeln ('\t\t\t\t res = ${variant_typ} _to_sumtype_${sym.cname} (($variant_typ *)${tmp} .data);' )
215+ dec.writeln ('\t\t\t }' )
216+ }
217+ }
218+ }
219+
220+ // DECODING (inline)
221+ $if ! json_no_inline_sumtypes ? {
222+ dec.writeln ('\t\t }' )
223+
224+ mut number_is_met := false
225+ mut string_is_met := false
226+ mut last_number_type := ''
227+
228+ if at_least_one_prim {
229+ dec.writeln ('\t } else {' )
230+
231+ if 'bool' in variant_types {
232+ var_t := 'bool'
233+ dec.writeln ('\t\t if (cJSON_IsBool(root)) {' )
234+ dec.writeln ('\t\t\t $var_t value = ${js_dec_name(var_t)} (root);' )
235+ dec.writeln ('\t\t\t res = ${var_t} _to_sumtype_${sym.cname} (&value);' )
236+ dec.writeln ('\t\t }' )
237+ }
238+
239+ for i, var_t in variant_types {
240+ if variant_symbols[i].kind == .enum_ {
241+ if number_is_met {
242+ var_num := var_t.replace ('__' , '.' )
243+ last_num := last_number_type.replace ('__' , '.' )
244+ verror ('json: can not decode `$sym.name ` sumtype, too many numeric types (conflict of `$last_num ` and `$var_num `), you can try to use alias for `$var_num ` or compile v with `json_no_inline_sumtypes` flag' )
245+ }
246+ number_is_met = true
247+ last_number_type = var_t
248+ dec.writeln ('\t\t if (cJSON_IsNumber(root)) {' )
249+ dec.writeln ('\t\t\t $var_t value = ${js_dec_name('u64')} (root);' )
250+ dec.writeln ('\t\t\t res = ${var_t} _to_sumtype_${sym.cname} (&value);' )
251+ dec.writeln ('\t\t }' )
252+ }
253+
254+ if var_t in ['string' , 'rune' ] {
255+ if string_is_met {
256+ var_num := var_t.replace ('__' , '.' )
257+ verror ('json: can not decode `$sym.name ` sumtype, too many string types (conflict of `string` and `rune`), you can try to use alias for `$var_num ` or compile v with `json_no_inline_sumtypes` flag' )
258+ }
259+ string_is_met = true
260+ dec.writeln ('\t\t if (cJSON_IsString(root)) {' )
261+ dec.writeln ('\t\t\t $var_t value = ${js_dec_name(var_t)} (root);' )
262+ dec.writeln ('\t\t\t res = ${var_t} _to_sumtype_${sym.cname} (&value);' )
263+ dec.writeln ('\t\t }' )
264+ }
265+
266+ if var_t in ['i64' , 'int' , 'i8' , 'u64' , 'u32' , 'u16' , 'byte' , 'u8' , 'rune' , 'f64' ,
267+ 'f32' ] {
268+ if number_is_met {
269+ var_num := var_t.replace ('__' , '.' )
270+ last_num := last_number_type.replace ('__' , '.' )
271+ verror ('json: can not decode `$sym.name ` sumtype, too many numeric types (conflict of `$last_num ` and `$var_num `), you can try to use alias for `$var_num ` or compile v with `json_no_inline_sumtypes` flag' )
272+ }
273+ number_is_met = true
274+ last_number_type = var_t
275+ dec.writeln ('\t\t if (cJSON_IsNumber(root)) {' )
276+ dec.writeln ('\t\t\t $var_t value = ${js_dec_name(var_t)} (root);' )
277+ dec.writeln ('\t\t\t res = ${var_t} _to_sumtype_${sym.cname} (&value);' )
278+ dec.writeln ('\t\t }' )
279+ }
280+ }
159281 }
160- dec.writeln ('\t\t res = ${variant_typ} _to_sumtype_${sym.cname} (&value);' )
161282 dec.writeln ('\t }' )
162283 }
163284}
@@ -294,8 +415,8 @@ fn js_dec_name(typ string) string {
294415}
295416
296417fn is_js_prim (typ string ) bool {
297- return typ in ['int' , 'string' , 'bool' , 'f32' , 'f64' , 'i8' , 'i16' , 'i64' , 'u16 ' , 'u32' , 'u64 ' ,
298- 'byte' ]
418+ return typ in ['int' , 'rune' , ' string' , 'bool' , 'f32' , 'f64' , 'i8' , 'i16' , 'i64' , 'u8 ' , 'u16 ' ,
419+ 'u32' , 'u64' , ' byte' ]
299420}
300421
301422fn (mut g Gen) decode_array (value_type ast.Type) string {
0 commit comments