1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsenpackage internal_gengo 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "fmt" 9*1c12ee1eSDan Willemsen "math" 10*1c12ee1eSDan Willemsen "strings" 11*1c12ee1eSDan Willemsen "unicode/utf8" 12*1c12ee1eSDan Willemsen 13*1c12ee1eSDan Willemsen "google.golang.org/protobuf/compiler/protogen" 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protopath" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protorange" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 18*1c12ee1eSDan Willemsen 19*1c12ee1eSDan Willemsen "google.golang.org/protobuf/types/descriptorpb" 20*1c12ee1eSDan Willemsen) 21*1c12ee1eSDan Willemsen 22*1c12ee1eSDan Willemsenfunc genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { 23*1c12ee1eSDan Willemsen g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor")) 24*1c12ee1eSDan Willemsen g.P() 25*1c12ee1eSDan Willemsen 26*1c12ee1eSDan Willemsen genFileDescriptor(gen, g, f) 27*1c12ee1eSDan Willemsen if len(f.allEnums) > 0 { 28*1c12ee1eSDan Willemsen g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")") 29*1c12ee1eSDan Willemsen } 30*1c12ee1eSDan Willemsen if len(f.allMessages) > 0 { 31*1c12ee1eSDan Willemsen g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")") 32*1c12ee1eSDan Willemsen } 33*1c12ee1eSDan Willemsen 34*1c12ee1eSDan Willemsen // Generate a unique list of Go types for all declarations and dependencies, 35*1c12ee1eSDan Willemsen // and the associated index into the type list for all dependencies. 36*1c12ee1eSDan Willemsen var goTypes []string 37*1c12ee1eSDan Willemsen var depIdxs []string 38*1c12ee1eSDan Willemsen seen := map[protoreflect.FullName]int{} 39*1c12ee1eSDan Willemsen genDep := func(name protoreflect.FullName, depSource string) { 40*1c12ee1eSDan Willemsen if depSource != "" { 41*1c12ee1eSDan Willemsen line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name) 42*1c12ee1eSDan Willemsen depIdxs = append(depIdxs, line) 43*1c12ee1eSDan Willemsen } 44*1c12ee1eSDan Willemsen } 45*1c12ee1eSDan Willemsen genEnum := func(e *protogen.Enum, depSource string) { 46*1c12ee1eSDan Willemsen if e != nil { 47*1c12ee1eSDan Willemsen name := e.Desc.FullName() 48*1c12ee1eSDan Willemsen if _, ok := seen[name]; !ok { 49*1c12ee1eSDan Willemsen line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name) 50*1c12ee1eSDan Willemsen goTypes = append(goTypes, line) 51*1c12ee1eSDan Willemsen seen[name] = len(seen) 52*1c12ee1eSDan Willemsen } 53*1c12ee1eSDan Willemsen if depSource != "" { 54*1c12ee1eSDan Willemsen genDep(name, depSource) 55*1c12ee1eSDan Willemsen } 56*1c12ee1eSDan Willemsen } 57*1c12ee1eSDan Willemsen } 58*1c12ee1eSDan Willemsen genMessage := func(m *protogen.Message, depSource string) { 59*1c12ee1eSDan Willemsen if m != nil { 60*1c12ee1eSDan Willemsen name := m.Desc.FullName() 61*1c12ee1eSDan Willemsen if _, ok := seen[name]; !ok { 62*1c12ee1eSDan Willemsen line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name) 63*1c12ee1eSDan Willemsen if m.Desc.IsMapEntry() { 64*1c12ee1eSDan Willemsen // Map entry messages have no associated Go type. 65*1c12ee1eSDan Willemsen line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name) 66*1c12ee1eSDan Willemsen } 67*1c12ee1eSDan Willemsen goTypes = append(goTypes, line) 68*1c12ee1eSDan Willemsen seen[name] = len(seen) 69*1c12ee1eSDan Willemsen } 70*1c12ee1eSDan Willemsen if depSource != "" { 71*1c12ee1eSDan Willemsen genDep(name, depSource) 72*1c12ee1eSDan Willemsen } 73*1c12ee1eSDan Willemsen } 74*1c12ee1eSDan Willemsen } 75*1c12ee1eSDan Willemsen 76*1c12ee1eSDan Willemsen // This ordering is significant. 77*1c12ee1eSDan Willemsen // See filetype.TypeBuilder.DependencyIndexes. 78*1c12ee1eSDan Willemsen type offsetEntry struct { 79*1c12ee1eSDan Willemsen start int 80*1c12ee1eSDan Willemsen name string 81*1c12ee1eSDan Willemsen } 82*1c12ee1eSDan Willemsen var depOffsets []offsetEntry 83*1c12ee1eSDan Willemsen for _, enum := range f.allEnums { 84*1c12ee1eSDan Willemsen genEnum(enum.Enum, "") 85*1c12ee1eSDan Willemsen } 86*1c12ee1eSDan Willemsen for _, message := range f.allMessages { 87*1c12ee1eSDan Willemsen genMessage(message.Message, "") 88*1c12ee1eSDan Willemsen } 89*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"}) 90*1c12ee1eSDan Willemsen for _, message := range f.allMessages { 91*1c12ee1eSDan Willemsen for _, field := range message.Fields { 92*1c12ee1eSDan Willemsen if field.Desc.IsWeak() { 93*1c12ee1eSDan Willemsen continue 94*1c12ee1eSDan Willemsen } 95*1c12ee1eSDan Willemsen source := string(field.Desc.FullName()) 96*1c12ee1eSDan Willemsen genEnum(field.Enum, source+":type_name") 97*1c12ee1eSDan Willemsen genMessage(field.Message, source+":type_name") 98*1c12ee1eSDan Willemsen } 99*1c12ee1eSDan Willemsen } 100*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"}) 101*1c12ee1eSDan Willemsen for _, extension := range f.allExtensions { 102*1c12ee1eSDan Willemsen source := string(extension.Desc.FullName()) 103*1c12ee1eSDan Willemsen genMessage(extension.Extendee, source+":extendee") 104*1c12ee1eSDan Willemsen } 105*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"}) 106*1c12ee1eSDan Willemsen for _, extension := range f.allExtensions { 107*1c12ee1eSDan Willemsen source := string(extension.Desc.FullName()) 108*1c12ee1eSDan Willemsen genEnum(extension.Enum, source+":type_name") 109*1c12ee1eSDan Willemsen genMessage(extension.Message, source+":type_name") 110*1c12ee1eSDan Willemsen } 111*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"}) 112*1c12ee1eSDan Willemsen for _, service := range f.Services { 113*1c12ee1eSDan Willemsen for _, method := range service.Methods { 114*1c12ee1eSDan Willemsen source := string(method.Desc.FullName()) 115*1c12ee1eSDan Willemsen genMessage(method.Input, source+":input_type") 116*1c12ee1eSDan Willemsen } 117*1c12ee1eSDan Willemsen } 118*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"}) 119*1c12ee1eSDan Willemsen for _, service := range f.Services { 120*1c12ee1eSDan Willemsen for _, method := range service.Methods { 121*1c12ee1eSDan Willemsen source := string(method.Desc.FullName()) 122*1c12ee1eSDan Willemsen genMessage(method.Output, source+":output_type") 123*1c12ee1eSDan Willemsen } 124*1c12ee1eSDan Willemsen } 125*1c12ee1eSDan Willemsen depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""}) 126*1c12ee1eSDan Willemsen for i := len(depOffsets) - 2; i >= 0; i-- { 127*1c12ee1eSDan Willemsen curr, next := depOffsets[i], depOffsets[i+1] 128*1c12ee1eSDan Willemsen depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s", 129*1c12ee1eSDan Willemsen curr.start, curr.start, next.start, curr.name)) 130*1c12ee1eSDan Willemsen } 131*1c12ee1eSDan Willemsen if len(depIdxs) > math.MaxInt32 { 132*1c12ee1eSDan Willemsen panic("too many dependencies") // sanity check 133*1c12ee1eSDan Willemsen } 134*1c12ee1eSDan Willemsen 135*1c12ee1eSDan Willemsen g.P("var ", goTypesVarName(f), " = []interface{}{") 136*1c12ee1eSDan Willemsen for _, s := range goTypes { 137*1c12ee1eSDan Willemsen g.P(s) 138*1c12ee1eSDan Willemsen } 139*1c12ee1eSDan Willemsen g.P("}") 140*1c12ee1eSDan Willemsen 141*1c12ee1eSDan Willemsen g.P("var ", depIdxsVarName(f), " = []int32{") 142*1c12ee1eSDan Willemsen for _, s := range depIdxs { 143*1c12ee1eSDan Willemsen g.P(s) 144*1c12ee1eSDan Willemsen } 145*1c12ee1eSDan Willemsen g.P("}") 146*1c12ee1eSDan Willemsen 147*1c12ee1eSDan Willemsen g.P("func init() { ", initFuncName(f.File), "() }") 148*1c12ee1eSDan Willemsen 149*1c12ee1eSDan Willemsen g.P("func ", initFuncName(f.File), "() {") 150*1c12ee1eSDan Willemsen g.P("if ", f.GoDescriptorIdent, " != nil {") 151*1c12ee1eSDan Willemsen g.P("return") 152*1c12ee1eSDan Willemsen g.P("}") 153*1c12ee1eSDan Willemsen 154*1c12ee1eSDan Willemsen // Ensure that initialization functions for different files in the same Go 155*1c12ee1eSDan Willemsen // package run in the correct order: Call the init funcs for every .proto file 156*1c12ee1eSDan Willemsen // imported by this one that is in the same Go package. 157*1c12ee1eSDan Willemsen for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ { 158*1c12ee1eSDan Willemsen impFile := gen.FilesByPath[imps.Get(i).Path()] 159*1c12ee1eSDan Willemsen if impFile.GoImportPath != f.GoImportPath { 160*1c12ee1eSDan Willemsen continue 161*1c12ee1eSDan Willemsen } 162*1c12ee1eSDan Willemsen g.P(initFuncName(impFile), "()") 163*1c12ee1eSDan Willemsen } 164*1c12ee1eSDan Willemsen 165*1c12ee1eSDan Willemsen if len(f.allMessages) > 0 { 166*1c12ee1eSDan Willemsen // Populate MessageInfo.Exporters. 167*1c12ee1eSDan Willemsen g.P("if !", protoimplPackage.Ident("UnsafeEnabled"), " {") 168*1c12ee1eSDan Willemsen for _, message := range f.allMessages { 169*1c12ee1eSDan Willemsen if sf := f.allMessageFieldsByPtr[message]; len(sf.unexported) > 0 { 170*1c12ee1eSDan Willemsen idx := f.allMessagesByPtr[message] 171*1c12ee1eSDan Willemsen typesVar := messageTypesVarName(f) 172*1c12ee1eSDan Willemsen 173*1c12ee1eSDan Willemsen g.P(typesVar, "[", idx, "].Exporter = func(v interface{}, i int) interface{} {") 174*1c12ee1eSDan Willemsen g.P("switch v := v.(*", message.GoIdent, "); i {") 175*1c12ee1eSDan Willemsen for i := 0; i < sf.count; i++ { 176*1c12ee1eSDan Willemsen if name := sf.unexported[i]; name != "" { 177*1c12ee1eSDan Willemsen g.P("case ", i, ": return &v.", name) 178*1c12ee1eSDan Willemsen } 179*1c12ee1eSDan Willemsen } 180*1c12ee1eSDan Willemsen g.P("default: return nil") 181*1c12ee1eSDan Willemsen g.P("}") 182*1c12ee1eSDan Willemsen g.P("}") 183*1c12ee1eSDan Willemsen } 184*1c12ee1eSDan Willemsen } 185*1c12ee1eSDan Willemsen g.P("}") 186*1c12ee1eSDan Willemsen 187*1c12ee1eSDan Willemsen // Populate MessageInfo.OneofWrappers. 188*1c12ee1eSDan Willemsen for _, message := range f.allMessages { 189*1c12ee1eSDan Willemsen if len(message.Oneofs) > 0 { 190*1c12ee1eSDan Willemsen idx := f.allMessagesByPtr[message] 191*1c12ee1eSDan Willemsen typesVar := messageTypesVarName(f) 192*1c12ee1eSDan Willemsen 193*1c12ee1eSDan Willemsen // Associate the wrapper types by directly passing them to the MessageInfo. 194*1c12ee1eSDan Willemsen g.P(typesVar, "[", idx, "].OneofWrappers = []interface{} {") 195*1c12ee1eSDan Willemsen for _, oneof := range message.Oneofs { 196*1c12ee1eSDan Willemsen if !oneof.Desc.IsSynthetic() { 197*1c12ee1eSDan Willemsen for _, field := range oneof.Fields { 198*1c12ee1eSDan Willemsen g.P("(*", field.GoIdent, ")(nil),") 199*1c12ee1eSDan Willemsen } 200*1c12ee1eSDan Willemsen } 201*1c12ee1eSDan Willemsen } 202*1c12ee1eSDan Willemsen g.P("}") 203*1c12ee1eSDan Willemsen } 204*1c12ee1eSDan Willemsen } 205*1c12ee1eSDan Willemsen } 206*1c12ee1eSDan Willemsen 207*1c12ee1eSDan Willemsen g.P("type x struct{}") 208*1c12ee1eSDan Willemsen g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{") 209*1c12ee1eSDan Willemsen g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{") 210*1c12ee1eSDan Willemsen g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),") 211*1c12ee1eSDan Willemsen g.P("RawDescriptor: ", rawDescVarName(f), ",") 212*1c12ee1eSDan Willemsen g.P("NumEnums: ", len(f.allEnums), ",") 213*1c12ee1eSDan Willemsen g.P("NumMessages: ", len(f.allMessages), ",") 214*1c12ee1eSDan Willemsen g.P("NumExtensions: ", len(f.allExtensions), ",") 215*1c12ee1eSDan Willemsen g.P("NumServices: ", len(f.Services), ",") 216*1c12ee1eSDan Willemsen g.P("},") 217*1c12ee1eSDan Willemsen g.P("GoTypes: ", goTypesVarName(f), ",") 218*1c12ee1eSDan Willemsen g.P("DependencyIndexes: ", depIdxsVarName(f), ",") 219*1c12ee1eSDan Willemsen if len(f.allEnums) > 0 { 220*1c12ee1eSDan Willemsen g.P("EnumInfos: ", enumTypesVarName(f), ",") 221*1c12ee1eSDan Willemsen } 222*1c12ee1eSDan Willemsen if len(f.allMessages) > 0 { 223*1c12ee1eSDan Willemsen g.P("MessageInfos: ", messageTypesVarName(f), ",") 224*1c12ee1eSDan Willemsen } 225*1c12ee1eSDan Willemsen if len(f.allExtensions) > 0 { 226*1c12ee1eSDan Willemsen g.P("ExtensionInfos: ", extensionTypesVarName(f), ",") 227*1c12ee1eSDan Willemsen } 228*1c12ee1eSDan Willemsen g.P("}.Build()") 229*1c12ee1eSDan Willemsen g.P(f.GoDescriptorIdent, " = out.File") 230*1c12ee1eSDan Willemsen 231*1c12ee1eSDan Willemsen // Set inputs to nil to allow GC to reclaim resources. 232*1c12ee1eSDan Willemsen g.P(rawDescVarName(f), " = nil") 233*1c12ee1eSDan Willemsen g.P(goTypesVarName(f), " = nil") 234*1c12ee1eSDan Willemsen g.P(depIdxsVarName(f), " = nil") 235*1c12ee1eSDan Willemsen g.P("}") 236*1c12ee1eSDan Willemsen} 237*1c12ee1eSDan Willemsen 238*1c12ee1eSDan Willemsen// stripSourceRetentionFieldsFromMessage walks the given message tree recursively 239*1c12ee1eSDan Willemsen// and clears any fields with the field option: [retention = RETENTION_SOURCE] 240*1c12ee1eSDan Willemsenfunc stripSourceRetentionFieldsFromMessage(m protoreflect.Message) { 241*1c12ee1eSDan Willemsen protorange.Range(m, func(ppv protopath.Values) error { 242*1c12ee1eSDan Willemsen m2, ok := ppv.Index(-1).Value.Interface().(protoreflect.Message) 243*1c12ee1eSDan Willemsen if !ok { 244*1c12ee1eSDan Willemsen return nil 245*1c12ee1eSDan Willemsen } 246*1c12ee1eSDan Willemsen m2.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { 247*1c12ee1eSDan Willemsen fdo, ok := fd.Options().(*descriptorpb.FieldOptions) 248*1c12ee1eSDan Willemsen if ok && fdo.GetRetention() == descriptorpb.FieldOptions_RETENTION_SOURCE { 249*1c12ee1eSDan Willemsen m2.Clear(fd) 250*1c12ee1eSDan Willemsen } 251*1c12ee1eSDan Willemsen return true 252*1c12ee1eSDan Willemsen }) 253*1c12ee1eSDan Willemsen return nil 254*1c12ee1eSDan Willemsen }) 255*1c12ee1eSDan Willemsen} 256*1c12ee1eSDan Willemsen 257*1c12ee1eSDan Willemsenfunc genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { 258*1c12ee1eSDan Willemsen descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto) 259*1c12ee1eSDan Willemsen descProto.SourceCodeInfo = nil // drop source code information 260*1c12ee1eSDan Willemsen stripSourceRetentionFieldsFromMessage(descProto.ProtoReflect()) 261*1c12ee1eSDan Willemsen b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto) 262*1c12ee1eSDan Willemsen if err != nil { 263*1c12ee1eSDan Willemsen gen.Error(err) 264*1c12ee1eSDan Willemsen return 265*1c12ee1eSDan Willemsen } 266*1c12ee1eSDan Willemsen 267*1c12ee1eSDan Willemsen g.P("var ", rawDescVarName(f), " = []byte{") 268*1c12ee1eSDan Willemsen for len(b) > 0 { 269*1c12ee1eSDan Willemsen n := 16 270*1c12ee1eSDan Willemsen if n > len(b) { 271*1c12ee1eSDan Willemsen n = len(b) 272*1c12ee1eSDan Willemsen } 273*1c12ee1eSDan Willemsen 274*1c12ee1eSDan Willemsen s := "" 275*1c12ee1eSDan Willemsen for _, c := range b[:n] { 276*1c12ee1eSDan Willemsen s += fmt.Sprintf("0x%02x,", c) 277*1c12ee1eSDan Willemsen } 278*1c12ee1eSDan Willemsen g.P(s) 279*1c12ee1eSDan Willemsen 280*1c12ee1eSDan Willemsen b = b[n:] 281*1c12ee1eSDan Willemsen } 282*1c12ee1eSDan Willemsen g.P("}") 283*1c12ee1eSDan Willemsen g.P() 284*1c12ee1eSDan Willemsen 285*1c12ee1eSDan Willemsen if f.needRawDesc { 286*1c12ee1eSDan Willemsen onceVar := rawDescVarName(f) + "Once" 287*1c12ee1eSDan Willemsen dataVar := rawDescVarName(f) + "Data" 288*1c12ee1eSDan Willemsen g.P("var (") 289*1c12ee1eSDan Willemsen g.P(onceVar, " ", syncPackage.Ident("Once")) 290*1c12ee1eSDan Willemsen g.P(dataVar, " = ", rawDescVarName(f)) 291*1c12ee1eSDan Willemsen g.P(")") 292*1c12ee1eSDan Willemsen g.P() 293*1c12ee1eSDan Willemsen 294*1c12ee1eSDan Willemsen g.P("func ", rawDescVarName(f), "GZIP() []byte {") 295*1c12ee1eSDan Willemsen g.P(onceVar, ".Do(func() {") 296*1c12ee1eSDan Willemsen g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")") 297*1c12ee1eSDan Willemsen g.P("})") 298*1c12ee1eSDan Willemsen g.P("return ", dataVar) 299*1c12ee1eSDan Willemsen g.P("}") 300*1c12ee1eSDan Willemsen g.P() 301*1c12ee1eSDan Willemsen } 302*1c12ee1eSDan Willemsen} 303*1c12ee1eSDan Willemsen 304*1c12ee1eSDan Willemsenfunc genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) { 305*1c12ee1eSDan Willemsen idx := f.allEnumsByPtr[e] 306*1c12ee1eSDan Willemsen typesVar := enumTypesVarName(f) 307*1c12ee1eSDan Willemsen 308*1c12ee1eSDan Willemsen // Descriptor method. 309*1c12ee1eSDan Willemsen g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {") 310*1c12ee1eSDan Willemsen g.P("return ", typesVar, "[", idx, "].Descriptor()") 311*1c12ee1eSDan Willemsen g.P("}") 312*1c12ee1eSDan Willemsen g.P() 313*1c12ee1eSDan Willemsen 314*1c12ee1eSDan Willemsen // Type method. 315*1c12ee1eSDan Willemsen g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {") 316*1c12ee1eSDan Willemsen g.P("return &", typesVar, "[", idx, "]") 317*1c12ee1eSDan Willemsen g.P("}") 318*1c12ee1eSDan Willemsen g.P() 319*1c12ee1eSDan Willemsen 320*1c12ee1eSDan Willemsen // Number method. 321*1c12ee1eSDan Willemsen g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {") 322*1c12ee1eSDan Willemsen g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)") 323*1c12ee1eSDan Willemsen g.P("}") 324*1c12ee1eSDan Willemsen g.P() 325*1c12ee1eSDan Willemsen} 326*1c12ee1eSDan Willemsen 327*1c12ee1eSDan Willemsenfunc genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { 328*1c12ee1eSDan Willemsen idx := f.allMessagesByPtr[m] 329*1c12ee1eSDan Willemsen typesVar := messageTypesVarName(f) 330*1c12ee1eSDan Willemsen 331*1c12ee1eSDan Willemsen // ProtoReflect method. 332*1c12ee1eSDan Willemsen g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {") 333*1c12ee1eSDan Willemsen g.P("mi := &", typesVar, "[", idx, "]") 334*1c12ee1eSDan Willemsen g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {") 335*1c12ee1eSDan Willemsen g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))") 336*1c12ee1eSDan Willemsen g.P("if ms.LoadMessageInfo() == nil {") 337*1c12ee1eSDan Willemsen g.P("ms.StoreMessageInfo(mi)") 338*1c12ee1eSDan Willemsen g.P("}") 339*1c12ee1eSDan Willemsen g.P("return ms") 340*1c12ee1eSDan Willemsen g.P("}") 341*1c12ee1eSDan Willemsen g.P("return mi.MessageOf(x)") 342*1c12ee1eSDan Willemsen g.P("}") 343*1c12ee1eSDan Willemsen g.P() 344*1c12ee1eSDan Willemsen} 345*1c12ee1eSDan Willemsen 346*1c12ee1eSDan Willemsenfunc fileVarName(f *protogen.File, suffix string) string { 347*1c12ee1eSDan Willemsen prefix := f.GoDescriptorIdent.GoName 348*1c12ee1eSDan Willemsen _, n := utf8.DecodeRuneInString(prefix) 349*1c12ee1eSDan Willemsen prefix = strings.ToLower(prefix[:n]) + prefix[n:] 350*1c12ee1eSDan Willemsen return prefix + "_" + suffix 351*1c12ee1eSDan Willemsen} 352*1c12ee1eSDan Willemsenfunc rawDescVarName(f *fileInfo) string { 353*1c12ee1eSDan Willemsen return fileVarName(f.File, "rawDesc") 354*1c12ee1eSDan Willemsen} 355*1c12ee1eSDan Willemsenfunc goTypesVarName(f *fileInfo) string { 356*1c12ee1eSDan Willemsen return fileVarName(f.File, "goTypes") 357*1c12ee1eSDan Willemsen} 358*1c12ee1eSDan Willemsenfunc depIdxsVarName(f *fileInfo) string { 359*1c12ee1eSDan Willemsen return fileVarName(f.File, "depIdxs") 360*1c12ee1eSDan Willemsen} 361*1c12ee1eSDan Willemsenfunc enumTypesVarName(f *fileInfo) string { 362*1c12ee1eSDan Willemsen return fileVarName(f.File, "enumTypes") 363*1c12ee1eSDan Willemsen} 364*1c12ee1eSDan Willemsenfunc messageTypesVarName(f *fileInfo) string { 365*1c12ee1eSDan Willemsen return fileVarName(f.File, "msgTypes") 366*1c12ee1eSDan Willemsen} 367*1c12ee1eSDan Willemsenfunc extensionTypesVarName(f *fileInfo) string { 368*1c12ee1eSDan Willemsen return fileVarName(f.File, "extTypes") 369*1c12ee1eSDan Willemsen} 370*1c12ee1eSDan Willemsenfunc initFuncName(f *protogen.File) string { 371*1c12ee1eSDan Willemsen return fileVarName(f, "init") 372*1c12ee1eSDan Willemsen} 373