| // 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) |
| 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.GoFeatures_LegacyUnmarshalJsonEnum_field_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] |
| } |