blob: e486e9fa791adafe7e531a1c222c9d28a84a3a45 [file] [log] [blame]
Joe Tsaifa02f4e2018-09-12 16:20:37 -07001// 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 Tsaic6b75612018-09-13 14:24:37 -07008 "fmt"
Joe Tsaifa02f4e2018-09-12 16:20:37 -07009 "reflect"
10 "strconv"
11 "strings"
Joe Tsaic6b75612018-09-13 14:24:37 -070012 "sync"
Damien Neilc37adef2019-04-01 13:49:56 -070013 "sync/atomic"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070014
Damien Neile89e6242019-05-13 23:55:40 -070015 pvalue "google.golang.org/protobuf/internal/value"
16 pref "google.golang.org/protobuf/reflect/protoreflect"
17 piface "google.golang.org/protobuf/runtime/protoiface"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070018)
19
Joe Tsai4fe96632019-05-22 05:12:36 -040020// MessageInfo provides protobuf related functionality for a given Go type
21// that represents a message. A given instance of MessageInfo is tied to
Joe Tsaic6b75612018-09-13 14:24:37 -070022// exactly one Go type, which must be a pointer to a struct type.
Joe Tsai4fe96632019-05-22 05:12:36 -040023type MessageInfo struct {
Damien Neil8012b442019-01-18 09:32:24 -080024 // GoType is the underlying message Go type and must be populated.
Joe Tsaic6b75612018-09-13 14:24:37 -070025 // Once set, this field must never be mutated.
Damien Neil8012b442019-01-18 09:32:24 -080026 GoType reflect.Type // pointer to struct
27
28 // PBType is the underlying message descriptor type and must be populated.
29 // Once set, this field must never be mutated.
30 PBType pref.MessageType
Joe Tsaic6b75612018-09-13 14:24:37 -070031
Damien Neilc37adef2019-04-01 13:49:56 -070032 initMu sync.Mutex // protects all unexported fields
33 initDone uint32
Joe Tsaic6b75612018-09-13 14:24:37 -070034
Damien Neil4ae30bb2019-06-20 10:12:23 -070035 fields map[pref.FieldNumber]*fieldInfo
Joe Tsai4ec39c72019-04-03 13:40:53 -070036 oneofs map[pref.Name]*oneofInfo
Joe Tsaibe5348c2018-10-23 18:31:18 -070037
Joe Tsai378c1322019-04-25 23:48:08 -070038 getUnknown func(pointer) pref.RawFields
39 setUnknown func(pointer, pref.RawFields)
40
41 extensionMap func(pointer) *extensionMap
42
Damien Neil4ae30bb2019-06-20 10:12:23 -070043 // Information used by the fast-path methods.
Joe Tsai4a539f42019-06-17 12:30:25 -070044 methods piface.Methods
Damien Neil4ae30bb2019-06-20 10:12:23 -070045 coderMessageInfo
Damien Neilc37adef2019-04-01 13:49:56 -070046
Damien Neilc37adef2019-04-01 13:49:56 -070047 extensionFieldInfosMu sync.RWMutex
Joe Tsai89d49632019-06-04 16:20:00 -070048 extensionFieldInfos map[pref.ExtensionType]*extensionFieldInfo
Damien Neilc37adef2019-04-01 13:49:56 -070049}
50
51var prefMessageType = reflect.TypeOf((*pref.Message)(nil)).Elem()
52
Joe Tsai4fe96632019-05-22 05:12:36 -040053// getMessageInfo returns the MessageInfo (if any) for a type.
Damien Neilc37adef2019-04-01 13:49:56 -070054//
Joe Tsai4fe96632019-05-22 05:12:36 -040055// We find the MessageInfo by calling the ProtoReflect method on the type's
Damien Neilc37adef2019-04-01 13:49:56 -070056// zero value and looking at the returned type to see if it is a
Joe Tsai4fe96632019-05-22 05:12:36 -040057// messageReflectWrapper. Note that the MessageInfo may still be uninitialized
Damien Neilc37adef2019-04-01 13:49:56 -070058// at this point.
Joe Tsai4fe96632019-05-22 05:12:36 -040059func getMessageInfo(mt reflect.Type) (mi *MessageInfo, ok bool) {
Damien Neilc37adef2019-04-01 13:49:56 -070060 method, ok := mt.MethodByName("ProtoReflect")
61 if !ok {
62 return nil, false
63 }
64 if method.Type.NumIn() != 1 || method.Type.NumOut() != 1 || method.Type.Out(0) != prefMessageType {
65 return nil, false
66 }
67 ret := reflect.Zero(mt).Method(method.Index).Call(nil)
68 m, ok := ret[0].Elem().Interface().(*messageReflectWrapper)
69 if !ok {
70 return nil, ok
71 }
72 return m.mi, true
Joe Tsaifa02f4e2018-09-12 16:20:37 -070073}
74
Joe Tsai4fe96632019-05-22 05:12:36 -040075func (mi *MessageInfo) init() {
Damien Neilc37adef2019-04-01 13:49:56 -070076 // This function is called in the hot path. Inline the sync.Once
77 // logic, since allocating a closure for Once.Do is expensive.
78 // Keep init small to ensure that it can be inlined.
79 if atomic.LoadUint32(&mi.initDone) == 1 {
80 return
81 }
82 mi.initOnce()
83}
Joe Tsaic6b75612018-09-13 14:24:37 -070084
Joe Tsai4fe96632019-05-22 05:12:36 -040085func (mi *MessageInfo) initOnce() {
Damien Neilc37adef2019-04-01 13:49:56 -070086 mi.initMu.Lock()
87 defer mi.initMu.Unlock()
88 if mi.initDone == 1 {
89 return
90 }
91
92 t := mi.GoType
93 if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct {
94 panic(fmt.Sprintf("got %v, want *struct kind", t))
95 }
96
97 si := mi.makeStructInfo(t.Elem())
98 mi.makeKnownFieldsFunc(si)
99 mi.makeUnknownFieldsFunc(t.Elem())
100 mi.makeExtensionFieldsFunc(t.Elem())
Damien Neil4ae30bb2019-06-20 10:12:23 -0700101 mi.makeMethods(t.Elem(), si)
Damien Neilc37adef2019-04-01 13:49:56 -0700102
103 atomic.StoreUint32(&mi.initDone, 1)
104}
105
Joe Tsai378c1322019-04-25 23:48:08 -0700106type (
107 SizeCache = int32
108 UnknownFields = []byte
109 ExtensionFields = map[int32]ExtensionField
110)
111
112var (
113 sizecacheType = reflect.TypeOf(SizeCache(0))
114 unknownFieldsType = reflect.TypeOf(UnknownFields(nil))
115 extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
116)
Damien Neilc37adef2019-04-01 13:49:56 -0700117
Damien Neil3eaddf02019-05-09 11:33:55 -0700118type structInfo struct {
119 fieldsByNumber map[pref.FieldNumber]reflect.StructField
120 oneofsByName map[pref.Name]reflect.StructField
121 oneofWrappersByType map[reflect.Type]pref.FieldNumber
122 oneofWrappersByNumber map[pref.FieldNumber]reflect.Type
123}
124
Joe Tsai4fe96632019-05-22 05:12:36 -0400125func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700126 // Generate a mapping of field numbers and names to Go struct field or type.
Damien Neil3eaddf02019-05-09 11:33:55 -0700127 si := structInfo{
128 fieldsByNumber: map[pref.FieldNumber]reflect.StructField{},
129 oneofsByName: map[pref.Name]reflect.StructField{},
130 oneofWrappersByType: map[reflect.Type]pref.FieldNumber{},
131 oneofWrappersByNumber: map[pref.FieldNumber]reflect.Type{},
132 }
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700133fieldLoop:
134 for i := 0; i < t.NumField(); i++ {
135 f := t.Field(i)
136 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
137 if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
138 n, _ := strconv.ParseUint(s, 10, 64)
Damien Neil3eaddf02019-05-09 11:33:55 -0700139 si.fieldsByNumber[pref.FieldNumber(n)] = f
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700140 continue fieldLoop
141 }
142 }
143 if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 {
Damien Neil3eaddf02019-05-09 11:33:55 -0700144 si.oneofsByName[pref.Name(s)] = f
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700145 continue fieldLoop
146 }
147 }
Joe Tsaid7e97bc2018-11-26 12:57:27 -0800148 var oneofWrappers []interface{}
Joe Tsai2c870bb2018-10-17 11:46:52 -0700149 if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
Joe Tsaid7e97bc2018-11-26 12:57:27 -0800150 oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
151 }
152 if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
153 oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
154 }
155 for _, v := range oneofWrappers {
156 tf := reflect.TypeOf(v).Elem()
157 f := tf.Field(0)
158 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
159 if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
160 n, _ := strconv.ParseUint(s, 10, 64)
Damien Neil3eaddf02019-05-09 11:33:55 -0700161 si.oneofWrappersByType[tf] = pref.FieldNumber(n)
162 si.oneofWrappersByNumber[pref.FieldNumber(n)] = tf
Joe Tsaid7e97bc2018-11-26 12:57:27 -0800163 break
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700164 }
165 }
166 }
Damien Neil3eaddf02019-05-09 11:33:55 -0700167 return si
168}
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700169
Damien Neil3eaddf02019-05-09 11:33:55 -0700170// makeKnownFieldsFunc generates functions for operations that can be performed
171// on each protobuf message field. It takes in a reflect.Type representing the
172// Go struct and matches message fields with struct fields.
173//
174// This code assumes that the struct is well-formed and panics if there are
175// any discrepancies.
Joe Tsai4fe96632019-05-22 05:12:36 -0400176func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700177 mi.fields = map[pref.FieldNumber]*fieldInfo{}
Joe Tsai0fc49f82019-05-01 12:29:25 -0700178 for i := 0; i < mi.PBType.Descriptor().Fields().Len(); i++ {
179 fd := mi.PBType.Descriptor().Fields().Get(i)
Damien Neil3eaddf02019-05-09 11:33:55 -0700180 fs := si.fieldsByNumber[fd.Number()]
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700181 var fi fieldInfo
182 switch {
Joe Tsaiac31a352019-05-13 14:32:56 -0700183 case fd.ContainingOneof() != nil:
184 fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], si.oneofWrappersByNumber[fd.Number()])
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700185 case fd.IsMap():
186 fi = fieldInfoForMap(fd, fs)
Joe Tsaiac31a352019-05-13 14:32:56 -0700187 case fd.IsList():
Joe Tsai4b7aff62018-11-14 14:05:19 -0800188 fi = fieldInfoForList(fd, fs)
Joe Tsaic6b75612018-09-13 14:24:37 -0700189 case fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind:
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700190 fi = fieldInfoForMessage(fd, fs)
Joe Tsaic6b75612018-09-13 14:24:37 -0700191 default:
192 fi = fieldInfoForScalar(fd, fs)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700193 }
194 mi.fields[fd.Number()] = &fi
195 }
Joe Tsai4ec39c72019-04-03 13:40:53 -0700196
197 mi.oneofs = map[pref.Name]*oneofInfo{}
Joe Tsai0fc49f82019-05-01 12:29:25 -0700198 for i := 0; i < mi.PBType.Descriptor().Oneofs().Len(); i++ {
199 od := mi.PBType.Descriptor().Oneofs().Get(i)
Damien Neil3eaddf02019-05-09 11:33:55 -0700200 mi.oneofs[od.Name()] = makeOneofInfo(od, si.oneofsByName[od.Name()], si.oneofWrappersByType)
Joe Tsai4ec39c72019-04-03 13:40:53 -0700201 }
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700202}
Joe Tsaic6b75612018-09-13 14:24:37 -0700203
Joe Tsai4fe96632019-05-22 05:12:36 -0400204func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type) {
Joe Tsai378c1322019-04-25 23:48:08 -0700205 mi.getUnknown = func(pointer) pref.RawFields { return nil }
206 mi.setUnknown = func(pointer, pref.RawFields) { return }
207 fu, _ := t.FieldByName("XXX_unrecognized")
208 if fu.Type == unknownFieldsType {
209 fieldOffset := offsetOf(fu)
210 mi.getUnknown = func(p pointer) pref.RawFields {
211 if p.IsNil() {
212 return nil
213 }
214 rv := p.Apply(fieldOffset).AsValueOf(unknownFieldsType)
215 return pref.RawFields(*rv.Interface().(*[]byte))
216 }
217 mi.setUnknown = func(p pointer, b pref.RawFields) {
218 if p.IsNil() {
219 panic("invalid SetUnknown on nil Message")
220 }
221 rv := p.Apply(fieldOffset).AsValueOf(unknownFieldsType)
222 *rv.Interface().(*[]byte) = []byte(b)
223 }
224 } else {
225 mi.getUnknown = func(pointer) pref.RawFields {
226 return nil
227 }
228 mi.setUnknown = func(p pointer, _ pref.RawFields) {
229 if p.IsNil() {
230 panic("invalid SetUnknown on nil Message")
231 }
232 }
Joe Tsaibe5348c2018-10-23 18:31:18 -0700233 }
234}
235
Joe Tsai4fe96632019-05-22 05:12:36 -0400236func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type) {
Joe Tsai378c1322019-04-25 23:48:08 -0700237 fx, _ := t.FieldByName("XXX_extensions")
238 if fx.Type != extensionFieldsType {
239 fx, _ = t.FieldByName("XXX_InternalExtensions")
Joe Tsaif0c01e42018-11-06 13:05:20 -0800240 }
Joe Tsai378c1322019-04-25 23:48:08 -0700241 if fx.Type == extensionFieldsType {
242 fieldOffset := offsetOf(fx)
243 mi.extensionMap = func(p pointer) *extensionMap {
Joe Tsaid8881392019-06-06 13:01:53 -0700244 if p.IsNil() {
245 return (*extensionMap)(nil)
246 }
Joe Tsai378c1322019-04-25 23:48:08 -0700247 v := p.Apply(fieldOffset).AsValueOf(extensionFieldsType)
248 return (*extensionMap)(v.Interface().(*map[int32]ExtensionField))
249 }
250 } else {
251 mi.extensionMap = func(pointer) *extensionMap {
252 return (*extensionMap)(nil)
253 }
Joe Tsaibe5348c2018-10-23 18:31:18 -0700254 }
255}
256
Joe Tsai4fe96632019-05-22 05:12:36 -0400257func (mi *MessageInfo) MessageOf(p interface{}) pref.Message {
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700258 return (*messageReflectWrapper)(mi.dataTypeOf(p))
Joe Tsai08e00302018-11-26 22:32:06 -0800259}
260
Joe Tsai4fe96632019-05-22 05:12:36 -0400261func (mi *MessageInfo) Methods() *piface.Methods {
Damien Neilc37adef2019-04-01 13:49:56 -0700262 mi.init()
263 return &mi.methods
Damien Neil0d3e8cc2019-04-01 13:31:55 -0700264}
265
Joe Tsai4fe96632019-05-22 05:12:36 -0400266func (mi *MessageInfo) dataTypeOf(p interface{}) *messageDataType {
Damien Neil8012b442019-01-18 09:32:24 -0800267 // TODO: Remove this check? This API is primarily used by generated code,
268 // and should not violate this assumption. Leave this check in for now to
269 // provide some sanity checks during development. This can be removed if
270 // it proves to be detrimental to performance.
271 if reflect.TypeOf(p) != mi.GoType {
272 panic(fmt.Sprintf("type mismatch: got %T, want %v", p, mi.GoType))
273 }
Joe Tsai6cf80c42018-12-01 04:57:09 -0800274 return &messageDataType{pointerOfIface(p), mi}
Joe Tsaic6b75612018-09-13 14:24:37 -0700275}
276
277// messageDataType is a tuple of a pointer to the message data and
278// a pointer to the message type.
279//
Joe Tsai4fe96632019-05-22 05:12:36 -0400280// TODO: Unfortunately, we need to close over a pointer and MessageInfo,
Joe Tsaic6b75612018-09-13 14:24:37 -0700281// which incurs an an allocation. This pair is similar to a Go interface,
282// which is essentially a tuple of the same thing. We can make this efficient
283// with reflect.NamedOf (see https://golang.org/issues/16522).
284//
285// With that hypothetical API, we could dynamically create a new named type
Joe Tsai4fe96632019-05-22 05:12:36 -0400286// that has the same underlying type as MessageInfo.GoType, and
287// dynamically create methods that close over MessageInfo.
Joe Tsaic6b75612018-09-13 14:24:37 -0700288// Since the new type would have the same underlying type, we could directly
289// convert between pointers of those types, giving us an efficient way to swap
290// out the method set.
291//
292// Barring the ability to dynamically create named types, the workaround is
293// 1. either to accept the cost of an allocation for this wrapper struct or
294// 2. generate more types and methods, at the expense of binary size increase.
295type messageDataType struct {
296 p pointer
Joe Tsai4fe96632019-05-22 05:12:36 -0400297 mi *MessageInfo
Joe Tsaic6b75612018-09-13 14:24:37 -0700298}
299
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700300type messageReflectWrapper messageDataType
Joe Tsai08e00302018-11-26 22:32:06 -0800301
Joe Tsai0fc49f82019-05-01 12:29:25 -0700302func (m *messageReflectWrapper) Descriptor() pref.MessageDescriptor {
303 return m.mi.PBType.Descriptor()
304}
Joe Tsai0fc49f82019-05-01 12:29:25 -0700305func (m *messageReflectWrapper) New() pref.Message {
306 return m.mi.PBType.New()
307}
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700308func (m *messageReflectWrapper) Interface() pref.ProtoMessage {
Joe Tsai08e00302018-11-26 22:32:06 -0800309 if m, ok := m.ProtoUnwrap().(pref.ProtoMessage); ok {
310 return m
311 }
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700312 return (*messageIfaceWrapper)(m)
Joe Tsai08e00302018-11-26 22:32:06 -0800313}
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700314func (m *messageReflectWrapper) ProtoUnwrap() interface{} {
Damien Neil8012b442019-01-18 09:32:24 -0800315 return m.p.AsIfaceOf(m.mi.GoType.Elem())
Joe Tsai08e00302018-11-26 22:32:06 -0800316}
Joe Tsai08e00302018-11-26 22:32:06 -0800317
Joe Tsai378c1322019-04-25 23:48:08 -0700318func (m *messageReflectWrapper) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
319 m.mi.init()
320 for _, fi := range m.mi.fields {
321 if fi.has(m.p) {
322 if !f(fi.fieldDesc, fi.get(m.p)) {
323 return
324 }
325 }
326 }
327 m.mi.extensionMap(m.p).Range(f)
328}
329func (m *messageReflectWrapper) Has(fd pref.FieldDescriptor) bool {
330 if fi, xt := m.checkField(fd); fi != nil {
331 return fi.has(m.p)
332 } else {
333 return m.mi.extensionMap(m.p).Has(xt)
334 }
335}
336func (m *messageReflectWrapper) Clear(fd pref.FieldDescriptor) {
337 if fi, xt := m.checkField(fd); fi != nil {
338 fi.clear(m.p)
339 } else {
340 m.mi.extensionMap(m.p).Clear(xt)
341 }
342}
343func (m *messageReflectWrapper) Get(fd pref.FieldDescriptor) pref.Value {
344 if fi, xt := m.checkField(fd); fi != nil {
345 return fi.get(m.p)
346 } else {
347 return m.mi.extensionMap(m.p).Get(xt)
348 }
349}
350func (m *messageReflectWrapper) Set(fd pref.FieldDescriptor, v pref.Value) {
351 if fi, xt := m.checkField(fd); fi != nil {
352 fi.set(m.p, v)
353 } else {
354 m.mi.extensionMap(m.p).Set(xt, v)
355 }
356}
357func (m *messageReflectWrapper) Mutable(fd pref.FieldDescriptor) pref.Value {
358 if fi, xt := m.checkField(fd); fi != nil {
359 return fi.mutable(m.p)
360 } else {
361 return m.mi.extensionMap(m.p).Mutable(xt)
362 }
363}
364func (m *messageReflectWrapper) NewMessage(fd pref.FieldDescriptor) pref.Message {
365 if fi, xt := m.checkField(fd); fi != nil {
366 return fi.newMessage()
367 } else {
368 return xt.New().Message()
369 }
370}
371func (m *messageReflectWrapper) WhichOneof(od pref.OneofDescriptor) pref.FieldDescriptor {
372 m.mi.init()
373 if oi := m.mi.oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
374 return od.Fields().ByNumber(oi.which(m.p))
375 }
376 panic("invalid oneof descriptor")
377}
378func (m *messageReflectWrapper) GetUnknown() pref.RawFields {
379 m.mi.init()
380 return m.mi.getUnknown(m.p)
381}
382func (m *messageReflectWrapper) SetUnknown(b pref.RawFields) {
383 m.mi.init()
384 m.mi.setUnknown(m.p, b)
385}
386
387// checkField verifies that the provided field descriptor is valid.
388// Exactly one of the returned values is populated.
389func (m *messageReflectWrapper) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.ExtensionType) {
390 m.mi.init()
391 if fi := m.mi.fields[fd.Number()]; fi != nil {
392 if fi.fieldDesc != fd {
393 panic("mismatching field descriptor")
394 }
395 return fi, nil
396 }
397 if fd.IsExtension() {
398 if fd.ContainingMessage().FullName() != m.mi.PBType.FullName() {
399 // TODO: Should this be exact containing message descriptor match?
400 panic("mismatching containing message")
401 }
402 if !m.mi.PBType.ExtensionRanges().Has(fd.Number()) {
403 panic("invalid extension field")
404 }
405 return nil, fd.(pref.ExtensionType)
406 }
407 panic("invalid field descriptor")
408}
409
410type extensionMap map[int32]ExtensionField
411
Joe Tsai378c1322019-04-25 23:48:08 -0700412func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
413 if m != nil {
414 for _, x := range *m {
415 xt := x.GetType()
416 if !f(xt, xt.ValueOf(x.GetValue())) {
417 return
418 }
419 }
420 }
421}
422func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) {
423 if m != nil {
424 _, ok = (*m)[int32(xt.Number())]
425 }
426 return ok
427}
428func (m *extensionMap) Clear(xt pref.ExtensionType) {
429 delete(*m, int32(xt.Number()))
430}
431func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value {
432 if m != nil {
433 if x, ok := (*m)[int32(xt.Number())]; ok {
434 return xt.ValueOf(x.GetValue())
435 }
436 }
437 if !isComposite(xt) {
438 return defaultValueOf(xt)
439 }
440 return frozenValueOf(xt.New())
441}
442func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) {
443 if *m == nil {
444 *m = make(map[int32]ExtensionField)
445 }
446 var x ExtensionField
447 x.SetType(xt)
448 x.SetEagerValue(xt.InterfaceOf(v))
449 (*m)[int32(xt.Number())] = x
450}
451func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
452 if !isComposite(xt) {
453 panic("invalid Mutable on field with non-composite type")
454 }
455 if x, ok := (*m)[int32(xt.Number())]; ok {
456 return xt.ValueOf(x.GetValue())
457 }
458 v := xt.New()
459 m.Set(xt, v)
460 return v
461}
462
463func isComposite(fd pref.FieldDescriptor) bool {
464 return fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind || fd.IsList() || fd.IsMap()
465}
466
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700467var _ pvalue.Unwrapper = (*messageReflectWrapper)(nil)
468
469type messageIfaceWrapper messageDataType
470
471func (m *messageIfaceWrapper) ProtoReflect() pref.Message {
472 return (*messageReflectWrapper)(m)
473}
Damien Neil0d3e8cc2019-04-01 13:31:55 -0700474func (m *messageIfaceWrapper) XXX_Methods() *piface.Methods {
Damien Neilc37adef2019-04-01 13:49:56 -0700475 // TODO: Consider not recreating this on every call.
476 m.mi.init()
477 return &piface.Methods{
478 Flags: piface.MethodFlagDeterministicMarshal,
479 MarshalAppend: m.marshalAppend,
480 Size: m.size,
481 }
Damien Neil0d3e8cc2019-04-01 13:31:55 -0700482}
Joe Tsai22b1ebd2019-03-11 13:45:14 -0700483func (m *messageIfaceWrapper) ProtoUnwrap() interface{} {
484 return m.p.AsIfaceOf(m.mi.GoType.Elem())
485}
Damien Neilc37adef2019-04-01 13:49:56 -0700486func (m *messageIfaceWrapper) marshalAppend(b []byte, _ pref.ProtoMessage, opts piface.MarshalOptions) ([]byte, error) {
487 return m.mi.marshalAppendPointer(b, m.p, newMarshalOptions(opts))
488}
489func (m *messageIfaceWrapper) size(msg pref.ProtoMessage) (size int) {
490 return m.mi.sizePointer(m.p, 0)
491}