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