124 lines
4.4 KiB
Go
124 lines
4.4 KiB
Go
package internalgengo
|
|
|
|
import (
|
|
"google.golang.org/protobuf/compiler/protogen"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
var protowirePackage = protogen.GoImportPath("google.golang.org/protobuf/encoding/protowire")
|
|
|
|
func emitStableSize(g *protogen.GeneratedFile, msg *protogen.Message) {
|
|
fs := sortFields(msg.Fields)
|
|
|
|
g.P("// StableSize returns the size of x in protobuf format.")
|
|
g.P("//")
|
|
g.P("// Structures with the same field values have the same binary size.")
|
|
g.P("func (x *", msg.GoIdent.GoName, ") StableSize() (size int) {")
|
|
g.P("if x == nil { return 0 }")
|
|
if len(fs) != 0 {
|
|
for _, f := range fs {
|
|
if f.Desc.IsList() && marshalers[f.Desc.Kind()].RepeatedDouble && !(f.Desc.Kind() == protoreflect.Uint64Kind && !f.Desc.IsPacked()) {
|
|
g.P("var n int")
|
|
break
|
|
}
|
|
}
|
|
for _, f := range fs {
|
|
emitFieldSize(g, f)
|
|
}
|
|
}
|
|
g.P("return size")
|
|
g.P("}\n")
|
|
}
|
|
|
|
func emitSignatureMethods(g *protogen.GeneratedFile, msg *protogen.Message) {
|
|
// SignedDataSize implementation (only for requests and responses).
|
|
g.P("// ReadSignedData fills buf with signed data of x.")
|
|
g.P("// If buffer length is less than x.SignedDataSize(), new buffer is allocated.")
|
|
g.P("//")
|
|
g.P("// Returns any error encountered which did not allow writing the data completely.")
|
|
g.P("// Otherwise, returns the buffer in which the data is written.")
|
|
g.P("//")
|
|
g.P("// Structures with the same field values have the same signed data.")
|
|
g.P("func (x *", msg.GoIdent.GoName, ") SignedDataSize() int {")
|
|
g.P("return x.GetBody().StableSize()")
|
|
g.P("}\n")
|
|
|
|
// ReadSignedData implementation (only for requests and responses).
|
|
g.P("// SignedDataSize returns size of the request signed data in bytes.")
|
|
g.P("//")
|
|
g.P("// Structures with the same field values have the same signed data size.")
|
|
g.P("func (x *", msg.GoIdent.GoName, ") ReadSignedData(buf []byte) ([]byte, error) {")
|
|
g.P("return x.GetBody().MarshalProtobuf(buf), nil")
|
|
g.P("}\n")
|
|
}
|
|
|
|
func emitFieldSize(g *protogen.GeneratedFile, f *protogen.Field) {
|
|
m := marshalers[f.Desc.Kind()]
|
|
if m.Prefix == "" {
|
|
g.P("// FIXME missing field marshaler: ", f.GoName, " of type ", f.Desc.Kind().String())
|
|
g.P(`panic("unimplemented")`)
|
|
return
|
|
}
|
|
|
|
name := castFieldName(f)
|
|
if f.Oneof != nil {
|
|
name = "x." + f.Oneof.GoName
|
|
g.P("if inner, ok := ", name, ".(*", f.GoIdent.GoName, "); ok {")
|
|
defer g.P("}")
|
|
name = "inner." + f.GoName
|
|
}
|
|
|
|
switch {
|
|
case f.Desc.IsList() && (f.Desc.Kind() == protoreflect.MessageKind || f.Desc.Kind() == protoreflect.Uint64Kind && !f.Desc.IsPacked()):
|
|
g.P("for i := range ", name, "{")
|
|
if f.Desc.Kind() == protoreflect.MessageKind {
|
|
g.P("size += ", protoPackage.Ident("NestedStructureSize"), "(", f.Desc.Number(), ", ", name, "[i])")
|
|
} else {
|
|
if f.Desc.Kind() != protoreflect.Uint64Kind {
|
|
panic("only uint64 unpacked primitive is supported")
|
|
}
|
|
|
|
g.P("size += ", protowirePackage.Ident("SizeGroup"), "(",
|
|
protowirePackage.Ident("Number"), "(", f.Desc.Number(), "), ",
|
|
protowirePackage.Ident("SizeVarint"), "(", name, "[i]))")
|
|
}
|
|
g.P("}")
|
|
|
|
case f.Desc.IsList():
|
|
if m.RepeatedDouble {
|
|
g.P("n, _ = ", protoPackage.Ident("Repeated"+m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")")
|
|
g.P("size += n")
|
|
} else {
|
|
g.P("size += ", protoPackage.Ident("Repeated"+m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")")
|
|
}
|
|
default:
|
|
g.P("size += ", protoPackage.Ident(m.Prefix+"Size"), "(", f.Desc.Number(), ", ", name, ")")
|
|
}
|
|
}
|
|
|
|
type marshalerDesc struct {
|
|
Prefix string
|
|
RepeatedDouble bool
|
|
}
|
|
|
|
// Unused kinds are commented.
|
|
var marshalers = map[protoreflect.Kind]marshalerDesc{
|
|
protoreflect.BoolKind: {Prefix: "Bool"},
|
|
protoreflect.EnumKind: {Prefix: "Enum"},
|
|
protoreflect.Int32Kind: {Prefix: "Int32", RepeatedDouble: true},
|
|
// protoreflect.Sint32Kind: "",
|
|
protoreflect.Uint32Kind: {Prefix: "UInt32", RepeatedDouble: true},
|
|
protoreflect.Int64Kind: {Prefix: "Int64", RepeatedDouble: true},
|
|
// protoreflect.Sint64Kind: "",
|
|
protoreflect.Uint64Kind: {Prefix: "UInt64", RepeatedDouble: true},
|
|
// protoreflect.Sfixed32Kind: "",
|
|
protoreflect.Fixed32Kind: {Prefix: "Fixed32", RepeatedDouble: true},
|
|
// protoreflect.FloatKind: "",
|
|
// protoreflect.Sfixed64Kind: "",
|
|
protoreflect.Fixed64Kind: {Prefix: "Fixed64", RepeatedDouble: true},
|
|
protoreflect.DoubleKind: {Prefix: "Float64"},
|
|
protoreflect.StringKind: {Prefix: "String"},
|
|
protoreflect.BytesKind: {Prefix: "Bytes"},
|
|
protoreflect.MessageKind: {Prefix: "NestedStructure"},
|
|
// protoreflect.GroupKind: "",
|
|
}
|