desc.go 20 KB

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