xref: /aosp_15_r20/external/golang-protobuf/internal/filedesc/desc.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 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 filedesc
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"bytes"
9*1c12ee1eSDan Willemsen	"fmt"
10*1c12ee1eSDan Willemsen	"sync"
11*1c12ee1eSDan Willemsen	"sync/atomic"
12*1c12ee1eSDan Willemsen
13*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/descfmt"
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/descopts"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/defval"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/messageset"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/genid"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/pragma"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/strs"
20*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
21*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
22*1c12ee1eSDan Willemsen)
23*1c12ee1eSDan Willemsen
24*1c12ee1eSDan Willemsen// The types in this file may have a suffix:
25*1c12ee1eSDan Willemsen//	• L0: Contains fields common to all descriptors (except File) and
26*1c12ee1eSDan Willemsen//	must be initialized up front.
27*1c12ee1eSDan Willemsen//	• L1: Contains fields specific to a descriptor and
28*1c12ee1eSDan Willemsen//	must be initialized up front.
29*1c12ee1eSDan Willemsen//	• L2: Contains fields that are lazily initialized when constructing
30*1c12ee1eSDan Willemsen//	from the raw file descriptor. When constructing as a literal, the L2
31*1c12ee1eSDan Willemsen//	fields must be initialized up front.
32*1c12ee1eSDan Willemsen//
33*1c12ee1eSDan Willemsen// The types are exported so that packages like reflect/protodesc can
34*1c12ee1eSDan Willemsen// directly construct descriptors.
35*1c12ee1eSDan Willemsen
36*1c12ee1eSDan Willemsentype (
37*1c12ee1eSDan Willemsen	File struct {
38*1c12ee1eSDan Willemsen		fileRaw
39*1c12ee1eSDan Willemsen		L1 FileL1
40*1c12ee1eSDan Willemsen
41*1c12ee1eSDan Willemsen		once uint32     // atomically set if L2 is valid
42*1c12ee1eSDan Willemsen		mu   sync.Mutex // protects L2
43*1c12ee1eSDan Willemsen		L2   *FileL2
44*1c12ee1eSDan Willemsen	}
45*1c12ee1eSDan Willemsen	FileL1 struct {
46*1c12ee1eSDan Willemsen		Syntax  protoreflect.Syntax
47*1c12ee1eSDan Willemsen		Path    string
48*1c12ee1eSDan Willemsen		Package protoreflect.FullName
49*1c12ee1eSDan Willemsen
50*1c12ee1eSDan Willemsen		Enums      Enums
51*1c12ee1eSDan Willemsen		Messages   Messages
52*1c12ee1eSDan Willemsen		Extensions Extensions
53*1c12ee1eSDan Willemsen		Services   Services
54*1c12ee1eSDan Willemsen	}
55*1c12ee1eSDan Willemsen	FileL2 struct {
56*1c12ee1eSDan Willemsen		Options   func() protoreflect.ProtoMessage
57*1c12ee1eSDan Willemsen		Imports   FileImports
58*1c12ee1eSDan Willemsen		Locations SourceLocations
59*1c12ee1eSDan Willemsen	}
60*1c12ee1eSDan Willemsen)
61*1c12ee1eSDan Willemsen
62*1c12ee1eSDan Willemsenfunc (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
63*1c12ee1eSDan Willemsenfunc (fd *File) Parent() protoreflect.Descriptor         { return nil }
64*1c12ee1eSDan Willemsenfunc (fd *File) Index() int                              { return 0 }
65*1c12ee1eSDan Willemsenfunc (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }
66*1c12ee1eSDan Willemsenfunc (fd *File) Name() protoreflect.Name                 { return fd.L1.Package.Name() }
67*1c12ee1eSDan Willemsenfunc (fd *File) FullName() protoreflect.FullName         { return fd.L1.Package }
68*1c12ee1eSDan Willemsenfunc (fd *File) IsPlaceholder() bool                     { return false }
69*1c12ee1eSDan Willemsenfunc (fd *File) Options() protoreflect.ProtoMessage {
70*1c12ee1eSDan Willemsen	if f := fd.lazyInit().Options; f != nil {
71*1c12ee1eSDan Willemsen		return f()
72*1c12ee1eSDan Willemsen	}
73*1c12ee1eSDan Willemsen	return descopts.File
74*1c12ee1eSDan Willemsen}
75*1c12ee1eSDan Willemsenfunc (fd *File) Path() string                                  { return fd.L1.Path }
76*1c12ee1eSDan Willemsenfunc (fd *File) Package() protoreflect.FullName                { return fd.L1.Package }
77*1c12ee1eSDan Willemsenfunc (fd *File) Imports() protoreflect.FileImports             { return &fd.lazyInit().Imports }
78*1c12ee1eSDan Willemsenfunc (fd *File) Enums() protoreflect.EnumDescriptors           { return &fd.L1.Enums }
79*1c12ee1eSDan Willemsenfunc (fd *File) Messages() protoreflect.MessageDescriptors     { return &fd.L1.Messages }
80*1c12ee1eSDan Willemsenfunc (fd *File) Extensions() protoreflect.ExtensionDescriptors { return &fd.L1.Extensions }
81*1c12ee1eSDan Willemsenfunc (fd *File) Services() protoreflect.ServiceDescriptors     { return &fd.L1.Services }
82*1c12ee1eSDan Willemsenfunc (fd *File) SourceLocations() protoreflect.SourceLocations { return &fd.lazyInit().Locations }
83*1c12ee1eSDan Willemsenfunc (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, fd) }
84*1c12ee1eSDan Willemsenfunc (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
85*1c12ee1eSDan Willemsenfunc (fd *File) ProtoInternal(pragma.DoNotImplement)           {}
86*1c12ee1eSDan Willemsen
87*1c12ee1eSDan Willemsenfunc (fd *File) lazyInit() *FileL2 {
88*1c12ee1eSDan Willemsen	if atomic.LoadUint32(&fd.once) == 0 {
89*1c12ee1eSDan Willemsen		fd.lazyInitOnce()
90*1c12ee1eSDan Willemsen	}
91*1c12ee1eSDan Willemsen	return fd.L2
92*1c12ee1eSDan Willemsen}
93*1c12ee1eSDan Willemsen
94*1c12ee1eSDan Willemsenfunc (fd *File) lazyInitOnce() {
95*1c12ee1eSDan Willemsen	fd.mu.Lock()
96*1c12ee1eSDan Willemsen	if fd.L2 == nil {
97*1c12ee1eSDan Willemsen		fd.lazyRawInit() // recursively initializes all L2 structures
98*1c12ee1eSDan Willemsen	}
99*1c12ee1eSDan Willemsen	atomic.StoreUint32(&fd.once, 1)
100*1c12ee1eSDan Willemsen	fd.mu.Unlock()
101*1c12ee1eSDan Willemsen}
102*1c12ee1eSDan Willemsen
103*1c12ee1eSDan Willemsen// GoPackagePath is a pseudo-internal API for determining the Go package path
104*1c12ee1eSDan Willemsen// that this file descriptor is declared in.
105*1c12ee1eSDan Willemsen//
106*1c12ee1eSDan Willemsen// WARNING: This method is exempt from the compatibility promise and may be
107*1c12ee1eSDan Willemsen// removed in the future without warning.
108*1c12ee1eSDan Willemsenfunc (fd *File) GoPackagePath() string {
109*1c12ee1eSDan Willemsen	return fd.builder.GoPackagePath
110*1c12ee1eSDan Willemsen}
111*1c12ee1eSDan Willemsen
112*1c12ee1eSDan Willemsentype (
113*1c12ee1eSDan Willemsen	Enum struct {
114*1c12ee1eSDan Willemsen		Base
115*1c12ee1eSDan Willemsen		L1 EnumL1
116*1c12ee1eSDan Willemsen		L2 *EnumL2 // protected by fileDesc.once
117*1c12ee1eSDan Willemsen	}
118*1c12ee1eSDan Willemsen	EnumL1 struct {
119*1c12ee1eSDan Willemsen		eagerValues bool // controls whether EnumL2.Values is already populated
120*1c12ee1eSDan Willemsen	}
121*1c12ee1eSDan Willemsen	EnumL2 struct {
122*1c12ee1eSDan Willemsen		Options        func() protoreflect.ProtoMessage
123*1c12ee1eSDan Willemsen		Values         EnumValues
124*1c12ee1eSDan Willemsen		ReservedNames  Names
125*1c12ee1eSDan Willemsen		ReservedRanges EnumRanges
126*1c12ee1eSDan Willemsen	}
127*1c12ee1eSDan Willemsen
128*1c12ee1eSDan Willemsen	EnumValue struct {
129*1c12ee1eSDan Willemsen		Base
130*1c12ee1eSDan Willemsen		L1 EnumValueL1
131*1c12ee1eSDan Willemsen	}
132*1c12ee1eSDan Willemsen	EnumValueL1 struct {
133*1c12ee1eSDan Willemsen		Options func() protoreflect.ProtoMessage
134*1c12ee1eSDan Willemsen		Number  protoreflect.EnumNumber
135*1c12ee1eSDan Willemsen	}
136*1c12ee1eSDan Willemsen)
137*1c12ee1eSDan Willemsen
138*1c12ee1eSDan Willemsenfunc (ed *Enum) Options() protoreflect.ProtoMessage {
139*1c12ee1eSDan Willemsen	if f := ed.lazyInit().Options; f != nil {
140*1c12ee1eSDan Willemsen		return f()
141*1c12ee1eSDan Willemsen	}
142*1c12ee1eSDan Willemsen	return descopts.Enum
143*1c12ee1eSDan Willemsen}
144*1c12ee1eSDan Willemsenfunc (ed *Enum) Values() protoreflect.EnumValueDescriptors {
145*1c12ee1eSDan Willemsen	if ed.L1.eagerValues {
146*1c12ee1eSDan Willemsen		return &ed.L2.Values
147*1c12ee1eSDan Willemsen	}
148*1c12ee1eSDan Willemsen	return &ed.lazyInit().Values
149*1c12ee1eSDan Willemsen}
150*1c12ee1eSDan Willemsenfunc (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit().ReservedNames }
151*1c12ee1eSDan Willemsenfunc (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
152*1c12ee1eSDan Willemsenfunc (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
153*1c12ee1eSDan Willemsenfunc (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
154*1c12ee1eSDan Willemsenfunc (ed *Enum) lazyInit() *EnumL2 {
155*1c12ee1eSDan Willemsen	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
156*1c12ee1eSDan Willemsen	return ed.L2
157*1c12ee1eSDan Willemsen}
158*1c12ee1eSDan Willemsen
159*1c12ee1eSDan Willemsenfunc (ed *EnumValue) Options() protoreflect.ProtoMessage {
160*1c12ee1eSDan Willemsen	if f := ed.L1.Options; f != nil {
161*1c12ee1eSDan Willemsen		return f()
162*1c12ee1eSDan Willemsen	}
163*1c12ee1eSDan Willemsen	return descopts.EnumValue
164*1c12ee1eSDan Willemsen}
165*1c12ee1eSDan Willemsenfunc (ed *EnumValue) Number() protoreflect.EnumNumber            { return ed.L1.Number }
166*1c12ee1eSDan Willemsenfunc (ed *EnumValue) Format(s fmt.State, r rune)                 { descfmt.FormatDesc(s, r, ed) }
167*1c12ee1eSDan Willemsenfunc (ed *EnumValue) ProtoType(protoreflect.EnumValueDescriptor) {}
168*1c12ee1eSDan Willemsen
169*1c12ee1eSDan Willemsentype (
170*1c12ee1eSDan Willemsen	Message struct {
171*1c12ee1eSDan Willemsen		Base
172*1c12ee1eSDan Willemsen		L1 MessageL1
173*1c12ee1eSDan Willemsen		L2 *MessageL2 // protected by fileDesc.once
174*1c12ee1eSDan Willemsen	}
175*1c12ee1eSDan Willemsen	MessageL1 struct {
176*1c12ee1eSDan Willemsen		Enums        Enums
177*1c12ee1eSDan Willemsen		Messages     Messages
178*1c12ee1eSDan Willemsen		Extensions   Extensions
179*1c12ee1eSDan Willemsen		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
180*1c12ee1eSDan Willemsen		IsMessageSet bool // promoted from google.protobuf.MessageOptions
181*1c12ee1eSDan Willemsen	}
182*1c12ee1eSDan Willemsen	MessageL2 struct {
183*1c12ee1eSDan Willemsen		Options               func() protoreflect.ProtoMessage
184*1c12ee1eSDan Willemsen		Fields                Fields
185*1c12ee1eSDan Willemsen		Oneofs                Oneofs
186*1c12ee1eSDan Willemsen		ReservedNames         Names
187*1c12ee1eSDan Willemsen		ReservedRanges        FieldRanges
188*1c12ee1eSDan Willemsen		RequiredNumbers       FieldNumbers // must be consistent with Fields.Cardinality
189*1c12ee1eSDan Willemsen		ExtensionRanges       FieldRanges
190*1c12ee1eSDan Willemsen		ExtensionRangeOptions []func() protoreflect.ProtoMessage // must be same length as ExtensionRanges
191*1c12ee1eSDan Willemsen	}
192*1c12ee1eSDan Willemsen
193*1c12ee1eSDan Willemsen	Field struct {
194*1c12ee1eSDan Willemsen		Base
195*1c12ee1eSDan Willemsen		L1 FieldL1
196*1c12ee1eSDan Willemsen	}
197*1c12ee1eSDan Willemsen	FieldL1 struct {
198*1c12ee1eSDan Willemsen		Options          func() protoreflect.ProtoMessage
199*1c12ee1eSDan Willemsen		Number           protoreflect.FieldNumber
200*1c12ee1eSDan Willemsen		Cardinality      protoreflect.Cardinality // must be consistent with Message.RequiredNumbers
201*1c12ee1eSDan Willemsen		Kind             protoreflect.Kind
202*1c12ee1eSDan Willemsen		StringName       stringName
203*1c12ee1eSDan Willemsen		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
204*1c12ee1eSDan Willemsen		IsWeak           bool // promoted from google.protobuf.FieldOptions
205*1c12ee1eSDan Willemsen		HasPacked        bool // promoted from google.protobuf.FieldOptions
206*1c12ee1eSDan Willemsen		IsPacked         bool // promoted from google.protobuf.FieldOptions
207*1c12ee1eSDan Willemsen		HasEnforceUTF8   bool // promoted from google.protobuf.FieldOptions
208*1c12ee1eSDan Willemsen		EnforceUTF8      bool // promoted from google.protobuf.FieldOptions
209*1c12ee1eSDan Willemsen		Default          defaultValue
210*1c12ee1eSDan Willemsen		ContainingOneof  protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
211*1c12ee1eSDan Willemsen		Enum             protoreflect.EnumDescriptor
212*1c12ee1eSDan Willemsen		Message          protoreflect.MessageDescriptor
213*1c12ee1eSDan Willemsen	}
214*1c12ee1eSDan Willemsen
215*1c12ee1eSDan Willemsen	Oneof struct {
216*1c12ee1eSDan Willemsen		Base
217*1c12ee1eSDan Willemsen		L1 OneofL1
218*1c12ee1eSDan Willemsen	}
219*1c12ee1eSDan Willemsen	OneofL1 struct {
220*1c12ee1eSDan Willemsen		Options func() protoreflect.ProtoMessage
221*1c12ee1eSDan Willemsen		Fields  OneofFields // must be consistent with Message.Fields.ContainingOneof
222*1c12ee1eSDan Willemsen	}
223*1c12ee1eSDan Willemsen)
224*1c12ee1eSDan Willemsen
225*1c12ee1eSDan Willemsenfunc (md *Message) Options() protoreflect.ProtoMessage {
226*1c12ee1eSDan Willemsen	if f := md.lazyInit().Options; f != nil {
227*1c12ee1eSDan Willemsen		return f()
228*1c12ee1eSDan Willemsen	}
229*1c12ee1eSDan Willemsen	return descopts.Message
230*1c12ee1eSDan Willemsen}
231*1c12ee1eSDan Willemsenfunc (md *Message) IsMapEntry() bool                           { return md.L1.IsMapEntry }
232*1c12ee1eSDan Willemsenfunc (md *Message) Fields() protoreflect.FieldDescriptors      { return &md.lazyInit().Fields }
233*1c12ee1eSDan Willemsenfunc (md *Message) Oneofs() protoreflect.OneofDescriptors      { return &md.lazyInit().Oneofs }
234*1c12ee1eSDan Willemsenfunc (md *Message) ReservedNames() protoreflect.Names          { return &md.lazyInit().ReservedNames }
235*1c12ee1eSDan Willemsenfunc (md *Message) ReservedRanges() protoreflect.FieldRanges   { return &md.lazyInit().ReservedRanges }
236*1c12ee1eSDan Willemsenfunc (md *Message) RequiredNumbers() protoreflect.FieldNumbers { return &md.lazyInit().RequiredNumbers }
237*1c12ee1eSDan Willemsenfunc (md *Message) ExtensionRanges() protoreflect.FieldRanges  { return &md.lazyInit().ExtensionRanges }
238*1c12ee1eSDan Willemsenfunc (md *Message) ExtensionRangeOptions(i int) protoreflect.ProtoMessage {
239*1c12ee1eSDan Willemsen	if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil {
240*1c12ee1eSDan Willemsen		return f()
241*1c12ee1eSDan Willemsen	}
242*1c12ee1eSDan Willemsen	return descopts.ExtensionRange
243*1c12ee1eSDan Willemsen}
244*1c12ee1eSDan Willemsenfunc (md *Message) Enums() protoreflect.EnumDescriptors           { return &md.L1.Enums }
245*1c12ee1eSDan Willemsenfunc (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L1.Messages }
246*1c12ee1eSDan Willemsenfunc (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
247*1c12ee1eSDan Willemsenfunc (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
248*1c12ee1eSDan Willemsenfunc (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
249*1c12ee1eSDan Willemsenfunc (md *Message) lazyInit() *MessageL2 {
250*1c12ee1eSDan Willemsen	md.L0.ParentFile.lazyInit() // implicitly initializes L2
251*1c12ee1eSDan Willemsen	return md.L2
252*1c12ee1eSDan Willemsen}
253*1c12ee1eSDan Willemsen
254*1c12ee1eSDan Willemsen// IsMessageSet is a pseudo-internal API for checking whether a message
255*1c12ee1eSDan Willemsen// should serialize in the proto1 message format.
256*1c12ee1eSDan Willemsen//
257*1c12ee1eSDan Willemsen// WARNING: This method is exempt from the compatibility promise and may be
258*1c12ee1eSDan Willemsen// removed in the future without warning.
259*1c12ee1eSDan Willemsenfunc (md *Message) IsMessageSet() bool {
260*1c12ee1eSDan Willemsen	return md.L1.IsMessageSet
261*1c12ee1eSDan Willemsen}
262*1c12ee1eSDan Willemsen
263*1c12ee1eSDan Willemsenfunc (fd *Field) Options() protoreflect.ProtoMessage {
264*1c12ee1eSDan Willemsen	if f := fd.L1.Options; f != nil {
265*1c12ee1eSDan Willemsen		return f()
266*1c12ee1eSDan Willemsen	}
267*1c12ee1eSDan Willemsen	return descopts.Field
268*1c12ee1eSDan Willemsen}
269*1c12ee1eSDan Willemsenfunc (fd *Field) Number() protoreflect.FieldNumber      { return fd.L1.Number }
270*1c12ee1eSDan Willemsenfunc (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
271*1c12ee1eSDan Willemsenfunc (fd *Field) Kind() protoreflect.Kind               { return fd.L1.Kind }
272*1c12ee1eSDan Willemsenfunc (fd *Field) HasJSONName() bool                     { return fd.L1.StringName.hasJSON }
273*1c12ee1eSDan Willemsenfunc (fd *Field) JSONName() string                      { return fd.L1.StringName.getJSON(fd) }
274*1c12ee1eSDan Willemsenfunc (fd *Field) TextName() string                      { return fd.L1.StringName.getText(fd) }
275*1c12ee1eSDan Willemsenfunc (fd *Field) HasPresence() bool {
276*1c12ee1eSDan Willemsen	return fd.L1.Cardinality != protoreflect.Repeated && (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil)
277*1c12ee1eSDan Willemsen}
278*1c12ee1eSDan Willemsenfunc (fd *Field) HasOptionalKeyword() bool {
279*1c12ee1eSDan Willemsen	return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
280*1c12ee1eSDan Willemsen}
281*1c12ee1eSDan Willemsenfunc (fd *Field) IsPacked() bool {
282*1c12ee1eSDan Willemsen	if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Repeated {
283*1c12ee1eSDan Willemsen		switch fd.L1.Kind {
284*1c12ee1eSDan Willemsen		case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
285*1c12ee1eSDan Willemsen		default:
286*1c12ee1eSDan Willemsen			return true
287*1c12ee1eSDan Willemsen		}
288*1c12ee1eSDan Willemsen	}
289*1c12ee1eSDan Willemsen	return fd.L1.IsPacked
290*1c12ee1eSDan Willemsen}
291*1c12ee1eSDan Willemsenfunc (fd *Field) IsExtension() bool { return false }
292*1c12ee1eSDan Willemsenfunc (fd *Field) IsWeak() bool      { return fd.L1.IsWeak }
293*1c12ee1eSDan Willemsenfunc (fd *Field) IsList() bool      { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
294*1c12ee1eSDan Willemsenfunc (fd *Field) IsMap() bool       { return fd.Message() != nil && fd.Message().IsMapEntry() }
295*1c12ee1eSDan Willemsenfunc (fd *Field) MapKey() protoreflect.FieldDescriptor {
296*1c12ee1eSDan Willemsen	if !fd.IsMap() {
297*1c12ee1eSDan Willemsen		return nil
298*1c12ee1eSDan Willemsen	}
299*1c12ee1eSDan Willemsen	return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
300*1c12ee1eSDan Willemsen}
301*1c12ee1eSDan Willemsenfunc (fd *Field) MapValue() protoreflect.FieldDescriptor {
302*1c12ee1eSDan Willemsen	if !fd.IsMap() {
303*1c12ee1eSDan Willemsen		return nil
304*1c12ee1eSDan Willemsen	}
305*1c12ee1eSDan Willemsen	return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
306*1c12ee1eSDan Willemsen}
307*1c12ee1eSDan Willemsenfunc (fd *Field) HasDefault() bool                                   { return fd.L1.Default.has }
308*1c12ee1eSDan Willemsenfunc (fd *Field) Default() protoreflect.Value                        { return fd.L1.Default.get(fd) }
309*1c12ee1eSDan Willemsenfunc (fd *Field) DefaultEnumValue() protoreflect.EnumValueDescriptor { return fd.L1.Default.enum }
310*1c12ee1eSDan Willemsenfunc (fd *Field) ContainingOneof() protoreflect.OneofDescriptor      { return fd.L1.ContainingOneof }
311*1c12ee1eSDan Willemsenfunc (fd *Field) ContainingMessage() protoreflect.MessageDescriptor {
312*1c12ee1eSDan Willemsen	return fd.L0.Parent.(protoreflect.MessageDescriptor)
313*1c12ee1eSDan Willemsen}
314*1c12ee1eSDan Willemsenfunc (fd *Field) Enum() protoreflect.EnumDescriptor {
315*1c12ee1eSDan Willemsen	return fd.L1.Enum
316*1c12ee1eSDan Willemsen}
317*1c12ee1eSDan Willemsenfunc (fd *Field) Message() protoreflect.MessageDescriptor {
318*1c12ee1eSDan Willemsen	if fd.L1.IsWeak {
319*1c12ee1eSDan Willemsen		if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
320*1c12ee1eSDan Willemsen			return d.(protoreflect.MessageDescriptor)
321*1c12ee1eSDan Willemsen		}
322*1c12ee1eSDan Willemsen	}
323*1c12ee1eSDan Willemsen	return fd.L1.Message
324*1c12ee1eSDan Willemsen}
325*1c12ee1eSDan Willemsenfunc (fd *Field) Format(s fmt.State, r rune)             { descfmt.FormatDesc(s, r, fd) }
326*1c12ee1eSDan Willemsenfunc (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
327*1c12ee1eSDan Willemsen
328*1c12ee1eSDan Willemsen// EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8
329*1c12ee1eSDan Willemsen// validation for the string field. This exists for Google-internal use only
330*1c12ee1eSDan Willemsen// since proto3 did not enforce UTF-8 validity prior to the open-source release.
331*1c12ee1eSDan Willemsen// If this method does not exist, the default is to enforce valid UTF-8.
332*1c12ee1eSDan Willemsen//
333*1c12ee1eSDan Willemsen// WARNING: This method is exempt from the compatibility promise and may be
334*1c12ee1eSDan Willemsen// removed in the future without warning.
335*1c12ee1eSDan Willemsenfunc (fd *Field) EnforceUTF8() bool {
336*1c12ee1eSDan Willemsen	if fd.L1.HasEnforceUTF8 {
337*1c12ee1eSDan Willemsen		return fd.L1.EnforceUTF8
338*1c12ee1eSDan Willemsen	}
339*1c12ee1eSDan Willemsen	return fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3
340*1c12ee1eSDan Willemsen}
341*1c12ee1eSDan Willemsen
342*1c12ee1eSDan Willemsenfunc (od *Oneof) IsSynthetic() bool {
343*1c12ee1eSDan Willemsen	return od.L0.ParentFile.L1.Syntax == protoreflect.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
344*1c12ee1eSDan Willemsen}
345*1c12ee1eSDan Willemsenfunc (od *Oneof) Options() protoreflect.ProtoMessage {
346*1c12ee1eSDan Willemsen	if f := od.L1.Options; f != nil {
347*1c12ee1eSDan Willemsen		return f()
348*1c12ee1eSDan Willemsen	}
349*1c12ee1eSDan Willemsen	return descopts.Oneof
350*1c12ee1eSDan Willemsen}
351*1c12ee1eSDan Willemsenfunc (od *Oneof) Fields() protoreflect.FieldDescriptors  { return &od.L1.Fields }
352*1c12ee1eSDan Willemsenfunc (od *Oneof) Format(s fmt.State, r rune)             { descfmt.FormatDesc(s, r, od) }
353*1c12ee1eSDan Willemsenfunc (od *Oneof) ProtoType(protoreflect.OneofDescriptor) {}
354*1c12ee1eSDan Willemsen
355*1c12ee1eSDan Willemsentype (
356*1c12ee1eSDan Willemsen	Extension struct {
357*1c12ee1eSDan Willemsen		Base
358*1c12ee1eSDan Willemsen		L1 ExtensionL1
359*1c12ee1eSDan Willemsen		L2 *ExtensionL2 // protected by fileDesc.once
360*1c12ee1eSDan Willemsen	}
361*1c12ee1eSDan Willemsen	ExtensionL1 struct {
362*1c12ee1eSDan Willemsen		Number      protoreflect.FieldNumber
363*1c12ee1eSDan Willemsen		Extendee    protoreflect.MessageDescriptor
364*1c12ee1eSDan Willemsen		Cardinality protoreflect.Cardinality
365*1c12ee1eSDan Willemsen		Kind        protoreflect.Kind
366*1c12ee1eSDan Willemsen	}
367*1c12ee1eSDan Willemsen	ExtensionL2 struct {
368*1c12ee1eSDan Willemsen		Options          func() protoreflect.ProtoMessage
369*1c12ee1eSDan Willemsen		StringName       stringName
370*1c12ee1eSDan Willemsen		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
371*1c12ee1eSDan Willemsen		IsPacked         bool // promoted from google.protobuf.FieldOptions
372*1c12ee1eSDan Willemsen		Default          defaultValue
373*1c12ee1eSDan Willemsen		Enum             protoreflect.EnumDescriptor
374*1c12ee1eSDan Willemsen		Message          protoreflect.MessageDescriptor
375*1c12ee1eSDan Willemsen	}
376*1c12ee1eSDan Willemsen)
377*1c12ee1eSDan Willemsen
378*1c12ee1eSDan Willemsenfunc (xd *Extension) Options() protoreflect.ProtoMessage {
379*1c12ee1eSDan Willemsen	if f := xd.lazyInit().Options; f != nil {
380*1c12ee1eSDan Willemsen		return f()
381*1c12ee1eSDan Willemsen	}
382*1c12ee1eSDan Willemsen	return descopts.Field
383*1c12ee1eSDan Willemsen}
384*1c12ee1eSDan Willemsenfunc (xd *Extension) Number() protoreflect.FieldNumber      { return xd.L1.Number }
385*1c12ee1eSDan Willemsenfunc (xd *Extension) Cardinality() protoreflect.Cardinality { return xd.L1.Cardinality }
386*1c12ee1eSDan Willemsenfunc (xd *Extension) Kind() protoreflect.Kind               { return xd.L1.Kind }
387*1c12ee1eSDan Willemsenfunc (xd *Extension) HasJSONName() bool                     { return xd.lazyInit().StringName.hasJSON }
388*1c12ee1eSDan Willemsenfunc (xd *Extension) JSONName() string                      { return xd.lazyInit().StringName.getJSON(xd) }
389*1c12ee1eSDan Willemsenfunc (xd *Extension) TextName() string                      { return xd.lazyInit().StringName.getText(xd) }
390*1c12ee1eSDan Willemsenfunc (xd *Extension) HasPresence() bool                     { return xd.L1.Cardinality != protoreflect.Repeated }
391*1c12ee1eSDan Willemsenfunc (xd *Extension) HasOptionalKeyword() bool {
392*1c12ee1eSDan Willemsen	return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional
393*1c12ee1eSDan Willemsen}
394*1c12ee1eSDan Willemsenfunc (xd *Extension) IsPacked() bool                         { return xd.lazyInit().IsPacked }
395*1c12ee1eSDan Willemsenfunc (xd *Extension) IsExtension() bool                      { return true }
396*1c12ee1eSDan Willemsenfunc (xd *Extension) IsWeak() bool                           { return false }
397*1c12ee1eSDan Willemsenfunc (xd *Extension) IsList() bool                           { return xd.Cardinality() == protoreflect.Repeated }
398*1c12ee1eSDan Willemsenfunc (xd *Extension) IsMap() bool                            { return false }
399*1c12ee1eSDan Willemsenfunc (xd *Extension) MapKey() protoreflect.FieldDescriptor   { return nil }
400*1c12ee1eSDan Willemsenfunc (xd *Extension) MapValue() protoreflect.FieldDescriptor { return nil }
401*1c12ee1eSDan Willemsenfunc (xd *Extension) HasDefault() bool                       { return xd.lazyInit().Default.has }
402*1c12ee1eSDan Willemsenfunc (xd *Extension) Default() protoreflect.Value            { return xd.lazyInit().Default.get(xd) }
403*1c12ee1eSDan Willemsenfunc (xd *Extension) DefaultEnumValue() protoreflect.EnumValueDescriptor {
404*1c12ee1eSDan Willemsen	return xd.lazyInit().Default.enum
405*1c12ee1eSDan Willemsen}
406*1c12ee1eSDan Willemsenfunc (xd *Extension) ContainingOneof() protoreflect.OneofDescriptor     { return nil }
407*1c12ee1eSDan Willemsenfunc (xd *Extension) ContainingMessage() protoreflect.MessageDescriptor { return xd.L1.Extendee }
408*1c12ee1eSDan Willemsenfunc (xd *Extension) Enum() protoreflect.EnumDescriptor                 { return xd.lazyInit().Enum }
409*1c12ee1eSDan Willemsenfunc (xd *Extension) Message() protoreflect.MessageDescriptor           { return xd.lazyInit().Message }
410*1c12ee1eSDan Willemsenfunc (xd *Extension) Format(s fmt.State, r rune)                        { descfmt.FormatDesc(s, r, xd) }
411*1c12ee1eSDan Willemsenfunc (xd *Extension) ProtoType(protoreflect.FieldDescriptor)            {}
412*1c12ee1eSDan Willemsenfunc (xd *Extension) ProtoInternal(pragma.DoNotImplement)               {}
413*1c12ee1eSDan Willemsenfunc (xd *Extension) lazyInit() *ExtensionL2 {
414*1c12ee1eSDan Willemsen	xd.L0.ParentFile.lazyInit() // implicitly initializes L2
415*1c12ee1eSDan Willemsen	return xd.L2
416*1c12ee1eSDan Willemsen}
417*1c12ee1eSDan Willemsen
418*1c12ee1eSDan Willemsentype (
419*1c12ee1eSDan Willemsen	Service struct {
420*1c12ee1eSDan Willemsen		Base
421*1c12ee1eSDan Willemsen		L1 ServiceL1
422*1c12ee1eSDan Willemsen		L2 *ServiceL2 // protected by fileDesc.once
423*1c12ee1eSDan Willemsen	}
424*1c12ee1eSDan Willemsen	ServiceL1 struct{}
425*1c12ee1eSDan Willemsen	ServiceL2 struct {
426*1c12ee1eSDan Willemsen		Options func() protoreflect.ProtoMessage
427*1c12ee1eSDan Willemsen		Methods Methods
428*1c12ee1eSDan Willemsen	}
429*1c12ee1eSDan Willemsen
430*1c12ee1eSDan Willemsen	Method struct {
431*1c12ee1eSDan Willemsen		Base
432*1c12ee1eSDan Willemsen		L1 MethodL1
433*1c12ee1eSDan Willemsen	}
434*1c12ee1eSDan Willemsen	MethodL1 struct {
435*1c12ee1eSDan Willemsen		Options           func() protoreflect.ProtoMessage
436*1c12ee1eSDan Willemsen		Input             protoreflect.MessageDescriptor
437*1c12ee1eSDan Willemsen		Output            protoreflect.MessageDescriptor
438*1c12ee1eSDan Willemsen		IsStreamingClient bool
439*1c12ee1eSDan Willemsen		IsStreamingServer bool
440*1c12ee1eSDan Willemsen	}
441*1c12ee1eSDan Willemsen)
442*1c12ee1eSDan Willemsen
443*1c12ee1eSDan Willemsenfunc (sd *Service) Options() protoreflect.ProtoMessage {
444*1c12ee1eSDan Willemsen	if f := sd.lazyInit().Options; f != nil {
445*1c12ee1eSDan Willemsen		return f()
446*1c12ee1eSDan Willemsen	}
447*1c12ee1eSDan Willemsen	return descopts.Service
448*1c12ee1eSDan Willemsen}
449*1c12ee1eSDan Willemsenfunc (sd *Service) Methods() protoreflect.MethodDescriptors  { return &sd.lazyInit().Methods }
450*1c12ee1eSDan Willemsenfunc (sd *Service) Format(s fmt.State, r rune)               { descfmt.FormatDesc(s, r, sd) }
451*1c12ee1eSDan Willemsenfunc (sd *Service) ProtoType(protoreflect.ServiceDescriptor) {}
452*1c12ee1eSDan Willemsenfunc (sd *Service) ProtoInternal(pragma.DoNotImplement)      {}
453*1c12ee1eSDan Willemsenfunc (sd *Service) lazyInit() *ServiceL2 {
454*1c12ee1eSDan Willemsen	sd.L0.ParentFile.lazyInit() // implicitly initializes L2
455*1c12ee1eSDan Willemsen	return sd.L2
456*1c12ee1eSDan Willemsen}
457*1c12ee1eSDan Willemsen
458*1c12ee1eSDan Willemsenfunc (md *Method) Options() protoreflect.ProtoMessage {
459*1c12ee1eSDan Willemsen	if f := md.L1.Options; f != nil {
460*1c12ee1eSDan Willemsen		return f()
461*1c12ee1eSDan Willemsen	}
462*1c12ee1eSDan Willemsen	return descopts.Method
463*1c12ee1eSDan Willemsen}
464*1c12ee1eSDan Willemsenfunc (md *Method) Input() protoreflect.MessageDescriptor   { return md.L1.Input }
465*1c12ee1eSDan Willemsenfunc (md *Method) Output() protoreflect.MessageDescriptor  { return md.L1.Output }
466*1c12ee1eSDan Willemsenfunc (md *Method) IsStreamingClient() bool                 { return md.L1.IsStreamingClient }
467*1c12ee1eSDan Willemsenfunc (md *Method) IsStreamingServer() bool                 { return md.L1.IsStreamingServer }
468*1c12ee1eSDan Willemsenfunc (md *Method) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, md) }
469*1c12ee1eSDan Willemsenfunc (md *Method) ProtoType(protoreflect.MethodDescriptor) {}
470*1c12ee1eSDan Willemsenfunc (md *Method) ProtoInternal(pragma.DoNotImplement)     {}
471*1c12ee1eSDan Willemsen
472*1c12ee1eSDan Willemsen// Surrogate files are can be used to create standalone descriptors
473*1c12ee1eSDan Willemsen// where the syntax is only information derived from the parent file.
474*1c12ee1eSDan Willemsenvar (
475*1c12ee1eSDan Willemsen	SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}}
476*1c12ee1eSDan Willemsen	SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}}
477*1c12ee1eSDan Willemsen)
478*1c12ee1eSDan Willemsen
479*1c12ee1eSDan Willemsentype (
480*1c12ee1eSDan Willemsen	Base struct {
481*1c12ee1eSDan Willemsen		L0 BaseL0
482*1c12ee1eSDan Willemsen	}
483*1c12ee1eSDan Willemsen	BaseL0 struct {
484*1c12ee1eSDan Willemsen		FullName   protoreflect.FullName // must be populated
485*1c12ee1eSDan Willemsen		ParentFile *File                 // must be populated
486*1c12ee1eSDan Willemsen		Parent     protoreflect.Descriptor
487*1c12ee1eSDan Willemsen		Index      int
488*1c12ee1eSDan Willemsen	}
489*1c12ee1eSDan Willemsen)
490*1c12ee1eSDan Willemsen
491*1c12ee1eSDan Willemsenfunc (d *Base) Name() protoreflect.Name         { return d.L0.FullName.Name() }
492*1c12ee1eSDan Willemsenfunc (d *Base) FullName() protoreflect.FullName { return d.L0.FullName }
493*1c12ee1eSDan Willemsenfunc (d *Base) ParentFile() protoreflect.FileDescriptor {
494*1c12ee1eSDan Willemsen	if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 {
495*1c12ee1eSDan Willemsen		return nil // surrogate files are not real parents
496*1c12ee1eSDan Willemsen	}
497*1c12ee1eSDan Willemsen	return d.L0.ParentFile
498*1c12ee1eSDan Willemsen}
499*1c12ee1eSDan Willemsenfunc (d *Base) Parent() protoreflect.Descriptor     { return d.L0.Parent }
500*1c12ee1eSDan Willemsenfunc (d *Base) Index() int                          { return d.L0.Index }
501*1c12ee1eSDan Willemsenfunc (d *Base) Syntax() protoreflect.Syntax         { return d.L0.ParentFile.Syntax() }
502*1c12ee1eSDan Willemsenfunc (d *Base) IsPlaceholder() bool                 { return false }
503*1c12ee1eSDan Willemsenfunc (d *Base) ProtoInternal(pragma.DoNotImplement) {}
504*1c12ee1eSDan Willemsen
505*1c12ee1eSDan Willemsentype stringName struct {
506*1c12ee1eSDan Willemsen	hasJSON  bool
507*1c12ee1eSDan Willemsen	once     sync.Once
508*1c12ee1eSDan Willemsen	nameJSON string
509*1c12ee1eSDan Willemsen	nameText string
510*1c12ee1eSDan Willemsen}
511*1c12ee1eSDan Willemsen
512*1c12ee1eSDan Willemsen// InitJSON initializes the name. It is exported for use by other internal packages.
513*1c12ee1eSDan Willemsenfunc (s *stringName) InitJSON(name string) {
514*1c12ee1eSDan Willemsen	s.hasJSON = true
515*1c12ee1eSDan Willemsen	s.nameJSON = name
516*1c12ee1eSDan Willemsen}
517*1c12ee1eSDan Willemsen
518*1c12ee1eSDan Willemsenfunc (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
519*1c12ee1eSDan Willemsen	s.once.Do(func() {
520*1c12ee1eSDan Willemsen		if fd.IsExtension() {
521*1c12ee1eSDan Willemsen			// For extensions, JSON and text are formatted the same way.
522*1c12ee1eSDan Willemsen			var name string
523*1c12ee1eSDan Willemsen			if messageset.IsMessageSetExtension(fd) {
524*1c12ee1eSDan Willemsen				name = string("[" + fd.FullName().Parent() + "]")
525*1c12ee1eSDan Willemsen			} else {
526*1c12ee1eSDan Willemsen				name = string("[" + fd.FullName() + "]")
527*1c12ee1eSDan Willemsen			}
528*1c12ee1eSDan Willemsen			s.nameJSON = name
529*1c12ee1eSDan Willemsen			s.nameText = name
530*1c12ee1eSDan Willemsen		} else {
531*1c12ee1eSDan Willemsen			// Format the JSON name.
532*1c12ee1eSDan Willemsen			if !s.hasJSON {
533*1c12ee1eSDan Willemsen				s.nameJSON = strs.JSONCamelCase(string(fd.Name()))
534*1c12ee1eSDan Willemsen			}
535*1c12ee1eSDan Willemsen
536*1c12ee1eSDan Willemsen			// Format the text name.
537*1c12ee1eSDan Willemsen			s.nameText = string(fd.Name())
538*1c12ee1eSDan Willemsen			if fd.Kind() == protoreflect.GroupKind {
539*1c12ee1eSDan Willemsen				s.nameText = string(fd.Message().Name())
540*1c12ee1eSDan Willemsen			}
541*1c12ee1eSDan Willemsen		}
542*1c12ee1eSDan Willemsen	})
543*1c12ee1eSDan Willemsen	return s
544*1c12ee1eSDan Willemsen}
545*1c12ee1eSDan Willemsen
546*1c12ee1eSDan Willemsenfunc (s *stringName) getJSON(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameJSON }
547*1c12ee1eSDan Willemsenfunc (s *stringName) getText(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameText }
548*1c12ee1eSDan Willemsen
549*1c12ee1eSDan Willemsenfunc DefaultValue(v protoreflect.Value, ev protoreflect.EnumValueDescriptor) defaultValue {
550*1c12ee1eSDan Willemsen	dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
551*1c12ee1eSDan Willemsen	if b, ok := v.Interface().([]byte); ok {
552*1c12ee1eSDan Willemsen		// Store a copy of the default bytes, so that we can detect
553*1c12ee1eSDan Willemsen		// accidental mutations of the original value.
554*1c12ee1eSDan Willemsen		dv.bytes = append([]byte(nil), b...)
555*1c12ee1eSDan Willemsen	}
556*1c12ee1eSDan Willemsen	return dv
557*1c12ee1eSDan Willemsen}
558*1c12ee1eSDan Willemsen
559*1c12ee1eSDan Willemsenfunc unmarshalDefault(b []byte, k protoreflect.Kind, pf *File, ed protoreflect.EnumDescriptor) defaultValue {
560*1c12ee1eSDan Willemsen	var evs protoreflect.EnumValueDescriptors
561*1c12ee1eSDan Willemsen	if k == protoreflect.EnumKind {
562*1c12ee1eSDan Willemsen		// If the enum is declared within the same file, be careful not to
563*1c12ee1eSDan Willemsen		// blindly call the Values method, lest we bind ourselves in a deadlock.
564*1c12ee1eSDan Willemsen		if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf {
565*1c12ee1eSDan Willemsen			evs = &e.L2.Values
566*1c12ee1eSDan Willemsen		} else {
567*1c12ee1eSDan Willemsen			evs = ed.Values()
568*1c12ee1eSDan Willemsen		}
569*1c12ee1eSDan Willemsen
570*1c12ee1eSDan Willemsen		// If we are unable to resolve the enum dependency, use a placeholder
571*1c12ee1eSDan Willemsen		// enum value since we will not be able to parse the default value.
572*1c12ee1eSDan Willemsen		if ed.IsPlaceholder() && protoreflect.Name(b).IsValid() {
573*1c12ee1eSDan Willemsen			v := protoreflect.ValueOfEnum(0)
574*1c12ee1eSDan Willemsen			ev := PlaceholderEnumValue(ed.FullName().Parent().Append(protoreflect.Name(b)))
575*1c12ee1eSDan Willemsen			return DefaultValue(v, ev)
576*1c12ee1eSDan Willemsen		}
577*1c12ee1eSDan Willemsen	}
578*1c12ee1eSDan Willemsen
579*1c12ee1eSDan Willemsen	v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor)
580*1c12ee1eSDan Willemsen	if err != nil {
581*1c12ee1eSDan Willemsen		panic(err)
582*1c12ee1eSDan Willemsen	}
583*1c12ee1eSDan Willemsen	return DefaultValue(v, ev)
584*1c12ee1eSDan Willemsen}
585*1c12ee1eSDan Willemsen
586*1c12ee1eSDan Willemsentype defaultValue struct {
587*1c12ee1eSDan Willemsen	has   bool
588*1c12ee1eSDan Willemsen	val   protoreflect.Value
589*1c12ee1eSDan Willemsen	enum  protoreflect.EnumValueDescriptor
590*1c12ee1eSDan Willemsen	bytes []byte
591*1c12ee1eSDan Willemsen}
592*1c12ee1eSDan Willemsen
593*1c12ee1eSDan Willemsenfunc (dv *defaultValue) get(fd protoreflect.FieldDescriptor) protoreflect.Value {
594*1c12ee1eSDan Willemsen	// Return the zero value as the default if unpopulated.
595*1c12ee1eSDan Willemsen	if !dv.has {
596*1c12ee1eSDan Willemsen		if fd.Cardinality() == protoreflect.Repeated {
597*1c12ee1eSDan Willemsen			return protoreflect.Value{}
598*1c12ee1eSDan Willemsen		}
599*1c12ee1eSDan Willemsen		switch fd.Kind() {
600*1c12ee1eSDan Willemsen		case protoreflect.BoolKind:
601*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBool(false)
602*1c12ee1eSDan Willemsen		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
603*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt32(0)
604*1c12ee1eSDan Willemsen		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
605*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt64(0)
606*1c12ee1eSDan Willemsen		case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
607*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint32(0)
608*1c12ee1eSDan Willemsen		case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
609*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint64(0)
610*1c12ee1eSDan Willemsen		case protoreflect.FloatKind:
611*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat32(0)
612*1c12ee1eSDan Willemsen		case protoreflect.DoubleKind:
613*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(0)
614*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
615*1c12ee1eSDan Willemsen			return protoreflect.ValueOfString("")
616*1c12ee1eSDan Willemsen		case protoreflect.BytesKind:
617*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBytes(nil)
618*1c12ee1eSDan Willemsen		case protoreflect.EnumKind:
619*1c12ee1eSDan Willemsen			if evs := fd.Enum().Values(); evs.Len() > 0 {
620*1c12ee1eSDan Willemsen				return protoreflect.ValueOfEnum(evs.Get(0).Number())
621*1c12ee1eSDan Willemsen			}
622*1c12ee1eSDan Willemsen			return protoreflect.ValueOfEnum(0)
623*1c12ee1eSDan Willemsen		}
624*1c12ee1eSDan Willemsen	}
625*1c12ee1eSDan Willemsen
626*1c12ee1eSDan Willemsen	if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) {
627*1c12ee1eSDan Willemsen		// TODO: Avoid panic if we're running with the race detector
628*1c12ee1eSDan Willemsen		// and instead spawn a goroutine that periodically resets
629*1c12ee1eSDan Willemsen		// this value back to the original to induce a race.
630*1c12ee1eSDan Willemsen		panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
631*1c12ee1eSDan Willemsen	}
632*1c12ee1eSDan Willemsen	return dv.val
633*1c12ee1eSDan Willemsen}
634