message_reflect.go

  1// 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/detrand"
 12	"google.golang.org/protobuf/internal/pragma"
 13	"google.golang.org/protobuf/reflect/protoreflect"
 14)
 15
 16type reflectMessageInfo struct {
 17	fields map[protoreflect.FieldNumber]*fieldInfo
 18	oneofs map[protoreflect.Name]*oneofInfo
 19
 20	// fieldTypes contains the zero value of an enum or message field.
 21	// For lists, it contains the element type.
 22	// For maps, it contains the entry value type.
 23	fieldTypes map[protoreflect.FieldNumber]any
 24
 25	// denseFields is a subset of fields where:
 26	//	0 < fieldDesc.Number() < len(denseFields)
 27	// It provides faster access to the fieldInfo, but may be incomplete.
 28	denseFields []*fieldInfo
 29
 30	// rangeInfos is a list of all fields (not belonging to a oneof) and oneofs.
 31	rangeInfos []any // either *fieldInfo or *oneofInfo
 32
 33	getUnknown   func(pointer) protoreflect.RawFields
 34	setUnknown   func(pointer, protoreflect.RawFields)
 35	extensionMap func(pointer) *extensionMap
 36
 37	nilMessage atomicNilMessage
 38}
 39
 40// makeReflectFuncs generates the set of functions to support reflection.
 41func (mi *MessageInfo) makeReflectFuncs(t reflect.Type, si structInfo) {
 42	mi.makeKnownFieldsFunc(si)
 43	mi.makeUnknownFieldsFunc(t, si)
 44	mi.makeExtensionFieldsFunc(t, si)
 45	mi.makeFieldTypes(si)
 46}
 47
 48// makeKnownFieldsFunc generates functions for operations that can be performed
 49// on each protobuf message field. It takes in a reflect.Type representing the
 50// Go struct and matches message fields with struct fields.
 51//
 52// This code assumes that the struct is well-formed and panics if there are
 53// any discrepancies.
 54func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
 55	mi.fields = map[protoreflect.FieldNumber]*fieldInfo{}
 56	md := mi.Desc
 57	fds := md.Fields()
 58	for i := 0; i < fds.Len(); i++ {
 59		fd := fds.Get(i)
 60		fs := si.fieldsByNumber[fd.Number()]
 61		isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
 62		if isOneof {
 63			fs = si.oneofsByName[fd.ContainingOneof().Name()]
 64		}
 65		var fi fieldInfo
 66		switch {
 67		case fs.Type == nil:
 68			fi = fieldInfoForMissing(fd) // never occurs for officially generated message types
 69		case isOneof:
 70			fi = fieldInfoForOneof(fd, fs, mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
 71		case fd.IsMap():
 72			fi = fieldInfoForMap(fd, fs, mi.Exporter)
 73		case fd.IsList():
 74			fi = fieldInfoForList(fd, fs, mi.Exporter)
 75		case fd.Message() != nil:
 76			fi = fieldInfoForMessage(fd, fs, mi.Exporter)
 77		default:
 78			fi = fieldInfoForScalar(fd, fs, mi.Exporter)
 79		}
 80		mi.fields[fd.Number()] = &fi
 81	}
 82
 83	mi.oneofs = map[protoreflect.Name]*oneofInfo{}
 84	for i := 0; i < md.Oneofs().Len(); i++ {
 85		od := md.Oneofs().Get(i)
 86		mi.oneofs[od.Name()] = makeOneofInfo(od, si, mi.Exporter)
 87	}
 88
 89	mi.denseFields = make([]*fieldInfo, fds.Len()*2)
 90	for i := 0; i < fds.Len(); i++ {
 91		if fd := fds.Get(i); int(fd.Number()) < len(mi.denseFields) {
 92			mi.denseFields[fd.Number()] = mi.fields[fd.Number()]
 93		}
 94	}
 95
 96	for i := 0; i < fds.Len(); {
 97		fd := fds.Get(i)
 98		if od := fd.ContainingOneof(); od != nil && !od.IsSynthetic() {
 99			mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()])
100			i += od.Fields().Len()
101		} else {
102			mi.rangeInfos = append(mi.rangeInfos, mi.fields[fd.Number()])
103			i++
104		}
105	}
106
107	// Introduce instability to iteration order, but keep it deterministic.
108	if len(mi.rangeInfos) > 1 && detrand.Bool() {
109		i := detrand.Intn(len(mi.rangeInfos) - 1)
110		mi.rangeInfos[i], mi.rangeInfos[i+1] = mi.rangeInfos[i+1], mi.rangeInfos[i]
111	}
112}
113
114func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) {
115	switch {
116	case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsAType:
117		// Handle as []byte.
118		mi.getUnknown = func(p pointer) protoreflect.RawFields {
119			if p.IsNil() {
120				return nil
121			}
122			return *p.Apply(mi.unknownOffset).Bytes()
123		}
124		mi.setUnknown = func(p pointer, b protoreflect.RawFields) {
125			if p.IsNil() {
126				panic("invalid SetUnknown on nil Message")
127			}
128			*p.Apply(mi.unknownOffset).Bytes() = b
129		}
130	case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsBType:
131		// Handle as *[]byte.
132		mi.getUnknown = func(p pointer) protoreflect.RawFields {
133			if p.IsNil() {
134				return nil
135			}
136			bp := p.Apply(mi.unknownOffset).BytesPtr()
137			if *bp == nil {
138				return nil
139			}
140			return **bp
141		}
142		mi.setUnknown = func(p pointer, b protoreflect.RawFields) {
143			if p.IsNil() {
144				panic("invalid SetUnknown on nil Message")
145			}
146			bp := p.Apply(mi.unknownOffset).BytesPtr()
147			if *bp == nil {
148				*bp = new([]byte)
149			}
150			**bp = b
151		}
152	default:
153		mi.getUnknown = func(pointer) protoreflect.RawFields {
154			return nil
155		}
156		mi.setUnknown = func(p pointer, _ protoreflect.RawFields) {
157			if p.IsNil() {
158				panic("invalid SetUnknown on nil Message")
159			}
160		}
161	}
162}
163
164func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type, si structInfo) {
165	if si.extensionOffset.IsValid() {
166		mi.extensionMap = func(p pointer) *extensionMap {
167			if p.IsNil() {
168				return (*extensionMap)(nil)
169			}
170			v := p.Apply(si.extensionOffset).AsValueOf(extensionFieldsType)
171			return (*extensionMap)(v.Interface().(*map[int32]ExtensionField))
172		}
173	} else {
174		mi.extensionMap = func(pointer) *extensionMap {
175			return (*extensionMap)(nil)
176		}
177	}
178}
179func (mi *MessageInfo) makeFieldTypes(si structInfo) {
180	md := mi.Desc
181	fds := md.Fields()
182	for i := 0; i < fds.Len(); i++ {
183		var ft reflect.Type
184		fd := fds.Get(i)
185		fs := si.fieldsByNumber[fd.Number()]
186		isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
187		if isOneof {
188			fs = si.oneofsByName[fd.ContainingOneof().Name()]
189		}
190		var isMessage bool
191		switch {
192		case fs.Type == nil:
193			continue // never occurs for officially generated message types
194		case isOneof:
195			if fd.Enum() != nil || fd.Message() != nil {
196				ft = si.oneofWrappersByNumber[fd.Number()].Field(0).Type
197			}
198		case fd.IsMap():
199			if fd.MapValue().Enum() != nil || fd.MapValue().Message() != nil {
200				ft = fs.Type.Elem()
201			}
202			isMessage = fd.MapValue().Message() != nil
203		case fd.IsList():
204			if fd.Enum() != nil || fd.Message() != nil {
205				ft = fs.Type.Elem()
206
207				if ft.Kind() == reflect.Slice {
208					ft = ft.Elem()
209				}
210
211			}
212			isMessage = fd.Message() != nil
213		case fd.Enum() != nil:
214			ft = fs.Type
215			if fd.HasPresence() && ft.Kind() == reflect.Ptr {
216				ft = ft.Elem()
217			}
218		case fd.Message() != nil:
219			ft = fs.Type
220			isMessage = true
221		}
222		if isMessage && ft != nil && ft.Kind() != reflect.Ptr {
223			ft = reflect.PtrTo(ft) // never occurs for officially generated message types
224		}
225		if ft != nil {
226			if mi.fieldTypes == nil {
227				mi.fieldTypes = make(map[protoreflect.FieldNumber]any)
228			}
229			mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface()
230		}
231	}
232}
233
234type extensionMap map[int32]ExtensionField
235
236func (m *extensionMap) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
237	if m != nil {
238		for _, x := range *m {
239			xd := x.Type().TypeDescriptor()
240			v := x.Value()
241			if xd.IsList() && v.List().Len() == 0 {
242				continue
243			}
244			if !f(xd, v) {
245				return
246			}
247		}
248	}
249}
250func (m *extensionMap) Has(xd protoreflect.ExtensionTypeDescriptor) (ok bool) {
251	if m == nil {
252		return false
253	}
254	x, ok := (*m)[int32(xd.Number())]
255	if !ok {
256		return false
257	}
258	if x.isUnexpandedLazy() {
259		// Avoid calling x.Value(), which triggers a lazy unmarshal.
260		return true
261	}
262	switch {
263	case xd.IsList():
264		return x.Value().List().Len() > 0
265	case xd.IsMap():
266		return x.Value().Map().Len() > 0
267	}
268	return true
269}
270func (m *extensionMap) Clear(xd protoreflect.ExtensionTypeDescriptor) {
271	delete(*m, int32(xd.Number()))
272}
273func (m *extensionMap) Get(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
274	if m != nil {
275		if x, ok := (*m)[int32(xd.Number())]; ok {
276			return x.Value()
277		}
278	}
279	return xd.Type().Zero()
280}
281func (m *extensionMap) Set(xd protoreflect.ExtensionTypeDescriptor, v protoreflect.Value) {
282	xt := xd.Type()
283	isValid := true
284	switch {
285	case !xt.IsValidValue(v):
286		isValid = false
287	case xd.IsList():
288		isValid = v.List().IsValid()
289	case xd.IsMap():
290		isValid = v.Map().IsValid()
291	case xd.Message() != nil:
292		isValid = v.Message().IsValid()
293	}
294	if !isValid {
295		panic(fmt.Sprintf("%v: assigning invalid value", xd.FullName()))
296	}
297
298	if *m == nil {
299		*m = make(map[int32]ExtensionField)
300	}
301	var x ExtensionField
302	x.Set(xt, v)
303	(*m)[int32(xd.Number())] = x
304}
305func (m *extensionMap) Mutable(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
306	if xd.Kind() != protoreflect.MessageKind && xd.Kind() != protoreflect.GroupKind && !xd.IsList() && !xd.IsMap() {
307		panic("invalid Mutable on field with non-composite type")
308	}
309	if x, ok := (*m)[int32(xd.Number())]; ok {
310		return x.Value()
311	}
312	v := xd.Type().New()
313	m.Set(xd, v)
314	return v
315}
316
317// MessageState is a data structure that is nested as the first field in a
318// concrete message. It provides a way to implement the ProtoReflect method
319// in an allocation-free way without needing to have a shadow Go type generated
320// for every message type. This technique only works using unsafe.
321//
322// Example generated code:
323//
324//	type M struct {
325//		state protoimpl.MessageState
326//
327//		Field1 int32
328//		Field2 string
329//		Field3 *BarMessage
330//		...
331//	}
332//
333//	func (m *M) ProtoReflect() protoreflect.Message {
334//		mi := &file_fizz_buzz_proto_msgInfos[5]
335//		if protoimpl.UnsafeEnabled && m != nil {
336//			ms := protoimpl.X.MessageStateOf(Pointer(m))
337//			if ms.LoadMessageInfo() == nil {
338//				ms.StoreMessageInfo(mi)
339//			}
340//			return ms
341//		}
342//		return mi.MessageOf(m)
343//	}
344//
345// The MessageState type holds a *MessageInfo, which must be atomically set to
346// the message info associated with a given message instance.
347// By unsafely converting a *M into a *MessageState, the MessageState object
348// has access to all the information needed to implement protobuf reflection.
349// It has access to the message info as its first field, and a pointer to the
350// MessageState is identical to a pointer to the concrete message value.
351//
352// Requirements:
353//   - The type M must implement protoreflect.ProtoMessage.
354//   - The address of m must not be nil.
355//   - The address of m and the address of m.state must be equal,
356//     even though they are different Go types.
357type MessageState struct {
358	pragma.NoUnkeyedLiterals
359	pragma.DoNotCompare
360	pragma.DoNotCopy
361
362	atomicMessageInfo *MessageInfo
363}
364
365type messageState MessageState
366
367var (
368	_ protoreflect.Message = (*messageState)(nil)
369	_ unwrapper            = (*messageState)(nil)
370)
371
372// messageDataType is a tuple of a pointer to the message data and
373// a pointer to the message type. It is a generalized way of providing a
374// reflective view over a message instance. The disadvantage of this approach
375// is the need to allocate this tuple of 16B.
376type messageDataType struct {
377	p  pointer
378	mi *MessageInfo
379}
380
381type (
382	messageReflectWrapper messageDataType
383	messageIfaceWrapper   messageDataType
384)
385
386var (
387	_ protoreflect.Message      = (*messageReflectWrapper)(nil)
388	_ unwrapper                 = (*messageReflectWrapper)(nil)
389	_ protoreflect.ProtoMessage = (*messageIfaceWrapper)(nil)
390	_ unwrapper                 = (*messageIfaceWrapper)(nil)
391)
392
393// MessageOf returns a reflective view over a message. The input must be a
394// pointer to a named Go struct. If the provided type has a ProtoReflect method,
395// it must be implemented by calling this method.
396func (mi *MessageInfo) MessageOf(m any) protoreflect.Message {
397	if reflect.TypeOf(m) != mi.GoReflectType {
398		panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType))
399	}
400	p := pointerOfIface(m)
401	if p.IsNil() {
402		return mi.nilMessage.Init(mi)
403	}
404	return &messageReflectWrapper{p, mi}
405}
406
407func (m *messageReflectWrapper) pointer() pointer          { return m.p }
408func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi }
409
410// Reset implements the v1 proto.Message.Reset method.
411func (m *messageIfaceWrapper) Reset() {
412	if mr, ok := m.protoUnwrap().(interface{ Reset() }); ok {
413		mr.Reset()
414		return
415	}
416	rv := reflect.ValueOf(m.protoUnwrap())
417	if rv.Kind() == reflect.Ptr && !rv.IsNil() {
418		rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
419	}
420}
421func (m *messageIfaceWrapper) ProtoReflect() protoreflect.Message {
422	return (*messageReflectWrapper)(m)
423}
424func (m *messageIfaceWrapper) protoUnwrap() any {
425	return m.p.AsIfaceOf(m.mi.GoReflectType.Elem())
426}
427
428// checkField verifies that the provided field descriptor is valid.
429// Exactly one of the returned values is populated.
430func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionTypeDescriptor) {
431	var fi *fieldInfo
432	if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) {
433		fi = mi.denseFields[n]
434	} else {
435		fi = mi.fields[n]
436	}
437	if fi != nil {
438		if fi.fieldDesc != fd {
439			if got, want := fd.FullName(), fi.fieldDesc.FullName(); got != want {
440				panic(fmt.Sprintf("mismatching field: got %v, want %v", got, want))
441			}
442			panic(fmt.Sprintf("mismatching field: %v", fd.FullName()))
443		}
444		return fi, nil
445	}
446
447	if fd.IsExtension() {
448		if got, want := fd.ContainingMessage().FullName(), mi.Desc.FullName(); got != want {
449			// TODO: Should this be exact containing message descriptor match?
450			panic(fmt.Sprintf("extension %v has mismatching containing message: got %v, want %v", fd.FullName(), got, want))
451		}
452		if !mi.Desc.ExtensionRanges().Has(fd.Number()) {
453			panic(fmt.Sprintf("extension %v extends %v outside the extension range", fd.FullName(), mi.Desc.FullName()))
454		}
455		xtd, ok := fd.(protoreflect.ExtensionTypeDescriptor)
456		if !ok {
457			panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
458		}
459		return nil, xtd
460	}
461	panic(fmt.Sprintf("field %v is invalid", fd.FullName()))
462}