blob: 10132c9b384790cef988c0be316760694fcd00ca [file] [log] [blame]
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301// Copyright 2024 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
5package filedesc
6
7import (
8 "fmt"
9
10 "google.golang.org/protobuf/encoding/protowire"
11 "google.golang.org/protobuf/internal/editiondefaults"
12 "google.golang.org/protobuf/internal/genid"
13 "google.golang.org/protobuf/reflect/protoreflect"
14)
15
16var defaultsCache = make(map[Edition]EditionFeatures)
17var defaultsKeys = []Edition{}
18
19func init() {
20 unmarshalEditionDefaults(editiondefaults.Defaults)
21 SurrogateProto2.L1.EditionFeatures = getFeaturesFor(EditionProto2)
22 SurrogateProto3.L1.EditionFeatures = getFeaturesFor(EditionProto3)
23 SurrogateEdition2023.L1.EditionFeatures = getFeaturesFor(Edition2023)
24}
25
26func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
27 for len(b) > 0 {
28 num, _, n := protowire.ConsumeTag(b)
29 b = b[n:]
30 switch num {
31 case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
32 v, m := protowire.ConsumeVarint(b)
33 b = b[m:]
34 parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
35 case genid.GoFeatures_ApiLevel_field_number:
36 v, m := protowire.ConsumeVarint(b)
37 b = b[m:]
38 parent.APILevel = int(v)
39 case genid.GoFeatures_StripEnumPrefix_field_number:
40 v, m := protowire.ConsumeVarint(b)
41 b = b[m:]
42 parent.StripEnumPrefix = int(v)
43 default:
44 panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
45 }
46 }
47 return parent
48}
49
50func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
51 for len(b) > 0 {
52 num, typ, n := protowire.ConsumeTag(b)
53 b = b[n:]
54 switch typ {
55 case protowire.VarintType:
56 v, m := protowire.ConsumeVarint(b)
57 b = b[m:]
58 switch num {
59 case genid.FeatureSet_FieldPresence_field_number:
60 parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
61 parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
62 case genid.FeatureSet_EnumType_field_number:
63 parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
64 case genid.FeatureSet_RepeatedFieldEncoding_field_number:
65 parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
66 case genid.FeatureSet_Utf8Validation_field_number:
67 parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
68 case genid.FeatureSet_MessageEncoding_field_number:
69 parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
70 case genid.FeatureSet_JsonFormat_field_number:
71 parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
72 default:
73 panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
74 }
75 case protowire.BytesType:
76 v, m := protowire.ConsumeBytes(b)
77 b = b[m:]
78 switch num {
79 case genid.FeatureSet_Go_ext_number:
80 parent = unmarshalGoFeature(v, parent)
81 }
82 }
83 }
84
85 return parent
86}
87
88func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
89 var parentFS EditionFeatures
90 switch p := parentDesc.(type) {
91 case *File:
92 parentFS = p.L1.EditionFeatures
93 case *Message:
94 parentFS = p.L1.EditionFeatures
95 default:
96 panic(fmt.Sprintf("unknown parent type %T", parentDesc))
97 }
98 return parentFS
99}
100
101func unmarshalEditionDefault(b []byte) {
102 var ed Edition
103 var fs EditionFeatures
104 for len(b) > 0 {
105 num, typ, n := protowire.ConsumeTag(b)
106 b = b[n:]
107 switch typ {
108 case protowire.VarintType:
109 v, m := protowire.ConsumeVarint(b)
110 b = b[m:]
111 switch num {
112 case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
113 ed = Edition(v)
114 }
115 case protowire.BytesType:
116 v, m := protowire.ConsumeBytes(b)
117 b = b[m:]
118 switch num {
119 case genid.FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number:
120 fs = unmarshalFeatureSet(v, fs)
121 case genid.FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number:
122 fs = unmarshalFeatureSet(v, fs)
123 }
124 }
125 }
126 defaultsCache[ed] = fs
127 defaultsKeys = append(defaultsKeys, ed)
128}
129
130func unmarshalEditionDefaults(b []byte) {
131 for len(b) > 0 {
132 num, _, n := protowire.ConsumeTag(b)
133 b = b[n:]
134 switch num {
135 case genid.FeatureSetDefaults_Defaults_field_number:
136 def, m := protowire.ConsumeBytes(b)
137 b = b[m:]
138 unmarshalEditionDefault(def)
139 case genid.FeatureSetDefaults_MinimumEdition_field_number,
140 genid.FeatureSetDefaults_MaximumEdition_field_number:
141 // We don't care about the minimum and maximum editions. If the
142 // edition we are looking for later on is not in the cache we know
143 // it is outside of the range between minimum and maximum edition.
144 _, m := protowire.ConsumeVarint(b)
145 b = b[m:]
146 default:
147 panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
148 }
149 }
150}
151
152func getFeaturesFor(ed Edition) EditionFeatures {
153 match := EditionUnknown
154 for _, key := range defaultsKeys {
155 if key > ed {
156 break
157 }
158 match = key
159 }
160 if match == EditionUnknown {
161 panic(fmt.Sprintf("unsupported edition: %v", ed))
162 }
163 return defaultsCache[match]
164}