xP: generate our own JSON marshallers
For non-trivial types, which are expensive to serialize with encoding/json's struct reflection.
This commit is contained in:
parent
f89f21a47f
commit
c1d2e38840
@ -206,13 +206,14 @@ function codegen_enum(name, cg, gotype, fields) {
|
|||||||
print "}"
|
print "}"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
|
CodegenIsMarshaler[name] = 1
|
||||||
fields = cg["marshal"]
|
fields = cg["marshal"]
|
||||||
sub(/,\n$/, ":", fields)
|
sub(/,\n$/, ":", fields)
|
||||||
gsub(/\n/, "\n\t", fields)
|
gsub(/\n/, "\n\t", fields)
|
||||||
print "func (v " gotype ") MarshalJSON() ([]byte, error) {"
|
print "func (v " gotype ") MarshalJSON() ([]byte, error) {"
|
||||||
print "\tswitch v {"
|
print "\tswitch v {"
|
||||||
print indent("case " fields)
|
print indent("case " fields)
|
||||||
print "\t\treturn json.Marshal(v.String())"
|
print "\t\treturn []byte(`\"` + v.String() + `\"`), nil"
|
||||||
print "\t}"
|
print "\t}"
|
||||||
print "\treturn json.Marshal(int(v))"
|
print "\treturn json.Marshal(int(v))"
|
||||||
print "}"
|
print "}"
|
||||||
@ -252,7 +253,50 @@ function codegen_enum(name, cg, gotype, fields) {
|
|||||||
delete cg[i]
|
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) {
|
function codegen_struct_field(d, cg, camel, f, serialize, deserialize) {
|
||||||
|
codegen_struct_field_marshal(d, cg)
|
||||||
|
|
||||||
camel = snaketocamel(d["name"])
|
camel = snaketocamel(d["name"])
|
||||||
f = "s." camel
|
f = "s." camel
|
||||||
serialize = CodegenSerialize[d["type"]]
|
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) {
|
function codegen_struct_tag(d, cg, camel, f) {
|
||||||
|
codegen_struct_field_marshal(d, cg)
|
||||||
|
|
||||||
camel = snaketocamel(d["name"])
|
camel = snaketocamel(d["name"])
|
||||||
f = "s." camel
|
f = "s." camel
|
||||||
append(cg, "fields", "\t" camel " " CodegenGoType[d["type"]] \
|
append(cg, "fields", "\t" camel " " CodegenGoType[d["type"]] \
|
||||||
@ -315,6 +361,16 @@ function codegen_struct(name, cg, gotype) {
|
|||||||
gotype = PrefixCamel name
|
gotype = PrefixCamel name
|
||||||
print "type " gotype " struct {\n" cg["fields"] "}\n"
|
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"]) {
|
if (cg["serialize"]) {
|
||||||
print "func (s *" gotype ") AppendTo(data []byte) ([]byte, bool) {"
|
print "func (s *" gotype ") AppendTo(data []byte) ([]byte, bool) {"
|
||||||
print "\tok := true"
|
print "\tok := true"
|
||||||
@ -362,15 +418,15 @@ function codegen_union_struct(name, casename, cg, scg, structname, init) {
|
|||||||
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
||||||
"\t\ts := " init "\n" \
|
"\t\ts := " init "\n" \
|
||||||
"\t\terr = json.Unmarshal(data, &s)\n" \
|
"\t\terr = json.Unmarshal(data, &s)\n" \
|
||||||
"\t\tu.Interface = s\n")
|
"\t\tu.Interface = &s\n")
|
||||||
append(cg, "serialize",
|
append(cg, "serialize",
|
||||||
"\tcase " CodegenGoType[structname] ":\n" \
|
"\tcase *" CodegenGoType[structname] ":\n" \
|
||||||
indent(sprintf(CodegenSerialize[structname], "union")))
|
indent(sprintf(CodegenSerialize[structname], "union")))
|
||||||
append(cg, "deserialize",
|
append(cg, "deserialize",
|
||||||
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
"\tcase " CodegenGoType[cg["tagtype"]] snaketocamel(casename) ":\n" \
|
||||||
"\t\ts := " init "\n" \
|
"\t\ts := " init "\n" \
|
||||||
indent(sprintf(CodegenDeserialize[structname], "s")) \
|
indent(sprintf(CodegenDeserialize[structname], "s")) \
|
||||||
"\t\tu.Interface = s\n")
|
"\t\tu.Interface = &s\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function codegen_union(name, cg, gotype, tagfield, tagvar) {
|
function codegen_union(name, cg, gotype, tagfield, tagvar) {
|
||||||
@ -381,8 +437,9 @@ function codegen_union(name, cg, gotype, tagfield, tagvar) {
|
|||||||
print ""
|
print ""
|
||||||
|
|
||||||
# This cannot be a pointer method, it wouldn't work recursively.
|
# This cannot be a pointer method, it wouldn't work recursively.
|
||||||
|
CodegenIsMarshaler[name] = 1
|
||||||
print "func (u " gotype ") MarshalJSON() ([]byte, error) {"
|
print "func (u " gotype ") MarshalJSON() ([]byte, error) {"
|
||||||
print "\treturn json.Marshal(u.Interface)"
|
print "\treturn u.Interface.(json.Marshaler).MarshalJSON()"
|
||||||
print "}"
|
print "}"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
|
6
xP/xP.go
6
xP/xP.go
@ -50,7 +50,7 @@ func relayReadJSON(conn net.Conn) []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
j, err := json.Marshal(&m)
|
j, err := m.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Event marshalling failed: " + err.Error())
|
log.Println("Event marshalling failed: " + err.Error())
|
||||||
return nil
|
return nil
|
||||||
@ -126,7 +126,7 @@ func clientWriteJSON(ctx context.Context, ws *websocket.Conn, j []byte) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func clientWriteError(ctx context.Context, ws *websocket.Conn, err error) bool {
|
func clientWriteError(ctx context.Context, ws *websocket.Conn, err error) bool {
|
||||||
j, err := json.Marshal(&RelayEventMessage{
|
j, err := (&RelayEventMessage{
|
||||||
EventSeq: 0,
|
EventSeq: 0,
|
||||||
Data: RelayEventData{
|
Data: RelayEventData{
|
||||||
Interface: RelayEventDataError{
|
Interface: RelayEventDataError{
|
||||||
@ -135,7 +135,7 @@ func clientWriteError(ctx context.Context, ws *websocket.Conn, err error) bool {
|
|||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
}).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Event marshalling failed: " + err.Error())
|
log.Println("Event marshalling failed: " + err.Error())
|
||||||
return false
|
return false
|
||||||
|
Loading…
Reference in New Issue
Block a user