Evgenii Stratonikov
5e1c6a908f
All checks were successful
DCO action / DCO (pull_request) Successful in 41s
Tests and linters / Tests (1.22) (pull_request) Successful in 55s
Tests and linters / Tests (1.23) (pull_request) Successful in 57s
Tests and linters / Tests with -race (pull_request) Successful in 1m8s
Tests and linters / Lint (pull_request) Successful in 2m12s
``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ ObjectIDSlice/0_elements/to_grpc_message-8 3.193n ± 2% 3.242n ± 0% +1.50% (p=0.034 n=10) ObjectIDSlice/0_elements/from_grpc_message-8 3.197n ± 2% 3.343n ± 1% +4.57% (p=0.000 n=10) ObjectIDSlice/0_elements/marshal-8 5.666n ± 3% 5.642n ± 0% -0.42% (p=0.000 n=10) ObjectIDSlice/1_elements/to_grpc_message-8 53.10n ± 6% 29.78n ± 12% -43.92% (p=0.000 n=10) ObjectIDSlice/1_elements/from_grpc_message-8 28.99n ± 5% 29.77n ± 7% ~ (p=0.165 n=10) ObjectIDSlice/1_elements/marshal-8 49.08n ± 7% 50.72n ± 6% ~ (p=0.218 n=10) ObjectIDSlice/50_elements/to_grpc_message-8 1652.5n ± 7% 277.2n ± 1% -83.22% (p=0.000 n=10) ObjectIDSlice/50_elements/from_grpc_message-8 261.2n ± 11% 226.7n ± 15% -13.19% (p=0.003 n=10) ObjectIDSlice/50_elements/marshal-8 1.512µ ± 6% 1.514µ ± 6% ~ (p=0.955 n=10) geomean 52.15n 39.99n -23.31% │ old │ new │ │ B/op │ B/op vs base │ ObjectIDSlice/0_elements/to_grpc_message-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/0_elements/from_grpc_message-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/0_elements/marshal-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/1_elements/to_grpc_message-8 32.00 ± 0% 24.00 ± 0% -25.00% (p=0.000 n=10) ObjectIDSlice/1_elements/from_grpc_message-8 24.00 ± 0% 24.00 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/1_elements/marshal-8 48.00 ± 0% 48.00 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/50_elements/to_grpc_message-8 1.578Ki ± 0% 1.250Ki ± 0% -20.79% (p=0.000 n=10) ObjectIDSlice/50_elements/from_grpc_message-8 1.250Ki ± 0% 1.250Ki ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/50_elements/marshal-8 2.000Ki ± 0% 2.000Ki ± 0% ~ (p=1.000 n=10) ¹ geomean ² -5.62% ² ¹ all samples are equal ² summaries must be >0 to compute geomean │ old │ new │ │ allocs/op │ allocs/op vs base │ ObjectIDSlice/0_elements/to_grpc_message-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/0_elements/from_grpc_message-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/0_elements/marshal-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/1_elements/to_grpc_message-8 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.000 n=10) ObjectIDSlice/1_elements/from_grpc_message-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/1_elements/marshal-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/50_elements/to_grpc_message-8 51.000 ± 0% 1.000 ± 0% -98.04% (p=0.000 n=10) ObjectIDSlice/50_elements/from_grpc_message-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ ObjectIDSlice/50_elements/marshal-8 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ geomean ² -40.18% ² ¹ all samples are equal ² summaries must be >0 to compute geomean ``` Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
228 lines
6.1 KiB
Go
228 lines
6.1 KiB
Go
package internalgengo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"google.golang.org/protobuf/compiler/protogen"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
var (
|
|
jwriterPackage = protogen.GoImportPath("github.com/mailru/easyjson/jwriter")
|
|
jlexerPackage = protogen.GoImportPath("github.com/mailru/easyjson/jlexer")
|
|
)
|
|
|
|
func emitJSONMethods(g *protogen.GeneratedFile, msg *protogen.Message) {
|
|
emitJSONMarshal(g, msg)
|
|
emitJSONUnmarshal(g, msg)
|
|
}
|
|
|
|
func emitJSONUnmarshal(g *protogen.GeneratedFile, msg *protogen.Message) {
|
|
g.P("// UnmarshalJSON implements the json.Unmarshaler interface.")
|
|
g.P("func (x *", msg.GoIdent.GoName, ") UnmarshalJSON(data []byte) error {")
|
|
g.P("r := ", jlexerPackage.Ident("Lexer"), "{Data: data}")
|
|
g.P("x.UnmarshalEasyJSON(&r)")
|
|
g.P("return r.Error()")
|
|
g.P("}")
|
|
|
|
g.P("func (x *", msg.GoIdent.GoName, ") UnmarshalEasyJSON(in *", jlexerPackage.Ident("Lexer"), ") {")
|
|
|
|
g.P("isTopLevel := in.IsStart()")
|
|
g.P("if in.IsNull() {")
|
|
g.P("if isTopLevel { in.Consumed() }")
|
|
g.P("in.Skip()")
|
|
g.P("return")
|
|
g.P("}")
|
|
|
|
g.P("in.Delim('{')")
|
|
g.P("for !in.IsDelim('}') {")
|
|
|
|
g.P("key := in.UnsafeFieldName(false)")
|
|
g.P("in.WantColon()")
|
|
g.P("if in.IsNull() { in.Skip(); in.WantComma(); continue }")
|
|
g.P("switch key {")
|
|
for _, f := range msg.Fields {
|
|
g.P(`case "`, fieldJSONName(f), `":`)
|
|
if f.Oneof != nil {
|
|
g.P("xx := new(", f.GoIdent, ")")
|
|
g.P("x." + f.Oneof.GoName + " = xx")
|
|
emitJSONFieldRead(g, f, "xx")
|
|
continue
|
|
}
|
|
emitJSONFieldRead(g, f, "x")
|
|
}
|
|
g.P("}")
|
|
g.P("in.WantComma()")
|
|
g.P("}")
|
|
g.P("in.Delim('}')")
|
|
g.P("if isTopLevel { in.Consumed() }")
|
|
g.P("}")
|
|
}
|
|
|
|
func emitJSONFieldRead(g *protogen.GeneratedFile, f *protogen.Field, name string) {
|
|
g.P("{")
|
|
defer g.P("}")
|
|
|
|
if f.Desc.IsList() {
|
|
g.P("var f ", fieldType(g, f)[2:])
|
|
g.P("var list ", fieldType(g, f))
|
|
g.P("in.Delim('[')")
|
|
defer g.P("in.Delim(']')")
|
|
|
|
g.P("for !in.IsDelim(']') {")
|
|
} else {
|
|
g.P("var f ", fieldType(g, f))
|
|
}
|
|
|
|
var template string
|
|
switch f.Desc.Kind() {
|
|
case protoreflect.BoolKind:
|
|
template = "%s = in.Bool()"
|
|
case protoreflect.EnumKind:
|
|
g.Import(strconvPackage)
|
|
|
|
enumType := fieldType(g, f).String()
|
|
g.P("var parsedValue " + enumType)
|
|
g.P(`switch v := in.Interface().(type) {
|
|
case string:
|
|
if vv, ok := `+enumType+`_value[v]; ok {
|
|
parsedValue = `+enumType+`(vv)
|
|
break
|
|
}
|
|
vv, err := `, strconvPackage.Ident("ParseInt"), `(v, 10, 32)
|
|
if err != nil {
|
|
in.AddError(err)
|
|
return
|
|
}
|
|
parsedValue = `+enumType+`(vv)
|
|
case float64:
|
|
parsedValue = `+enumType+`(v)
|
|
}`)
|
|
template = "%s = parsedValue"
|
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
|
template = "%s = in.Int32()"
|
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
|
template = "%s = in.Uint32()"
|
|
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
|
template = "%s = in.Int64()"
|
|
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
|
template = "%s = in.Uint64()"
|
|
case protoreflect.FloatKind:
|
|
template = "%s = in.Float32()"
|
|
case protoreflect.DoubleKind:
|
|
template = "%s = in.Float64()"
|
|
case protoreflect.StringKind:
|
|
template = "%s = in.String()"
|
|
case protoreflect.BytesKind:
|
|
template = "%s = in.Bytes()"
|
|
case protoreflect.MessageKind:
|
|
if f.Desc.IsList() {
|
|
g.P("f = ", fieldType(g, f)[2:], "{}")
|
|
} else {
|
|
g.P("f = new(", fieldType(g, f)[1:], ")")
|
|
}
|
|
template = "%s.UnmarshalEasyJSON(in)"
|
|
case protoreflect.GroupKind:
|
|
panic("unimplemented")
|
|
}
|
|
g.P(fmt.Sprintf(template, "f"))
|
|
if f.Desc.IsList() {
|
|
g.P("list = append(list, f)")
|
|
g.P("in.WantComma()")
|
|
g.P("}")
|
|
g.P(name, ".", f.GoName, " = list")
|
|
} else {
|
|
g.P(name, ".", f.GoName, " = f")
|
|
}
|
|
}
|
|
|
|
func emitJSONMarshal(g *protogen.GeneratedFile, msg *protogen.Message) {
|
|
g.P("// MarshalJSON implements the json.Marshaler interface.")
|
|
g.P("func (x *", msg.GoIdent.GoName, ") MarshalJSON() ([]byte, error) {")
|
|
g.P("w := ", jwriterPackage.Ident("Writer"), "{}")
|
|
g.P("x.MarshalEasyJSON(&w)")
|
|
g.P("return w.Buffer.BuildBytes(), w.Error")
|
|
g.P("}")
|
|
|
|
g.P("func (x *", msg.GoIdent.GoName, ") MarshalEasyJSON(out *", jwriterPackage.Ident("Writer"), ") {")
|
|
g.P(`if x == nil { out.RawString("null"); return }`)
|
|
|
|
g.P("out.RawByte('{')")
|
|
for i, f := range msg.Fields {
|
|
if f.Oneof != nil {
|
|
if f.Oneof.Fields[0] != f {
|
|
continue
|
|
}
|
|
|
|
g.P("switch xx := x.", f.Oneof.GoName, ".(type) {")
|
|
for _, ff := range f.Oneof.Fields {
|
|
g.P("case *", ff.GoIdent, ":")
|
|
emitJSONFieldWrite(g, ff, "xx", i == 0)
|
|
}
|
|
g.P("}")
|
|
continue
|
|
}
|
|
emitJSONFieldWrite(g, f, "x", i == 0)
|
|
}
|
|
g.P("out.RawByte('}')")
|
|
g.P("}")
|
|
}
|
|
|
|
func emitJSONFieldWrite(g *protogen.GeneratedFile, f *protogen.Field, name string, first bool) {
|
|
g.P("{")
|
|
defer g.P("}")
|
|
|
|
g.P("const prefix string = ", `",\"`, fieldJSONName(f), `\":"`)
|
|
if first {
|
|
g.P("out.RawString(prefix[1:])")
|
|
} else {
|
|
g.P("out.RawString(prefix)")
|
|
}
|
|
|
|
selector := name + "." + f.GoName
|
|
if f.Desc.IsList() {
|
|
selector += "[i]"
|
|
g.P("out.RawByte('[')")
|
|
defer g.P("out.RawByte(']')")
|
|
|
|
g.P("for i := range ", name, ".", f.GoName, " {")
|
|
g.P("if i != 0 { out.RawByte(',') }")
|
|
defer g.P("}")
|
|
}
|
|
|
|
var template string
|
|
switch f.Desc.Kind() {
|
|
case protoreflect.BoolKind:
|
|
template = "out.Bool(%s)"
|
|
case protoreflect.EnumKind:
|
|
template = "out.Int32(int32(%s))"
|
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
|
template = "out.Int32(%s)"
|
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
|
template = "out.Uint32(%s)"
|
|
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
|
template = "out.Int64(%s)"
|
|
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
|
template = "out.Uint64(%s)"
|
|
case protoreflect.FloatKind:
|
|
template = "out.Float32(%s)"
|
|
case protoreflect.DoubleKind:
|
|
template = "out.Float64(%s)"
|
|
case protoreflect.StringKind:
|
|
template = "out.String(%s)"
|
|
case protoreflect.BytesKind:
|
|
template = "out.Base64Bytes(%s)"
|
|
case protoreflect.MessageKind:
|
|
template = "%s.MarshalEasyJSON(out)"
|
|
case protoreflect.GroupKind:
|
|
panic("unimplemented")
|
|
}
|
|
g.P(fmt.Sprintf(template, selector))
|
|
}
|
|
|
|
func fieldJSONName(f *protogen.Field) string {
|
|
if f.Desc.HasJSONName() {
|
|
return f.Desc.JSONName()
|
|
}
|
|
return string(f.Desc.Name())
|
|
}
|