message_reflect.go raw

   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  
   5  package impl
   6  
   7  import (
   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  
  16  type 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.
  41  func (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.
  54  func (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  
 114  func (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  
 164  func (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  }
 179  func (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  
 234  type extensionMap map[int32]ExtensionField
 235  
 236  func (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  }
 250  func (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  }
 270  func (m *extensionMap) Clear(xd protoreflect.ExtensionTypeDescriptor) {
 271  	delete(*m, int32(xd.Number()))
 272  }
 273  func (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  }
 281  func (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  }
 305  func (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.
 357  type MessageState struct {
 358  	pragma.NoUnkeyedLiterals
 359  	pragma.DoNotCompare
 360  	pragma.DoNotCopy
 361  
 362  	atomicMessageInfo *MessageInfo
 363  }
 364  
 365  type messageState MessageState
 366  
 367  var (
 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.
 376  type messageDataType struct {
 377  	p  pointer
 378  	mi *MessageInfo
 379  }
 380  
 381  type (
 382  	messageReflectWrapper messageDataType
 383  	messageIfaceWrapper   messageDataType
 384  )
 385  
 386  var (
 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.
 396  func (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  
 407  func (m *messageReflectWrapper) pointer() pointer          { return m.p }
 408  func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi }
 409  
 410  // Reset implements the v1 proto.Message.Reset method.
 411  func (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  }
 421  func (m *messageIfaceWrapper) ProtoReflect() protoreflect.Message {
 422  	return (*messageReflectWrapper)(m)
 423  }
 424  func (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.
 430  func (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  }
 463