diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-09-14 04:29:31 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-09-14 06:56:36 +0200 |
commit | c1d2e38840c0596efd10e97ff5a9edaa20d5457e (patch) | |
tree | f1d56b745e9a8f1d649c442f52a3f0ddcf5d795b /xC-gen-proto-go.awk | |
parent | f89f21a47fd2764ab48d908dd93dd78f8ff8b471 (diff) | |
download | xK-c1d2e38840c0596efd10e97ff5a9edaa20d5457e.tar.gz xK-c1d2e38840c0596efd10e97ff5a9edaa20d5457e.tar.xz xK-c1d2e38840c0596efd10e97ff5a9edaa20d5457e.zip |
xP: generate our own JSON marshallers
For non-trivial types, which are expensive to serialize
with encoding/json's struct reflection.
Diffstat (limited to 'xC-gen-proto-go.awk')
-rw-r--r-- | xC-gen-proto-go.awk | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/xC-gen-proto-go.awk b/xC-gen-proto-go.awk index 4220ccc..eb08477 100644 --- a/xC-gen-proto-go.awk +++ b/xC-gen-proto-go.awk @@ -206,13 +206,14 @@ function codegen_enum(name, cg, gotype, fields) { print "}" print "" + CodegenIsMarshaler[name] = 1 fields = cg["marshal"] sub(/,\n$/, ":", fields) gsub(/\n/, "\n\t", fields) print "func (v " gotype ") MarshalJSON() ([]byte, error) {" print "\tswitch v {" print indent("case " fields) - print "\t\treturn json.Marshal(v.String())" + print "\t\treturn []byte(`\"` + v.String() + `\"`), nil" print "\t}" print "\treturn json.Marshal(int(v))" print "}" @@ -252,7 +253,50 @@ function codegen_enum(name, cg, gotype, fields) { delete cg[i] } +function codegen_struct_field_marshal(d, cg, camel, f, marshal) { + camel = snaketocamel(d["name"]) + f = "s." camel + + # Complex types are json.Marshalers, there's no need to json.Marshal(&f). + if (!d["isarray"]) { + if (CodegenIsMarshaler[d["type"]]) + marshal = f ".MarshalJSON()" + else + marshal = "json.Marshal(" f ")" + + append(cg, "marshal", + "\tb = append(b, `,\"" decapitalize(camel) "\":`...)\n" \ + "\tif j, err := " marshal "; err != nil {\n" \ + "\t\treturn nil, err\n" \ + "\t} else {\n" \ + "\t\tb = append(b, j...)\n" \ + "\t}\n") + return + } + + if (CodegenIsMarshaler[d["type"]]) + marshal = f "[i].MarshalJSON()" + else + marshal = "json.Marshal(" f "[i])" + + append(cg, "marshal", + "\tb = append(b, `,\"" decapitalize(camel) "\":[`...)\n" \ + "\tfor i := 0; i < len(" f "); i++ {\n" \ + "\t\tif i > 0 {\n" \ + "\t\t\tb = append(b, ',')\n" \ + "\t\t}\n" \ + "\t\tif j, err := " marshal "; err != nil {\n" \ + "\t\t\treturn nil, err\n" \ + "\t\t} else {\n" \ + "\t\t\tb = append(b, j...)\n" \ + "\t\t}\n" \ + "\t}\n" \ + "\tb = append(b, ']')\n") +} + function codegen_struct_field(d, cg, camel, f, serialize, deserialize) { + codegen_struct_field_marshal(d, cg) + camel = snaketocamel(d["name"]) f = "s." camel serialize = CodegenSerialize[d["type"]] @@ -303,6 +347,8 @@ function codegen_struct_field(d, cg, camel, f, serialize, deserialize) { } function codegen_struct_tag(d, cg, camel, f) { + codegen_struct_field_marshal(d, cg) + camel = snaketocamel(d["name"]) f = "s." camel append(cg, "fields", "\t" camel " " CodegenGoType[d["type"]] \ @@ -315,6 +361,16 @@ function codegen_struct(name, cg, gotype) { gotype = PrefixCamel name print "type " gotype " struct {\n" cg["fields"] "}\n" + if (cg["marshal"]) { + CodegenIsMarshaler[name] = 1 + print "func (s *" gotype ") MarshalJSON() ([]byte, error) {" + print "\tb := []byte{}" + print cg["marshal"] "\tb[0] = '{'" + print "\treturn append(b, '}'), nil" + print "}" + print "" + } + if (cg["serialize"]) { print "func (s *" gotype ") AppendTo(data []byte) ([]byte, bool) {" print "\tok := true" @@ -362,15 +418,15 @@ function codegen_union_struct(name, casename, cg, scg, structname, init) { "\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \ "\t\ts := " init "\n" \ "\t\terr = json.Unmarshal(data, &s)\n" \ - "\t\tu.Interface = s\n") + "\t\tu.Interface = &s\n") append(cg, "serialize", - "\tcase " CodegenGoType[structname] ":\n" \ + "\tcase *" CodegenGoType[structname] ":\n" \ indent(sprintf(CodegenSerialize[structname], "union"))) append(cg, "deserialize", "\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \ "\t\ts := " init "\n" \ indent(sprintf(CodegenDeserialize[structname], "s")) \ - "\t\tu.Interface = s\n") + "\t\tu.Interface = &s\n") } function codegen_union(name, cg, gotype, tagfield, tagvar) { @@ -381,8 +437,9 @@ function codegen_union(name, cg, gotype, tagfield, tagvar) { print "" # This cannot be a pointer method, it wouldn't work recursively. + CodegenIsMarshaler[name] = 1 print "func (u " gotype ") MarshalJSON() ([]byte, error) {" - print "\treturn json.Marshal(u.Interface)" + print "\treturn u.Interface.(json.Marshaler).MarshalJSON()" print "}" print "" |