blob: 0375a49d407a019febbbd22d15320b25e4182980 [file] [log] [blame]
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +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)
17
18func init() {
19 unmarshalEditionDefaults(editiondefaults.Defaults)
20}
21
22func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
23 for len(b) > 0 {
24 num, _, n := protowire.ConsumeTag(b)
25 b = b[n:]
26 switch num {
27 case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
28 v, m := protowire.ConsumeVarint(b)
29 b = b[m:]
30 parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
31 default:
32 panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
33 }
34 }
35 return parent
36}
37
38func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
39 for len(b) > 0 {
40 num, typ, n := protowire.ConsumeTag(b)
41 b = b[n:]
42 switch typ {
43 case protowire.VarintType:
44 v, m := protowire.ConsumeVarint(b)
45 b = b[m:]
46 switch num {
47 case genid.FeatureSet_FieldPresence_field_number:
48 parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
49 parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
50 case genid.FeatureSet_EnumType_field_number:
51 parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
52 case genid.FeatureSet_RepeatedFieldEncoding_field_number:
53 parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
54 case genid.FeatureSet_Utf8Validation_field_number:
55 parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
56 case genid.FeatureSet_MessageEncoding_field_number:
57 parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
58 case genid.FeatureSet_JsonFormat_field_number:
59 parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
60 default:
61 panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
62 }
63 case protowire.BytesType:
64 v, m := protowire.ConsumeBytes(b)
65 b = b[m:]
66 switch num {
67 case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
68 parent = unmarshalGoFeature(v, parent)
69 }
70 }
71 }
72
73 return parent
74}
75
76func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
77 var parentFS EditionFeatures
78 switch p := parentDesc.(type) {
79 case *File:
80 parentFS = p.L1.EditionFeatures
81 case *Message:
82 parentFS = p.L1.EditionFeatures
83 default:
84 panic(fmt.Sprintf("unknown parent type %T", parentDesc))
85 }
86 return parentFS
87}
88
89func unmarshalEditionDefault(b []byte) {
90 var ed Edition
91 var fs EditionFeatures
92 for len(b) > 0 {
93 num, typ, n := protowire.ConsumeTag(b)
94 b = b[n:]
95 switch typ {
96 case protowire.VarintType:
97 v, m := protowire.ConsumeVarint(b)
98 b = b[m:]
99 switch num {
100 case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
101 ed = Edition(v)
102 }
103 case protowire.BytesType:
104 v, m := protowire.ConsumeBytes(b)
105 b = b[m:]
106 switch num {
107 case genid.FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number:
108 fs = unmarshalFeatureSet(v, fs)
109 }
110 }
111 }
112 defaultsCache[ed] = fs
113}
114
115func unmarshalEditionDefaults(b []byte) {
116 for len(b) > 0 {
117 num, _, n := protowire.ConsumeTag(b)
118 b = b[n:]
119 switch num {
120 case genid.FeatureSetDefaults_Defaults_field_number:
121 def, m := protowire.ConsumeBytes(b)
122 b = b[m:]
123 unmarshalEditionDefault(def)
124 case genid.FeatureSetDefaults_MinimumEdition_field_number,
125 genid.FeatureSetDefaults_MaximumEdition_field_number:
126 // We don't care about the minimum and maximum editions. If the
127 // edition we are looking for later on is not in the cache we know
128 // it is outside of the range between minimum and maximum edition.
129 _, m := protowire.ConsumeVarint(b)
130 b = b[m:]
131 default:
132 panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
133 }
134 }
135}
136
137func getFeaturesFor(ed Edition) EditionFeatures {
138 if def, ok := defaultsCache[ed]; ok {
139 return def
140 }
141 panic(fmt.Sprintf("unsupported edition: %v", ed))
142}