blob: 8826bcf4021cfe6641c75af32bee50ffcf1ce23c [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package filedesc
6
7import (
8 "bytes"
9 "fmt"
10 "sync"
11 "sync/atomic"
12
13 "google.golang.org/protobuf/internal/descfmt"
14 "google.golang.org/protobuf/internal/descopts"
15 "google.golang.org/protobuf/internal/encoding/defval"
16 "google.golang.org/protobuf/internal/encoding/messageset"
17 "google.golang.org/protobuf/internal/genid"
18 "google.golang.org/protobuf/internal/pragma"
19 "google.golang.org/protobuf/internal/strs"
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053020 "google.golang.org/protobuf/reflect/protoreflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053021 "google.golang.org/protobuf/reflect/protoregistry"
22)
23
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053024// Edition is an Enum for proto2.Edition
25type Edition int32
26
27// These values align with the value of Enum in descriptor.proto which allows
28// direct conversion between the proto enum and this enum.
29const (
30 EditionUnknown Edition = 0
31 EditionProto2 Edition = 998
32 EditionProto3 Edition = 999
33 Edition2023 Edition = 1000
34 EditionUnsupported Edition = 100000
35)
36
Naveen Sampath04696f72022-06-13 15:19:14 +053037// The types in this file may have a suffix:
38// • L0: Contains fields common to all descriptors (except File) and
39// must be initialized up front.
40// • L1: Contains fields specific to a descriptor and
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053041// must be initialized up front. If the associated proto uses Editions, the
42// Editions features must always be resolved. If not explicitly set, the
43// appropriate default must be resolved and set.
Naveen Sampath04696f72022-06-13 15:19:14 +053044// • L2: Contains fields that are lazily initialized when constructing
45// from the raw file descriptor. When constructing as a literal, the L2
46// fields must be initialized up front.
47//
48// The types are exported so that packages like reflect/protodesc can
49// directly construct descriptors.
50
51type (
52 File struct {
53 fileRaw
54 L1 FileL1
55
56 once uint32 // atomically set if L2 is valid
57 mu sync.Mutex // protects L2
58 L2 *FileL2
59 }
60 FileL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053061 Syntax protoreflect.Syntax
62 Edition Edition // Only used if Syntax == Editions
Naveen Sampath04696f72022-06-13 15:19:14 +053063 Path string
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053064 Package protoreflect.FullName
Naveen Sampath04696f72022-06-13 15:19:14 +053065
66 Enums Enums
67 Messages Messages
68 Extensions Extensions
69 Services Services
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053070
71 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +053072 }
73 FileL2 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053074 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +053075 Imports FileImports
76 Locations SourceLocations
77 }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053078
79 EditionFeatures struct {
80 // IsFieldPresence is true if field_presence is EXPLICIT
81 // https://protobuf.dev/editions/features/#field_presence
82 IsFieldPresence bool
83 // IsFieldPresence is true if field_presence is LEGACY_REQUIRED
84 // https://protobuf.dev/editions/features/#field_presence
85 IsLegacyRequired bool
86 // IsOpenEnum is true if enum_type is OPEN
87 // https://protobuf.dev/editions/features/#enum_type
88 IsOpenEnum bool
89 // IsPacked is true if repeated_field_encoding is PACKED
90 // https://protobuf.dev/editions/features/#repeated_field_encoding
91 IsPacked bool
92 // IsUTF8Validated is true if utf_validation is VERIFY
93 // https://protobuf.dev/editions/features/#utf8_validation
94 IsUTF8Validated bool
95 // IsDelimitedEncoded is true if message_encoding is DELIMITED
96 // https://protobuf.dev/editions/features/#message_encoding
97 IsDelimitedEncoded bool
98 // IsJSONCompliant is true if json_format is ALLOW
99 // https://protobuf.dev/editions/features/#json_format
100 IsJSONCompliant bool
101 // GenerateLegacyUnmarshalJSON determines if the plugin generates the
102 // UnmarshalJSON([]byte) error method for enums.
103 GenerateLegacyUnmarshalJSON bool
104 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530105)
106
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530107func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
108func (fd *File) Parent() protoreflect.Descriptor { return nil }
109func (fd *File) Index() int { return 0 }
110func (fd *File) Syntax() protoreflect.Syntax { return fd.L1.Syntax }
111func (fd *File) Name() protoreflect.Name { return fd.L1.Package.Name() }
112func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
113func (fd *File) IsPlaceholder() bool { return false }
114func (fd *File) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530115 if f := fd.lazyInit().Options; f != nil {
116 return f()
117 }
118 return descopts.File
119}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530120func (fd *File) Path() string { return fd.L1.Path }
121func (fd *File) Package() protoreflect.FullName { return fd.L1.Package }
122func (fd *File) Imports() protoreflect.FileImports { return &fd.lazyInit().Imports }
123func (fd *File) Enums() protoreflect.EnumDescriptors { return &fd.L1.Enums }
124func (fd *File) Messages() protoreflect.MessageDescriptors { return &fd.L1.Messages }
125func (fd *File) Extensions() protoreflect.ExtensionDescriptors { return &fd.L1.Extensions }
126func (fd *File) Services() protoreflect.ServiceDescriptors { return &fd.L1.Services }
127func (fd *File) SourceLocations() protoreflect.SourceLocations { return &fd.lazyInit().Locations }
128func (fd *File) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) }
129func (fd *File) ProtoType(protoreflect.FileDescriptor) {}
130func (fd *File) ProtoInternal(pragma.DoNotImplement) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530131
132func (fd *File) lazyInit() *FileL2 {
133 if atomic.LoadUint32(&fd.once) == 0 {
134 fd.lazyInitOnce()
135 }
136 return fd.L2
137}
138
139func (fd *File) lazyInitOnce() {
140 fd.mu.Lock()
141 if fd.L2 == nil {
142 fd.lazyRawInit() // recursively initializes all L2 structures
143 }
144 atomic.StoreUint32(&fd.once, 1)
145 fd.mu.Unlock()
146}
147
148// GoPackagePath is a pseudo-internal API for determining the Go package path
149// that this file descriptor is declared in.
150//
151// WARNING: This method is exempt from the compatibility promise and may be
152// removed in the future without warning.
153func (fd *File) GoPackagePath() string {
154 return fd.builder.GoPackagePath
155}
156
157type (
158 Enum struct {
159 Base
160 L1 EnumL1
161 L2 *EnumL2 // protected by fileDesc.once
162 }
163 EnumL1 struct {
164 eagerValues bool // controls whether EnumL2.Values is already populated
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530165
166 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +0530167 }
168 EnumL2 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530169 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +0530170 Values EnumValues
171 ReservedNames Names
172 ReservedRanges EnumRanges
173 }
174
175 EnumValue struct {
176 Base
177 L1 EnumValueL1
178 }
179 EnumValueL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530180 Options func() protoreflect.ProtoMessage
181 Number protoreflect.EnumNumber
Naveen Sampath04696f72022-06-13 15:19:14 +0530182 }
183)
184
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530185func (ed *Enum) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530186 if f := ed.lazyInit().Options; f != nil {
187 return f()
188 }
189 return descopts.Enum
190}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530191func (ed *Enum) Values() protoreflect.EnumValueDescriptors {
Naveen Sampath04696f72022-06-13 15:19:14 +0530192 if ed.L1.eagerValues {
193 return &ed.L2.Values
194 }
195 return &ed.lazyInit().Values
196}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530197func (ed *Enum) ReservedNames() protoreflect.Names { return &ed.lazyInit().ReservedNames }
198func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
199func (ed *Enum) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) }
200func (ed *Enum) ProtoType(protoreflect.EnumDescriptor) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530201func (ed *Enum) lazyInit() *EnumL2 {
202 ed.L0.ParentFile.lazyInit() // implicitly initializes L2
203 return ed.L2
204}
205
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530206func (ed *EnumValue) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530207 if f := ed.L1.Options; f != nil {
208 return f()
209 }
210 return descopts.EnumValue
211}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530212func (ed *EnumValue) Number() protoreflect.EnumNumber { return ed.L1.Number }
213func (ed *EnumValue) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) }
214func (ed *EnumValue) ProtoType(protoreflect.EnumValueDescriptor) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530215
216type (
217 Message struct {
218 Base
219 L1 MessageL1
220 L2 *MessageL2 // protected by fileDesc.once
221 }
222 MessageL1 struct {
223 Enums Enums
224 Messages Messages
225 Extensions Extensions
226 IsMapEntry bool // promoted from google.protobuf.MessageOptions
227 IsMessageSet bool // promoted from google.protobuf.MessageOptions
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530228
229 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +0530230 }
231 MessageL2 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530232 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +0530233 Fields Fields
234 Oneofs Oneofs
235 ReservedNames Names
236 ReservedRanges FieldRanges
237 RequiredNumbers FieldNumbers // must be consistent with Fields.Cardinality
238 ExtensionRanges FieldRanges
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530239 ExtensionRangeOptions []func() protoreflect.ProtoMessage // must be same length as ExtensionRanges
Naveen Sampath04696f72022-06-13 15:19:14 +0530240 }
241
242 Field struct {
243 Base
244 L1 FieldL1
245 }
246 FieldL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530247 Options func() protoreflect.ProtoMessage
248 Number protoreflect.FieldNumber
249 Cardinality protoreflect.Cardinality // must be consistent with Message.RequiredNumbers
250 Kind protoreflect.Kind
Naveen Sampath04696f72022-06-13 15:19:14 +0530251 StringName stringName
252 IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
253 IsWeak bool // promoted from google.protobuf.FieldOptions
254 HasPacked bool // promoted from google.protobuf.FieldOptions
255 IsPacked bool // promoted from google.protobuf.FieldOptions
256 HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions
257 EnforceUTF8 bool // promoted from google.protobuf.FieldOptions
258 Default defaultValue
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530259 ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
260 Enum protoreflect.EnumDescriptor
261 Message protoreflect.MessageDescriptor
262
263 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +0530264 }
265
266 Oneof struct {
267 Base
268 L1 OneofL1
269 }
270 OneofL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530271 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +0530272 Fields OneofFields // must be consistent with Message.Fields.ContainingOneof
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530273
274 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +0530275 }
276)
277
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530278func (md *Message) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530279 if f := md.lazyInit().Options; f != nil {
280 return f()
281 }
282 return descopts.Message
283}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530284func (md *Message) IsMapEntry() bool { return md.L1.IsMapEntry }
285func (md *Message) Fields() protoreflect.FieldDescriptors { return &md.lazyInit().Fields }
286func (md *Message) Oneofs() protoreflect.OneofDescriptors { return &md.lazyInit().Oneofs }
287func (md *Message) ReservedNames() protoreflect.Names { return &md.lazyInit().ReservedNames }
288func (md *Message) ReservedRanges() protoreflect.FieldRanges { return &md.lazyInit().ReservedRanges }
289func (md *Message) RequiredNumbers() protoreflect.FieldNumbers { return &md.lazyInit().RequiredNumbers }
290func (md *Message) ExtensionRanges() protoreflect.FieldRanges { return &md.lazyInit().ExtensionRanges }
291func (md *Message) ExtensionRangeOptions(i int) protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530292 if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil {
293 return f()
294 }
295 return descopts.ExtensionRange
296}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530297func (md *Message) Enums() protoreflect.EnumDescriptors { return &md.L1.Enums }
298func (md *Message) Messages() protoreflect.MessageDescriptors { return &md.L1.Messages }
299func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
300func (md *Message) ProtoType(protoreflect.MessageDescriptor) {}
301func (md *Message) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) }
Naveen Sampath04696f72022-06-13 15:19:14 +0530302func (md *Message) lazyInit() *MessageL2 {
303 md.L0.ParentFile.lazyInit() // implicitly initializes L2
304 return md.L2
305}
306
307// IsMessageSet is a pseudo-internal API for checking whether a message
308// should serialize in the proto1 message format.
309//
310// WARNING: This method is exempt from the compatibility promise and may be
311// removed in the future without warning.
312func (md *Message) IsMessageSet() bool {
313 return md.L1.IsMessageSet
314}
315
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530316func (fd *Field) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530317 if f := fd.L1.Options; f != nil {
318 return f()
319 }
320 return descopts.Field
321}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530322func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number }
323func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
324func (fd *Field) Kind() protoreflect.Kind {
325 return fd.L1.Kind
326}
327func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
328func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) }
329func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) }
Naveen Sampath04696f72022-06-13 15:19:14 +0530330func (fd *Field) HasPresence() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530331 if fd.L1.Cardinality == protoreflect.Repeated {
332 return false
333 }
334 explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence
335 return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
Naveen Sampath04696f72022-06-13 15:19:14 +0530336}
337func (fd *Field) HasOptionalKeyword() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530338 return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
Naveen Sampath04696f72022-06-13 15:19:14 +0530339}
340func (fd *Field) IsPacked() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530341 if fd.L1.Cardinality != protoreflect.Repeated {
342 return false
343 }
344 switch fd.L1.Kind {
345 case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
346 return false
347 }
348 if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
349 return fd.L1.EditionFeatures.IsPacked
350 }
351 if fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3 {
352 // proto3 repeated fields are packed by default.
353 return !fd.L1.HasPacked || fd.L1.IsPacked
Naveen Sampath04696f72022-06-13 15:19:14 +0530354 }
355 return fd.L1.IsPacked
356}
357func (fd *Field) IsExtension() bool { return false }
358func (fd *Field) IsWeak() bool { return fd.L1.IsWeak }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530359func (fd *Field) IsList() bool { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
Naveen Sampath04696f72022-06-13 15:19:14 +0530360func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530361func (fd *Field) MapKey() protoreflect.FieldDescriptor {
Naveen Sampath04696f72022-06-13 15:19:14 +0530362 if !fd.IsMap() {
363 return nil
364 }
365 return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
366}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530367func (fd *Field) MapValue() protoreflect.FieldDescriptor {
Naveen Sampath04696f72022-06-13 15:19:14 +0530368 if !fd.IsMap() {
369 return nil
370 }
371 return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
372}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530373func (fd *Field) HasDefault() bool { return fd.L1.Default.has }
374func (fd *Field) Default() protoreflect.Value { return fd.L1.Default.get(fd) }
375func (fd *Field) DefaultEnumValue() protoreflect.EnumValueDescriptor { return fd.L1.Default.enum }
376func (fd *Field) ContainingOneof() protoreflect.OneofDescriptor { return fd.L1.ContainingOneof }
377func (fd *Field) ContainingMessage() protoreflect.MessageDescriptor {
378 return fd.L0.Parent.(protoreflect.MessageDescriptor)
Naveen Sampath04696f72022-06-13 15:19:14 +0530379}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530380func (fd *Field) Enum() protoreflect.EnumDescriptor {
Naveen Sampath04696f72022-06-13 15:19:14 +0530381 return fd.L1.Enum
382}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530383func (fd *Field) Message() protoreflect.MessageDescriptor {
Naveen Sampath04696f72022-06-13 15:19:14 +0530384 if fd.L1.IsWeak {
385 if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530386 return d.(protoreflect.MessageDescriptor)
Naveen Sampath04696f72022-06-13 15:19:14 +0530387 }
388 }
389 return fd.L1.Message
390}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530391func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) }
392func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530393
394// EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8
395// validation for the string field. This exists for Google-internal use only
396// since proto3 did not enforce UTF-8 validity prior to the open-source release.
397// If this method does not exist, the default is to enforce valid UTF-8.
398//
399// WARNING: This method is exempt from the compatibility promise and may be
400// removed in the future without warning.
401func (fd *Field) EnforceUTF8() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530402 if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
403 return fd.L1.EditionFeatures.IsUTF8Validated
404 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530405 if fd.L1.HasEnforceUTF8 {
406 return fd.L1.EnforceUTF8
407 }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530408 return fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3
Naveen Sampath04696f72022-06-13 15:19:14 +0530409}
410
411func (od *Oneof) IsSynthetic() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530412 return od.L0.ParentFile.L1.Syntax == protoreflect.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
Naveen Sampath04696f72022-06-13 15:19:14 +0530413}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530414func (od *Oneof) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530415 if f := od.L1.Options; f != nil {
416 return f()
417 }
418 return descopts.Oneof
419}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530420func (od *Oneof) Fields() protoreflect.FieldDescriptors { return &od.L1.Fields }
421func (od *Oneof) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, od) }
422func (od *Oneof) ProtoType(protoreflect.OneofDescriptor) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530423
424type (
425 Extension struct {
426 Base
427 L1 ExtensionL1
428 L2 *ExtensionL2 // protected by fileDesc.once
429 }
430 ExtensionL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530431 Number protoreflect.FieldNumber
432 Extendee protoreflect.MessageDescriptor
433 Cardinality protoreflect.Cardinality
434 Kind protoreflect.Kind
435 EditionFeatures EditionFeatures
Naveen Sampath04696f72022-06-13 15:19:14 +0530436 }
437 ExtensionL2 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530438 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +0530439 StringName stringName
440 IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
441 IsPacked bool // promoted from google.protobuf.FieldOptions
442 Default defaultValue
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530443 Enum protoreflect.EnumDescriptor
444 Message protoreflect.MessageDescriptor
Naveen Sampath04696f72022-06-13 15:19:14 +0530445 }
446)
447
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530448func (xd *Extension) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530449 if f := xd.lazyInit().Options; f != nil {
450 return f()
451 }
452 return descopts.Field
453}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530454func (xd *Extension) Number() protoreflect.FieldNumber { return xd.L1.Number }
455func (xd *Extension) Cardinality() protoreflect.Cardinality { return xd.L1.Cardinality }
456func (xd *Extension) Kind() protoreflect.Kind { return xd.L1.Kind }
457func (xd *Extension) HasJSONName() bool { return xd.lazyInit().StringName.hasJSON }
458func (xd *Extension) JSONName() string { return xd.lazyInit().StringName.getJSON(xd) }
459func (xd *Extension) TextName() string { return xd.lazyInit().StringName.getText(xd) }
460func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != protoreflect.Repeated }
Naveen Sampath04696f72022-06-13 15:19:14 +0530461func (xd *Extension) HasOptionalKeyword() bool {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530462 return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional
Naveen Sampath04696f72022-06-13 15:19:14 +0530463}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530464func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked }
465func (xd *Extension) IsExtension() bool { return true }
466func (xd *Extension) IsWeak() bool { return false }
467func (xd *Extension) IsList() bool { return xd.Cardinality() == protoreflect.Repeated }
468func (xd *Extension) IsMap() bool { return false }
469func (xd *Extension) MapKey() protoreflect.FieldDescriptor { return nil }
470func (xd *Extension) MapValue() protoreflect.FieldDescriptor { return nil }
471func (xd *Extension) HasDefault() bool { return xd.lazyInit().Default.has }
472func (xd *Extension) Default() protoreflect.Value { return xd.lazyInit().Default.get(xd) }
473func (xd *Extension) DefaultEnumValue() protoreflect.EnumValueDescriptor {
474 return xd.lazyInit().Default.enum
475}
476func (xd *Extension) ContainingOneof() protoreflect.OneofDescriptor { return nil }
477func (xd *Extension) ContainingMessage() protoreflect.MessageDescriptor { return xd.L1.Extendee }
478func (xd *Extension) Enum() protoreflect.EnumDescriptor { return xd.lazyInit().Enum }
479func (xd *Extension) Message() protoreflect.MessageDescriptor { return xd.lazyInit().Message }
480func (xd *Extension) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, xd) }
481func (xd *Extension) ProtoType(protoreflect.FieldDescriptor) {}
482func (xd *Extension) ProtoInternal(pragma.DoNotImplement) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530483func (xd *Extension) lazyInit() *ExtensionL2 {
484 xd.L0.ParentFile.lazyInit() // implicitly initializes L2
485 return xd.L2
486}
487
488type (
489 Service struct {
490 Base
491 L1 ServiceL1
492 L2 *ServiceL2 // protected by fileDesc.once
493 }
494 ServiceL1 struct{}
495 ServiceL2 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530496 Options func() protoreflect.ProtoMessage
Naveen Sampath04696f72022-06-13 15:19:14 +0530497 Methods Methods
498 }
499
500 Method struct {
501 Base
502 L1 MethodL1
503 }
504 MethodL1 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530505 Options func() protoreflect.ProtoMessage
506 Input protoreflect.MessageDescriptor
507 Output protoreflect.MessageDescriptor
Naveen Sampath04696f72022-06-13 15:19:14 +0530508 IsStreamingClient bool
509 IsStreamingServer bool
510 }
511)
512
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530513func (sd *Service) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530514 if f := sd.lazyInit().Options; f != nil {
515 return f()
516 }
517 return descopts.Service
518}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530519func (sd *Service) Methods() protoreflect.MethodDescriptors { return &sd.lazyInit().Methods }
520func (sd *Service) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, sd) }
521func (sd *Service) ProtoType(protoreflect.ServiceDescriptor) {}
522func (sd *Service) ProtoInternal(pragma.DoNotImplement) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530523func (sd *Service) lazyInit() *ServiceL2 {
524 sd.L0.ParentFile.lazyInit() // implicitly initializes L2
525 return sd.L2
526}
527
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530528func (md *Method) Options() protoreflect.ProtoMessage {
Naveen Sampath04696f72022-06-13 15:19:14 +0530529 if f := md.L1.Options; f != nil {
530 return f()
531 }
532 return descopts.Method
533}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530534func (md *Method) Input() protoreflect.MessageDescriptor { return md.L1.Input }
535func (md *Method) Output() protoreflect.MessageDescriptor { return md.L1.Output }
536func (md *Method) IsStreamingClient() bool { return md.L1.IsStreamingClient }
537func (md *Method) IsStreamingServer() bool { return md.L1.IsStreamingServer }
538func (md *Method) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) }
539func (md *Method) ProtoType(protoreflect.MethodDescriptor) {}
540func (md *Method) ProtoInternal(pragma.DoNotImplement) {}
Naveen Sampath04696f72022-06-13 15:19:14 +0530541
542// Surrogate files are can be used to create standalone descriptors
543// where the syntax is only information derived from the parent file.
544var (
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530545 SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}}
546 SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}}
Naveen Sampath04696f72022-06-13 15:19:14 +0530547)
548
549type (
550 Base struct {
551 L0 BaseL0
552 }
553 BaseL0 struct {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530554 FullName protoreflect.FullName // must be populated
555 ParentFile *File // must be populated
556 Parent protoreflect.Descriptor
Naveen Sampath04696f72022-06-13 15:19:14 +0530557 Index int
558 }
559)
560
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530561func (d *Base) Name() protoreflect.Name { return d.L0.FullName.Name() }
562func (d *Base) FullName() protoreflect.FullName { return d.L0.FullName }
563func (d *Base) ParentFile() protoreflect.FileDescriptor {
Naveen Sampath04696f72022-06-13 15:19:14 +0530564 if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 {
565 return nil // surrogate files are not real parents
566 }
567 return d.L0.ParentFile
568}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530569func (d *Base) Parent() protoreflect.Descriptor { return d.L0.Parent }
Naveen Sampath04696f72022-06-13 15:19:14 +0530570func (d *Base) Index() int { return d.L0.Index }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530571func (d *Base) Syntax() protoreflect.Syntax { return d.L0.ParentFile.Syntax() }
Naveen Sampath04696f72022-06-13 15:19:14 +0530572func (d *Base) IsPlaceholder() bool { return false }
573func (d *Base) ProtoInternal(pragma.DoNotImplement) {}
574
575type stringName struct {
576 hasJSON bool
577 once sync.Once
578 nameJSON string
579 nameText string
580}
581
582// InitJSON initializes the name. It is exported for use by other internal packages.
583func (s *stringName) InitJSON(name string) {
584 s.hasJSON = true
585 s.nameJSON = name
586}
587
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530588func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
Naveen Sampath04696f72022-06-13 15:19:14 +0530589 s.once.Do(func() {
590 if fd.IsExtension() {
591 // For extensions, JSON and text are formatted the same way.
592 var name string
593 if messageset.IsMessageSetExtension(fd) {
594 name = string("[" + fd.FullName().Parent() + "]")
595 } else {
596 name = string("[" + fd.FullName() + "]")
597 }
598 s.nameJSON = name
599 s.nameText = name
600 } else {
601 // Format the JSON name.
602 if !s.hasJSON {
603 s.nameJSON = strs.JSONCamelCase(string(fd.Name()))
604 }
605
606 // Format the text name.
607 s.nameText = string(fd.Name())
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530608 if fd.Kind() == protoreflect.GroupKind {
Naveen Sampath04696f72022-06-13 15:19:14 +0530609 s.nameText = string(fd.Message().Name())
610 }
611 }
612 })
613 return s
614}
615
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530616func (s *stringName) getJSON(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameJSON }
617func (s *stringName) getText(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameText }
Naveen Sampath04696f72022-06-13 15:19:14 +0530618
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530619func DefaultValue(v protoreflect.Value, ev protoreflect.EnumValueDescriptor) defaultValue {
Naveen Sampath04696f72022-06-13 15:19:14 +0530620 dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
621 if b, ok := v.Interface().([]byte); ok {
622 // Store a copy of the default bytes, so that we can detect
623 // accidental mutations of the original value.
624 dv.bytes = append([]byte(nil), b...)
625 }
626 return dv
627}
628
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530629func unmarshalDefault(b []byte, k protoreflect.Kind, pf *File, ed protoreflect.EnumDescriptor) defaultValue {
630 var evs protoreflect.EnumValueDescriptors
631 if k == protoreflect.EnumKind {
Naveen Sampath04696f72022-06-13 15:19:14 +0530632 // If the enum is declared within the same file, be careful not to
633 // blindly call the Values method, lest we bind ourselves in a deadlock.
634 if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf {
635 evs = &e.L2.Values
636 } else {
637 evs = ed.Values()
638 }
639
640 // If we are unable to resolve the enum dependency, use a placeholder
641 // enum value since we will not be able to parse the default value.
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530642 if ed.IsPlaceholder() && protoreflect.Name(b).IsValid() {
643 v := protoreflect.ValueOfEnum(0)
644 ev := PlaceholderEnumValue(ed.FullName().Parent().Append(protoreflect.Name(b)))
Naveen Sampath04696f72022-06-13 15:19:14 +0530645 return DefaultValue(v, ev)
646 }
647 }
648
649 v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor)
650 if err != nil {
651 panic(err)
652 }
653 return DefaultValue(v, ev)
654}
655
656type defaultValue struct {
657 has bool
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530658 val protoreflect.Value
659 enum protoreflect.EnumValueDescriptor
Naveen Sampath04696f72022-06-13 15:19:14 +0530660 bytes []byte
661}
662
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530663func (dv *defaultValue) get(fd protoreflect.FieldDescriptor) protoreflect.Value {
Naveen Sampath04696f72022-06-13 15:19:14 +0530664 // Return the zero value as the default if unpopulated.
665 if !dv.has {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530666 if fd.Cardinality() == protoreflect.Repeated {
667 return protoreflect.Value{}
Naveen Sampath04696f72022-06-13 15:19:14 +0530668 }
669 switch fd.Kind() {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530670 case protoreflect.BoolKind:
671 return protoreflect.ValueOfBool(false)
672 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
673 return protoreflect.ValueOfInt32(0)
674 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
675 return protoreflect.ValueOfInt64(0)
676 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
677 return protoreflect.ValueOfUint32(0)
678 case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
679 return protoreflect.ValueOfUint64(0)
680 case protoreflect.FloatKind:
681 return protoreflect.ValueOfFloat32(0)
682 case protoreflect.DoubleKind:
683 return protoreflect.ValueOfFloat64(0)
684 case protoreflect.StringKind:
685 return protoreflect.ValueOfString("")
686 case protoreflect.BytesKind:
687 return protoreflect.ValueOfBytes(nil)
688 case protoreflect.EnumKind:
Naveen Sampath04696f72022-06-13 15:19:14 +0530689 if evs := fd.Enum().Values(); evs.Len() > 0 {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530690 return protoreflect.ValueOfEnum(evs.Get(0).Number())
Naveen Sampath04696f72022-06-13 15:19:14 +0530691 }
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530692 return protoreflect.ValueOfEnum(0)
Naveen Sampath04696f72022-06-13 15:19:14 +0530693 }
694 }
695
696 if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) {
697 // TODO: Avoid panic if we're running with the race detector
698 // and instead spawn a goroutine that periodically resets
699 // this value back to the original to induce a race.
700 panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
701 }
702 return dv.val
703}