type.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 prototype provides constructors for protoreflect.EnumType,
  5. // protoreflect.MessageType, and protoreflect.ExtensionType.
  6. package prototype
  7. import (
  8. "fmt"
  9. "reflect"
  10. "sync"
  11. "google.golang.org/protobuf/internal/descfmt"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. )
  14. // Enum is a protoreflect.EnumType which combines a
  15. // protoreflect.EnumDescriptor with a constructor function.
  16. //
  17. // Both EnumDescriptor and NewEnum must be populated.
  18. // Once constructed, the exported fields must not be modified.
  19. type Enum struct {
  20. protoreflect.EnumDescriptor
  21. // NewEnum constructs a new protoreflect.Enum representing the provided
  22. // enum number. The returned Go type must be identical for every call.
  23. NewEnum func(protoreflect.EnumNumber) protoreflect.Enum
  24. once sync.Once
  25. goType reflect.Type
  26. }
  27. func (t *Enum) New(n protoreflect.EnumNumber) protoreflect.Enum {
  28. e := t.NewEnum(n)
  29. t.once.Do(func() {
  30. t.goType = reflect.TypeOf(e)
  31. if e.Descriptor() != t.Descriptor() {
  32. panic(fmt.Sprintf("mismatching enum descriptor: got %v, want %v", e.Descriptor(), t.Descriptor()))
  33. }
  34. if e.Descriptor().IsPlaceholder() {
  35. panic("enum descriptor must not be a placeholder")
  36. }
  37. })
  38. if t.goType != reflect.TypeOf(e) {
  39. panic(fmt.Sprintf("mismatching types for enum: got %T, want %v", e, t.goType))
  40. }
  41. return e
  42. }
  43. func (t *Enum) GoType() reflect.Type {
  44. t.New(0) // initialize t.typ
  45. return t.goType
  46. }
  47. func (t *Enum) Descriptor() protoreflect.EnumDescriptor {
  48. return t.EnumDescriptor
  49. }
  50. func (t *Enum) Format(s fmt.State, r rune) {
  51. descfmt.FormatDesc(s, r, t)
  52. }
  53. // Message is a protoreflect.MessageType which combines a
  54. // protoreflect.MessageDescriptor with a constructor function.
  55. //
  56. // Both MessageDescriptor and NewMessage must be populated.
  57. // Once constructed, the exported fields must not be modified.
  58. type Message struct {
  59. protoreflect.MessageDescriptor
  60. // NewMessage constructs an empty, newly allocated protoreflect.Message.
  61. // The returned Go type must be identical for every call.
  62. NewMessage func() protoreflect.Message
  63. once sync.Once
  64. goType reflect.Type
  65. }
  66. func (t *Message) New() protoreflect.Message {
  67. m := t.NewMessage()
  68. mi := m.Interface()
  69. t.once.Do(func() {
  70. t.goType = reflect.TypeOf(mi)
  71. if m.Descriptor() != t.Descriptor() {
  72. panic(fmt.Sprintf("mismatching message descriptor: got %v, want %v", m.Descriptor(), t.Descriptor()))
  73. }
  74. if m.Descriptor().IsPlaceholder() {
  75. panic("message descriptor must not be a placeholder")
  76. }
  77. })
  78. if t.goType != reflect.TypeOf(mi) {
  79. panic(fmt.Sprintf("mismatching types for message: got %T, want %v", mi, t.goType))
  80. }
  81. return m
  82. }
  83. func (t *Message) Zero() protoreflect.Message {
  84. return t.New() // TODO: return a read-only message instead
  85. }
  86. func (t *Message) GoType() reflect.Type {
  87. t.New() // initialize t.goType
  88. return t.goType
  89. }
  90. func (t *Message) Descriptor() protoreflect.MessageDescriptor {
  91. return t.MessageDescriptor
  92. }
  93. func (t *Message) Format(s fmt.State, r rune) {
  94. descfmt.FormatDesc(s, r, t)
  95. }
  96. var (
  97. _ protoreflect.EnumType = (*Enum)(nil)
  98. _ protoreflect.MessageType = (*Message)(nil)
  99. )