editions.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 protodesc
  5. import (
  6. _ "embed"
  7. "fmt"
  8. "os"
  9. "sync"
  10. "google.golang.org/protobuf/internal/filedesc"
  11. "google.golang.org/protobuf/proto"
  12. "google.golang.org/protobuf/types/descriptorpb"
  13. )
  14. const (
  15. SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2
  16. SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
  17. )
  18. //go:embed editions_defaults.binpb
  19. var binaryEditionDefaults []byte
  20. var defaults = &descriptorpb.FeatureSetDefaults{}
  21. var defaultsCacheMu sync.Mutex
  22. var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)
  23. func init() {
  24. err := proto.Unmarshal(binaryEditionDefaults, defaults)
  25. if err != nil {
  26. fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err)
  27. os.Exit(1)
  28. }
  29. }
  30. func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition {
  31. return filedesc.Edition(epb)
  32. }
  33. func toEditionProto(ed filedesc.Edition) descriptorpb.Edition {
  34. switch ed {
  35. case filedesc.EditionUnknown:
  36. return descriptorpb.Edition_EDITION_UNKNOWN
  37. case filedesc.EditionProto2:
  38. return descriptorpb.Edition_EDITION_PROTO2
  39. case filedesc.EditionProto3:
  40. return descriptorpb.Edition_EDITION_PROTO3
  41. case filedesc.Edition2023:
  42. return descriptorpb.Edition_EDITION_2023
  43. default:
  44. panic(fmt.Sprintf("unknown value for edition: %v", ed))
  45. }
  46. }
  47. func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet {
  48. defaultsCacheMu.Lock()
  49. defer defaultsCacheMu.Unlock()
  50. if def, ok := defaultsCache[ed]; ok {
  51. return def
  52. }
  53. edpb := toEditionProto(ed)
  54. if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
  55. // This should never happen protodesc.(FileOptions).New would fail when
  56. // initializing the file descriptor.
  57. // This most likely means the embedded defaults were not updated.
  58. fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb)
  59. os.Exit(1)
  60. }
  61. fs := defaults.GetDefaults()[0].GetFeatures()
  62. // Using a linear search for now.
  63. // Editions are guaranteed to be sorted and thus we could use a binary search.
  64. // Given that there are only a handful of editions (with one more per year)
  65. // there is not much reason to use a binary search.
  66. for _, def := range defaults.GetDefaults() {
  67. if def.GetEdition() <= edpb {
  68. fs = def.GetFeatures()
  69. } else {
  70. break
  71. }
  72. }
  73. defaultsCache[ed] = fs
  74. return fs
  75. }
  76. func resolveFeatureHasFieldPresence(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
  77. fs := fieldDesc.GetOptions().GetFeatures()
  78. if fs == nil || fs.FieldPresence == nil {
  79. return fileDesc.L1.EditionFeatures.IsFieldPresence
  80. }
  81. return fs.GetFieldPresence() == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
  82. fs.GetFieldPresence() == descriptorpb.FeatureSet_EXPLICIT
  83. }
  84. func resolveFeatureRepeatedFieldEncodingPacked(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
  85. fs := fieldDesc.GetOptions().GetFeatures()
  86. if fs == nil || fs.RepeatedFieldEncoding == nil {
  87. return fileDesc.L1.EditionFeatures.IsPacked
  88. }
  89. return fs.GetRepeatedFieldEncoding() == descriptorpb.FeatureSet_PACKED
  90. }
  91. func resolveFeatureEnforceUTF8(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
  92. fs := fieldDesc.GetOptions().GetFeatures()
  93. if fs == nil || fs.Utf8Validation == nil {
  94. return fileDesc.L1.EditionFeatures.IsUTF8Validated
  95. }
  96. return fs.GetUtf8Validation() == descriptorpb.FeatureSet_VERIFY
  97. }
  98. func resolveFeatureDelimitedEncoding(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
  99. fs := fieldDesc.GetOptions().GetFeatures()
  100. if fs == nil || fs.MessageEncoding == nil {
  101. return fileDesc.L1.EditionFeatures.IsDelimitedEncoded
  102. }
  103. return fs.GetMessageEncoding() == descriptorpb.FeatureSet_DELIMITED
  104. }
  105. // initFileDescFromFeatureSet initializes editions related fields in fd based
  106. // on fs. If fs is nil it is assumed to be an empty featureset and all fields
  107. // will be initialized with the appropriate default. fd.L1.Edition must be set
  108. // before calling this function.
  109. func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) {
  110. dfs := getFeatureSetFor(fd.L1.Edition)
  111. if fs == nil {
  112. fs = &descriptorpb.FeatureSet{}
  113. }
  114. var fieldPresence descriptorpb.FeatureSet_FieldPresence
  115. if fp := fs.FieldPresence; fp != nil {
  116. fieldPresence = *fp
  117. } else {
  118. fieldPresence = *dfs.FieldPresence
  119. }
  120. fd.L1.EditionFeatures.IsFieldPresence = fieldPresence == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
  121. fieldPresence == descriptorpb.FeatureSet_EXPLICIT
  122. var enumType descriptorpb.FeatureSet_EnumType
  123. if et := fs.EnumType; et != nil {
  124. enumType = *et
  125. } else {
  126. enumType = *dfs.EnumType
  127. }
  128. fd.L1.EditionFeatures.IsOpenEnum = enumType == descriptorpb.FeatureSet_OPEN
  129. var respeatedFieldEncoding descriptorpb.FeatureSet_RepeatedFieldEncoding
  130. if rfe := fs.RepeatedFieldEncoding; rfe != nil {
  131. respeatedFieldEncoding = *rfe
  132. } else {
  133. respeatedFieldEncoding = *dfs.RepeatedFieldEncoding
  134. }
  135. fd.L1.EditionFeatures.IsPacked = respeatedFieldEncoding == descriptorpb.FeatureSet_PACKED
  136. var isUTF8Validated descriptorpb.FeatureSet_Utf8Validation
  137. if utf8val := fs.Utf8Validation; utf8val != nil {
  138. isUTF8Validated = *utf8val
  139. } else {
  140. isUTF8Validated = *dfs.Utf8Validation
  141. }
  142. fd.L1.EditionFeatures.IsUTF8Validated = isUTF8Validated == descriptorpb.FeatureSet_VERIFY
  143. var messageEncoding descriptorpb.FeatureSet_MessageEncoding
  144. if me := fs.MessageEncoding; me != nil {
  145. messageEncoding = *me
  146. } else {
  147. messageEncoding = *dfs.MessageEncoding
  148. }
  149. fd.L1.EditionFeatures.IsDelimitedEncoded = messageEncoding == descriptorpb.FeatureSet_DELIMITED
  150. var jsonFormat descriptorpb.FeatureSet_JsonFormat
  151. if jf := fs.JsonFormat; jf != nil {
  152. jsonFormat = *jf
  153. } else {
  154. jsonFormat = *dfs.JsonFormat
  155. }
  156. fd.L1.EditionFeatures.IsJSONCompliant = jsonFormat == descriptorpb.FeatureSet_ALLOW
  157. }