xref: /aosp_15_r20/external/golang-protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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