blob: aac55ee8d803a0a989d51b57dbab4b51afff2053 [file] [log] [blame]
kesavand2cde6582020-06-22 04:56:23 -04001// Copyright 2019 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 (
8 "fmt"
9 "reflect"
10
11 "google.golang.org/protobuf/internal/pragma"
12 pref "google.golang.org/protobuf/reflect/protoreflect"
13)
14
15type reflectMessageInfo struct {
16 fields map[pref.FieldNumber]*fieldInfo
17 oneofs map[pref.Name]*oneofInfo
18
19 // denseFields is a subset of fields where:
20 // 0 < fieldDesc.Number() < len(denseFields)
21 // It provides faster access to the fieldInfo, but may be incomplete.
22 denseFields []*fieldInfo
23
24 // rangeInfos is a list of all fields (not belonging to a oneof) and oneofs.
25 rangeInfos []interface{} // either *fieldInfo or *oneofInfo
26
27 getUnknown func(pointer) pref.RawFields
28 setUnknown func(pointer, pref.RawFields)
29 extensionMap func(pointer) *extensionMap
30
31 nilMessage atomicNilMessage
32}
33
34// makeReflectFuncs generates the set of functions to support reflection.
35func (mi *MessageInfo) makeReflectFuncs(t reflect.Type, si structInfo) {
36 mi.makeKnownFieldsFunc(si)
37 mi.makeUnknownFieldsFunc(t, si)
38 mi.makeExtensionFieldsFunc(t, si)
39}
40
41// makeKnownFieldsFunc generates functions for operations that can be performed
42// on each protobuf message field. It takes in a reflect.Type representing the
43// Go struct and matches message fields with struct fields.
44//
45// This code assumes that the struct is well-formed and panics if there are
46// any discrepancies.
47func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
48 mi.fields = map[pref.FieldNumber]*fieldInfo{}
49 md := mi.Desc
50 fds := md.Fields()
51 for i := 0; i < fds.Len(); i++ {
52 fd := fds.Get(i)
53 fs := si.fieldsByNumber[fd.Number()]
54 var fi fieldInfo
55 switch {
56 case fd.ContainingOneof() != nil:
57 fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
58 case fd.IsMap():
59 fi = fieldInfoForMap(fd, fs, mi.Exporter)
60 case fd.IsList():
61 fi = fieldInfoForList(fd, fs, mi.Exporter)
62 case fd.IsWeak():
63 fi = fieldInfoForWeakMessage(fd, si.weakOffset)
64 case fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind:
65 fi = fieldInfoForMessage(fd, fs, mi.Exporter)
66 default:
67 fi = fieldInfoForScalar(fd, fs, mi.Exporter)
68 }
69 mi.fields[fd.Number()] = &fi
70 }
71
72 mi.oneofs = map[pref.Name]*oneofInfo{}
73 for i := 0; i < md.Oneofs().Len(); i++ {
74 od := md.Oneofs().Get(i)
75 mi.oneofs[od.Name()] = makeOneofInfo(od, si.oneofsByName[od.Name()], mi.Exporter, si.oneofWrappersByType)
76 }
77
78 mi.denseFields = make([]*fieldInfo, fds.Len()*2)
79 for i := 0; i < fds.Len(); i++ {
80 if fd := fds.Get(i); int(fd.Number()) < len(mi.denseFields) {
81 mi.denseFields[fd.Number()] = mi.fields[fd.Number()]
82 }
83 }
84
85 for i := 0; i < fds.Len(); {
86 fd := fds.Get(i)
87 if od := fd.ContainingOneof(); od != nil {
88 mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()])
89 i += od.Fields().Len()
90 } else {
91 mi.rangeInfos = append(mi.rangeInfos, mi.fields[fd.Number()])
92 i++
93 }
94 }
95}
96
97func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) {
98 mi.getUnknown = func(pointer) pref.RawFields { return nil }
99 mi.setUnknown = func(pointer, pref.RawFields) { return }
100 if si.unknownOffset.IsValid() {
101 mi.getUnknown = func(p pointer) pref.RawFields {
102 if p.IsNil() {
103 return nil
104 }
105 rv := p.Apply(si.unknownOffset).AsValueOf(unknownFieldsType)
106 return pref.RawFields(*rv.Interface().(*[]byte))
107 }
108 mi.setUnknown = func(p pointer, b pref.RawFields) {
109 if p.IsNil() {
110 panic("invalid SetUnknown on nil Message")
111 }
112 rv := p.Apply(si.unknownOffset).AsValueOf(unknownFieldsType)
113 *rv.Interface().(*[]byte) = []byte(b)
114 }
115 } else {
116 mi.getUnknown = func(pointer) pref.RawFields {
117 return nil
118 }
119 mi.setUnknown = func(p pointer, _ pref.RawFields) {
120 if p.IsNil() {
121 panic("invalid SetUnknown on nil Message")
122 }
123 }
124 }
125}
126
127func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type, si structInfo) {
128 if si.extensionOffset.IsValid() {
129 mi.extensionMap = func(p pointer) *extensionMap {
130 if p.IsNil() {
131 return (*extensionMap)(nil)
132 }
133 v := p.Apply(si.extensionOffset).AsValueOf(extensionFieldsType)
134 return (*extensionMap)(v.Interface().(*map[int32]ExtensionField))
135 }
136 } else {
137 mi.extensionMap = func(pointer) *extensionMap {
138 return (*extensionMap)(nil)
139 }
140 }
141}
142
143type extensionMap map[int32]ExtensionField
144
145func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
146 if m != nil {
147 for _, x := range *m {
148 xd := x.Type().TypeDescriptor()
149 v := x.Value()
150 if xd.IsList() && v.List().Len() == 0 {
151 continue
152 }
153 if !f(xd, v) {
154 return
155 }
156 }
157 }
158}
159func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) {
160 if m == nil {
161 return false
162 }
163 xd := xt.TypeDescriptor()
164 x, ok := (*m)[int32(xd.Number())]
165 if !ok {
166 return false
167 }
168 switch {
169 case xd.IsList():
170 return x.Value().List().Len() > 0
171 case xd.IsMap():
172 return x.Value().Map().Len() > 0
173 }
174 return true
175}
176func (m *extensionMap) Clear(xt pref.ExtensionType) {
177 delete(*m, int32(xt.TypeDescriptor().Number()))
178}
179func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value {
180 xd := xt.TypeDescriptor()
181 if m != nil {
182 if x, ok := (*m)[int32(xd.Number())]; ok {
183 return x.Value()
184 }
185 }
186 return xt.Zero()
187}
188func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) {
189 if !xt.IsValidValue(v) {
190 panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName()))
191 }
192 if *m == nil {
193 *m = make(map[int32]ExtensionField)
194 }
195 var x ExtensionField
196 x.Set(xt, v)
197 (*m)[int32(xt.TypeDescriptor().Number())] = x
198}
199func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
200 xd := xt.TypeDescriptor()
201 if xd.Kind() != pref.MessageKind && xd.Kind() != pref.GroupKind && !xd.IsList() && !xd.IsMap() {
202 panic("invalid Mutable on field with non-composite type")
203 }
204 if x, ok := (*m)[int32(xd.Number())]; ok {
205 return x.Value()
206 }
207 v := xt.New()
208 m.Set(xt, v)
209 return v
210}
211
212// MessageState is a data structure that is nested as the first field in a
213// concrete message. It provides a way to implement the ProtoReflect method
214// in an allocation-free way without needing to have a shadow Go type generated
215// for every message type. This technique only works using unsafe.
216//
217//
218// Example generated code:
219//
220// type M struct {
221// state protoimpl.MessageState
222//
223// Field1 int32
224// Field2 string
225// Field3 *BarMessage
226// ...
227// }
228//
229// func (m *M) ProtoReflect() protoreflect.Message {
230// mi := &file_fizz_buzz_proto_msgInfos[5]
231// if protoimpl.UnsafeEnabled && m != nil {
232// ms := protoimpl.X.MessageStateOf(Pointer(m))
233// if ms.LoadMessageInfo() == nil {
234// ms.StoreMessageInfo(mi)
235// }
236// return ms
237// }
238// return mi.MessageOf(m)
239// }
240//
241// The MessageState type holds a *MessageInfo, which must be atomically set to
242// the message info associated with a given message instance.
243// By unsafely converting a *M into a *MessageState, the MessageState object
244// has access to all the information needed to implement protobuf reflection.
245// It has access to the message info as its first field, and a pointer to the
246// MessageState is identical to a pointer to the concrete message value.
247//
248//
249// Requirements:
250// • The type M must implement protoreflect.ProtoMessage.
251// • The address of m must not be nil.
252// • The address of m and the address of m.state must be equal,
253// even though they are different Go types.
254type MessageState struct {
255 pragma.NoUnkeyedLiterals
256 pragma.DoNotCompare
257 pragma.DoNotCopy
258
259 atomicMessageInfo *MessageInfo
260}
261
262type messageState MessageState
263
264var (
265 _ pref.Message = (*messageState)(nil)
266 _ unwrapper = (*messageState)(nil)
267)
268
269// messageDataType is a tuple of a pointer to the message data and
270// a pointer to the message type. It is a generalized way of providing a
271// reflective view over a message instance. The disadvantage of this approach
272// is the need to allocate this tuple of 16B.
273type messageDataType struct {
274 p pointer
275 mi *MessageInfo
276}
277
278type (
279 messageReflectWrapper messageDataType
280 messageIfaceWrapper messageDataType
281)
282
283var (
284 _ pref.Message = (*messageReflectWrapper)(nil)
285 _ unwrapper = (*messageReflectWrapper)(nil)
286 _ pref.ProtoMessage = (*messageIfaceWrapper)(nil)
287 _ unwrapper = (*messageIfaceWrapper)(nil)
288)
289
290// MessageOf returns a reflective view over a message. The input must be a
291// pointer to a named Go struct. If the provided type has a ProtoReflect method,
292// it must be implemented by calling this method.
293func (mi *MessageInfo) MessageOf(m interface{}) pref.Message {
294 // TODO: Switch the input to be an opaque Pointer.
295 if reflect.TypeOf(m) != mi.GoReflectType {
296 panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType))
297 }
298 p := pointerOfIface(m)
299 if p.IsNil() {
300 return mi.nilMessage.Init(mi)
301 }
302 return &messageReflectWrapper{p, mi}
303}
304
305func (m *messageReflectWrapper) pointer() pointer { return m.p }
306func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi }
307
308func (m *messageIfaceWrapper) ProtoReflect() pref.Message {
309 return (*messageReflectWrapper)(m)
310}
311func (m *messageIfaceWrapper) protoUnwrap() interface{} {
312 return m.p.AsIfaceOf(m.mi.GoReflectType.Elem())
313}
314
315// checkField verifies that the provided field descriptor is valid.
316// Exactly one of the returned values is populated.
317func (mi *MessageInfo) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.ExtensionType) {
318 var fi *fieldInfo
319 if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) {
320 fi = mi.denseFields[n]
321 } else {
322 fi = mi.fields[n]
323 }
324 if fi != nil {
325 if fi.fieldDesc != fd {
326 panic("mismatching field descriptor")
327 }
328 return fi, nil
329 }
330
331 if fd.IsExtension() {
332 if fd.ContainingMessage().FullName() != mi.Desc.FullName() {
333 // TODO: Should this be exact containing message descriptor match?
334 panic("mismatching containing message")
335 }
336 if !mi.Desc.ExtensionRanges().Has(fd.Number()) {
337 panic("invalid extension field")
338 }
339 xtd, ok := fd.(pref.ExtensionTypeDescriptor)
340 if !ok {
341 panic("extension descriptor does not implement ExtensionTypeDescriptor")
342 }
343 return nil, xtd.Type()
344 }
345 panic("invalid field descriptor")
346}