|  | // Copyright 2024 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package filedesc | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  |  | 
|  | "google.golang.org/protobuf/encoding/protowire" | 
|  | "google.golang.org/protobuf/internal/editiondefaults" | 
|  | "google.golang.org/protobuf/internal/genid" | 
|  | "google.golang.org/protobuf/reflect/protoreflect" | 
|  | ) | 
|  |  | 
|  | var defaultsCache = make(map[Edition]EditionFeatures) | 
|  | var defaultsKeys = []Edition{} | 
|  |  | 
|  | func init() { | 
|  | unmarshalEditionDefaults(editiondefaults.Defaults) | 
|  | SurrogateProto2.L1.EditionFeatures = getFeaturesFor(EditionProto2) | 
|  | SurrogateProto3.L1.EditionFeatures = getFeaturesFor(EditionProto3) | 
|  | SurrogateEdition2023.L1.EditionFeatures = getFeaturesFor(Edition2023) | 
|  | } | 
|  |  | 
|  | func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures { | 
|  | for len(b) > 0 { | 
|  | num, _, n := protowire.ConsumeTag(b) | 
|  | b = b[n:] | 
|  | switch num { | 
|  | case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number: | 
|  | v, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v) | 
|  | case genid.GoFeatures_ApiLevel_field_number: | 
|  | v, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | parent.APILevel = int(v) | 
|  | case genid.GoFeatures_StripEnumPrefix_field_number: | 
|  | v, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | parent.StripEnumPrefix = int(v) | 
|  | default: | 
|  | panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num)) | 
|  | } | 
|  | } | 
|  | return parent | 
|  | } | 
|  |  | 
|  | func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures { | 
|  | for len(b) > 0 { | 
|  | num, typ, n := protowire.ConsumeTag(b) | 
|  | b = b[n:] | 
|  | switch typ { | 
|  | case protowire.VarintType: | 
|  | v, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | switch num { | 
|  | case genid.FeatureSet_FieldPresence_field_number: | 
|  | parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value | 
|  | parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value | 
|  | case genid.FeatureSet_EnumType_field_number: | 
|  | parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value | 
|  | case genid.FeatureSet_RepeatedFieldEncoding_field_number: | 
|  | parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value | 
|  | case genid.FeatureSet_Utf8Validation_field_number: | 
|  | parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value | 
|  | case genid.FeatureSet_MessageEncoding_field_number: | 
|  | parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value | 
|  | case genid.FeatureSet_JsonFormat_field_number: | 
|  | parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value | 
|  | default: | 
|  | panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num)) | 
|  | } | 
|  | case protowire.BytesType: | 
|  | v, m := protowire.ConsumeBytes(b) | 
|  | b = b[m:] | 
|  | switch num { | 
|  | case genid.FeatureSet_Go_ext_number: | 
|  | parent = unmarshalGoFeature(v, parent) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return parent | 
|  | } | 
|  |  | 
|  | func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures { | 
|  | var parentFS EditionFeatures | 
|  | switch p := parentDesc.(type) { | 
|  | case *File: | 
|  | parentFS = p.L1.EditionFeatures | 
|  | case *Message: | 
|  | parentFS = p.L1.EditionFeatures | 
|  | default: | 
|  | panic(fmt.Sprintf("unknown parent type %T", parentDesc)) | 
|  | } | 
|  | return parentFS | 
|  | } | 
|  |  | 
|  | func unmarshalEditionDefault(b []byte) { | 
|  | var ed Edition | 
|  | var fs EditionFeatures | 
|  | for len(b) > 0 { | 
|  | num, typ, n := protowire.ConsumeTag(b) | 
|  | b = b[n:] | 
|  | switch typ { | 
|  | case protowire.VarintType: | 
|  | v, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | switch num { | 
|  | case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number: | 
|  | ed = Edition(v) | 
|  | } | 
|  | case protowire.BytesType: | 
|  | v, m := protowire.ConsumeBytes(b) | 
|  | b = b[m:] | 
|  | switch num { | 
|  | case genid.FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number: | 
|  | fs = unmarshalFeatureSet(v, fs) | 
|  | case genid.FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number: | 
|  | fs = unmarshalFeatureSet(v, fs) | 
|  | } | 
|  | } | 
|  | } | 
|  | defaultsCache[ed] = fs | 
|  | defaultsKeys = append(defaultsKeys, ed) | 
|  | } | 
|  |  | 
|  | func unmarshalEditionDefaults(b []byte) { | 
|  | for len(b) > 0 { | 
|  | num, _, n := protowire.ConsumeTag(b) | 
|  | b = b[n:] | 
|  | switch num { | 
|  | case genid.FeatureSetDefaults_Defaults_field_number: | 
|  | def, m := protowire.ConsumeBytes(b) | 
|  | b = b[m:] | 
|  | unmarshalEditionDefault(def) | 
|  | case genid.FeatureSetDefaults_MinimumEdition_field_number, | 
|  | genid.FeatureSetDefaults_MaximumEdition_field_number: | 
|  | // We don't care about the minimum and maximum editions. If the | 
|  | // edition we are looking for later on is not in the cache we know | 
|  | // it is outside of the range between minimum and maximum edition. | 
|  | _, m := protowire.ConsumeVarint(b) | 
|  | b = b[m:] | 
|  | default: | 
|  | panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num)) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func getFeaturesFor(ed Edition) EditionFeatures { | 
|  | match := EditionUnknown | 
|  | for _, key := range defaultsKeys { | 
|  | if key > ed { | 
|  | break | 
|  | } | 
|  | match = key | 
|  | } | 
|  | if match == EditionUnknown { | 
|  | panic(fmt.Sprintf("unsupported edition: %v", ed)) | 
|  | } | 
|  | return defaultsCache[match] | 
|  | } |