blob: baa13fd8676f52798bb713499e15996a93807d6f [file] [log] [blame]
Joe Tsaif0c01e42018-11-06 13:05:20 -08001// Copyright 2018 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 impl
6
7import (
Joe Tsaif0c01e42018-11-06 13:05:20 -08008 "reflect"
9
Joe Tsaif18ab532018-11-27 17:25:04 -080010 papi "github.com/golang/protobuf/protoapi"
Joe Tsaif0c01e42018-11-06 13:05:20 -080011 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Joe Tsaif0c01e42018-11-06 13:05:20 -080012)
13
14func makeLegacyExtensionFieldsFunc(t reflect.Type) func(p *messageDataType) pref.KnownFields {
15 f := makeLegacyExtensionMapFunc(t)
16 if f == nil {
17 return nil
18 }
19 return func(p *messageDataType) pref.KnownFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080020 if p.p.IsNil() {
21 return emptyExtensionFields{}
22 }
Joe Tsaif0c01e42018-11-06 13:05:20 -080023 return legacyExtensionFields{p.mi, f(p)}
24 }
25}
26
Joe Tsaif18ab532018-11-27 17:25:04 -080027var (
28 extTypeA = reflect.TypeOf(map[int32]papi.ExtensionField(nil))
29 extTypeB = reflect.TypeOf(papi.XXX_InternalExtensions{})
30)
31
32func makeLegacyExtensionMapFunc(t reflect.Type) func(*messageDataType) papi.ExtensionFields {
33 fx1, _ := t.FieldByName("XXX_extensions")
34 fx2, _ := t.FieldByName("XXX_InternalExtensions")
35 switch {
36 case fx1.Type == extTypeA:
37 fieldOffset := offsetOf(fx1)
38 return func(p *messageDataType) papi.ExtensionFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080039 v := p.p.Apply(fieldOffset).AsValueOf(fx1.Type).Interface()
Joe Tsaif18ab532018-11-27 17:25:04 -080040 return papi.ExtensionFieldsOf(v)
41 }
42 case fx2.Type == extTypeB:
43 fieldOffset := offsetOf(fx2)
44 return func(p *messageDataType) papi.ExtensionFields {
Joe Tsai6cf80c42018-12-01 04:57:09 -080045 v := p.p.Apply(fieldOffset).AsValueOf(fx2.Type).Interface()
Joe Tsaif18ab532018-11-27 17:25:04 -080046 return papi.ExtensionFieldsOf(v)
47 }
48 default:
49 return nil
50 }
51}
52
Joe Tsaif0c01e42018-11-06 13:05:20 -080053type legacyExtensionFields struct {
54 mi *MessageType
Joe Tsaif18ab532018-11-27 17:25:04 -080055 x papi.ExtensionFields
Joe Tsaif0c01e42018-11-06 13:05:20 -080056}
57
58func (p legacyExtensionFields) Len() (n int) {
Joe Tsaif18ab532018-11-27 17:25:04 -080059 p.x.Range(func(num pref.FieldNumber, _ papi.ExtensionField) bool {
60 if p.Has(pref.FieldNumber(num)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -080061 n++
62 }
63 return true
64 })
65 return n
66}
67
68func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
69 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080070 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080071 return false
72 }
Joe Tsai08e00302018-11-26 22:32:06 -080073 t := legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -080074 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -080075 return t.ValueOf(x.Value).List().Len() > 0
Joe Tsaif0c01e42018-11-06 13:05:20 -080076 }
77 return true
78}
79
80func (p legacyExtensionFields) Get(n pref.FieldNumber) pref.Value {
81 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080082 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -080083 return pref.Value{}
84 }
Joe Tsai08e00302018-11-26 22:32:06 -080085 t := legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -080086 if x.Value == nil {
87 // NOTE: x.Value is never nil for Lists since they are always populated
Joe Tsaif6d4a422018-11-19 14:26:06 -080088 // during ExtensionFieldTypes.Register.
Joe Tsaif0c01e42018-11-06 13:05:20 -080089 if t.Kind() == pref.MessageKind || t.Kind() == pref.GroupKind {
Joe Tsaif0c01e42018-11-06 13:05:20 -080090 return pref.Value{}
91 }
92 return t.Default()
93 }
Joe Tsaif18ab532018-11-27 17:25:04 -080094 return t.ValueOf(x.Value)
Joe Tsaif0c01e42018-11-06 13:05:20 -080095}
96
97func (p legacyExtensionFields) Set(n pref.FieldNumber, v pref.Value) {
98 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -080099 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800100 panic("no extension descriptor registered")
101 }
Joe Tsai08e00302018-11-26 22:32:06 -0800102 t := legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -0800103 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800104 p.x.Set(n, x)
105}
106
107func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
108 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800109 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800110 return
111 }
Joe Tsai08e00302018-11-26 22:32:06 -0800112 t := legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800113 if t.Cardinality() == pref.Repeated {
Joe Tsaif18ab532018-11-27 17:25:04 -0800114 t.ValueOf(x.Value).List().Truncate(0)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800115 return
116 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800117 x.Value = nil
Joe Tsaif0c01e42018-11-06 13:05:20 -0800118 p.x.Set(n, x)
119}
120
121func (p legacyExtensionFields) Mutable(n pref.FieldNumber) pref.Mutable {
122 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800123 if x.Desc == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800124 panic("no extension descriptor registered")
125 }
Joe Tsai08e00302018-11-26 22:32:06 -0800126 t := legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif18ab532018-11-27 17:25:04 -0800127 if x.Value == nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800128 v := t.ValueOf(t.New())
Joe Tsaif18ab532018-11-27 17:25:04 -0800129 x.Value = t.InterfaceOf(v)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800130 p.x.Set(n, x)
131 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800132 return t.ValueOf(x.Value).Interface().(pref.Mutable)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800133}
134
135func (p legacyExtensionFields) Range(f func(pref.FieldNumber, pref.Value) bool) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800136 p.x.Range(func(n pref.FieldNumber, x papi.ExtensionField) bool {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800137 if p.Has(n) {
138 return f(n, p.Get(n))
139 }
140 return true
141 })
142}
143
144func (p legacyExtensionFields) ExtensionTypes() pref.ExtensionFieldTypes {
145 return legacyExtensionTypes(p)
146}
147
148type legacyExtensionTypes legacyExtensionFields
149
150func (p legacyExtensionTypes) Len() (n int) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800151 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
152 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800153 n++
154 }
155 return true
156 })
157 return n
158}
159
160func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
161 if p.mi.Type.FullName() != t.ExtendedType().FullName() {
162 panic("extended type mismatch")
163 }
164 if !p.mi.Type.ExtensionRanges().Has(t.Number()) {
165 panic("invalid extension field number")
166 }
167 x := p.x.Get(t.Number())
Joe Tsaif18ab532018-11-27 17:25:04 -0800168 if x.Desc != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800169 panic("extension descriptor already registered")
170 }
Joe Tsai08e00302018-11-26 22:32:06 -0800171 x.Desc = legacyWrapper.ExtensionDescFromType(t)
Joe Tsaif6d4a422018-11-19 14:26:06 -0800172 if t.Cardinality() == pref.Repeated {
173 // If the field is repeated, initialize the entry with an empty list
174 // so that future Get operations can return a mutable and concrete list.
Joe Tsaif18ab532018-11-27 17:25:04 -0800175 x.Value = t.InterfaceOf(t.ValueOf(t.New()))
Joe Tsaif6d4a422018-11-19 14:26:06 -0800176 }
Joe Tsaif0c01e42018-11-06 13:05:20 -0800177 p.x.Set(t.Number(), x)
178}
179
180func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
181 if !p.mi.Type.ExtensionRanges().Has(t.Number()) {
182 return
183 }
184 x := p.x.Get(t.Number())
Joe Tsaif6d4a422018-11-19 14:26:06 -0800185 if t.Cardinality() == pref.Repeated {
186 // Treat an empty repeated field as unpopulated.
Joe Tsaif18ab532018-11-27 17:25:04 -0800187 v := reflect.ValueOf(x.Value)
188 if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
189 x.Value = nil
Joe Tsaif6d4a422018-11-19 14:26:06 -0800190 }
191 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800192 if x.Value != nil {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800193 panic("value for extension descriptor still populated")
194 }
Joe Tsaif18ab532018-11-27 17:25:04 -0800195 x.Desc = nil
196 if len(x.Raw) == 0 {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800197 p.x.Clear(t.Number())
198 } else {
199 p.x.Set(t.Number(), x)
200 }
201}
202
203func (p legacyExtensionTypes) ByNumber(n pref.FieldNumber) pref.ExtensionType {
204 x := p.x.Get(n)
Joe Tsaif18ab532018-11-27 17:25:04 -0800205 if x.Desc != nil {
Joe Tsai08e00302018-11-26 22:32:06 -0800206 return legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800207 }
208 return nil
209}
210
211func (p legacyExtensionTypes) ByName(s pref.FullName) (t pref.ExtensionType) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800212 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
213 if x.Desc != nil && x.Desc.Name == string(s) {
Joe Tsai08e00302018-11-26 22:32:06 -0800214 t = legacyWrapper.ExtensionTypeFromDesc(x.Desc)
Joe Tsaif0c01e42018-11-06 13:05:20 -0800215 return false
216 }
217 return true
218 })
219 return t
220}
221
222func (p legacyExtensionTypes) Range(f func(pref.ExtensionType) bool) {
Joe Tsaif18ab532018-11-27 17:25:04 -0800223 p.x.Range(func(_ pref.FieldNumber, x papi.ExtensionField) bool {
224 if x.Desc != nil {
Joe Tsai08e00302018-11-26 22:32:06 -0800225 if !f(legacyWrapper.ExtensionTypeFromDesc(x.Desc)) {
Joe Tsaif0c01e42018-11-06 13:05:20 -0800226 return false
227 }
228 }
229 return true
230 })
231}