codec_message_opaque.go raw

   1  // Copyright 2024 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  	"sort"
  11  
  12  	"google.golang.org/protobuf/encoding/protowire"
  13  	"google.golang.org/protobuf/internal/encoding/messageset"
  14  	"google.golang.org/protobuf/internal/filedesc"
  15  	"google.golang.org/protobuf/internal/order"
  16  	"google.golang.org/protobuf/reflect/protoreflect"
  17  	piface "google.golang.org/protobuf/runtime/protoiface"
  18  )
  19  
  20  func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInfo) {
  21  	mi.sizecacheOffset = si.sizecacheOffset
  22  	mi.unknownOffset = si.unknownOffset
  23  	mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr
  24  	mi.extensionOffset = si.extensionOffset
  25  	mi.lazyOffset = si.lazyOffset
  26  	mi.presenceOffset = si.presenceOffset
  27  
  28  	mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
  29  	fields := mi.Desc.Fields()
  30  	for i := 0; i < fields.Len(); i++ {
  31  		fd := fields.Get(i)
  32  
  33  		fs := si.fieldsByNumber[fd.Number()]
  34  		if fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() {
  35  			fs = si.oneofsByName[fd.ContainingOneof().Name()]
  36  		}
  37  		ft := fs.Type
  38  		var wiretag uint64
  39  		if !fd.IsPacked() {
  40  			wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  41  		} else {
  42  			wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType)
  43  		}
  44  		var fieldOffset offset
  45  		var funcs pointerCoderFuncs
  46  		var childMessage *MessageInfo
  47  		switch {
  48  		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
  49  			fieldOffset = offsetOf(fs)
  50  		case fd.Message() != nil && !fd.IsMap():
  51  			fieldOffset = offsetOf(fs)
  52  			if fd.IsList() {
  53  				childMessage, funcs = makeOpaqueRepeatedMessageFieldCoder(fd, ft)
  54  			} else {
  55  				childMessage, funcs = makeOpaqueMessageFieldCoder(fd, ft)
  56  			}
  57  		default:
  58  			fieldOffset = offsetOf(fs)
  59  			childMessage, funcs = fieldCoder(fd, ft)
  60  		}
  61  		cf := &coderFieldInfo{
  62  			num:        fd.Number(),
  63  			offset:     fieldOffset,
  64  			wiretag:    wiretag,
  65  			ft:         ft,
  66  			tagsize:    protowire.SizeVarint(wiretag),
  67  			funcs:      funcs,
  68  			mi:         childMessage,
  69  			validation: newFieldValidationInfo(mi, si.structInfo, fd, ft),
  70  			isPointer: (fd.Cardinality() == protoreflect.Repeated ||
  71  				fd.Kind() == protoreflect.MessageKind ||
  72  				fd.Kind() == protoreflect.GroupKind),
  73  			isRequired:    fd.Cardinality() == protoreflect.Required,
  74  			presenceIndex: noPresence,
  75  		}
  76  
  77  		// TODO: Use presence for all fields.
  78  		//
  79  		// In some cases, such as maps, presence means only "might be set" rather
  80  		// than "is definitely set", but every field should have a presence bit to
  81  		// permit us to skip over definitely-unset fields at marshal time.
  82  
  83  		var hasPresence bool
  84  		hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
  85  
  86  		if hasPresence {
  87  			cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
  88  		}
  89  
  90  		mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
  91  		mi.coderFields[cf.num] = cf
  92  	}
  93  	for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ {
  94  		if od := oneofs.Get(i); !od.IsSynthetic() {
  95  			mi.initOneofFieldCoders(od, si.structInfo)
  96  		}
  97  	}
  98  	if messageset.IsMessageSet(mi.Desc) {
  99  		if !mi.extensionOffset.IsValid() {
 100  			panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName()))
 101  		}
 102  		if !mi.unknownOffset.IsValid() {
 103  			panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName()))
 104  		}
 105  		mi.isMessageSet = true
 106  	}
 107  	sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
 108  		return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
 109  	})
 110  
 111  	var maxDense protoreflect.FieldNumber
 112  	for _, cf := range mi.orderedCoderFields {
 113  		if cf.num >= 16 && cf.num >= 2*maxDense {
 114  			break
 115  		}
 116  		maxDense = cf.num
 117  	}
 118  	mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
 119  	for _, cf := range mi.orderedCoderFields {
 120  		if int(cf.num) > len(mi.denseCoderFields) {
 121  			break
 122  		}
 123  		mi.denseCoderFields[cf.num] = cf
 124  	}
 125  
 126  	// To preserve compatibility with historic wire output, marshal oneofs last.
 127  	if mi.Desc.Oneofs().Len() > 0 {
 128  		sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
 129  			fi := fields.ByNumber(mi.orderedCoderFields[i].num)
 130  			fj := fields.ByNumber(mi.orderedCoderFields[j].num)
 131  			return order.LegacyFieldOrder(fi, fj)
 132  		})
 133  	}
 134  
 135  	mi.needsInitCheck = needsInitCheck(mi.Desc)
 136  	if mi.methods.Marshal == nil && mi.methods.Size == nil {
 137  		mi.methods.Flags |= piface.SupportMarshalDeterministic
 138  		mi.methods.Marshal = mi.marshal
 139  		mi.methods.Size = mi.size
 140  	}
 141  	if mi.methods.Unmarshal == nil {
 142  		mi.methods.Flags |= piface.SupportUnmarshalDiscardUnknown
 143  		mi.methods.Unmarshal = mi.unmarshal
 144  	}
 145  	if mi.methods.CheckInitialized == nil {
 146  		mi.methods.CheckInitialized = mi.checkInitialized
 147  	}
 148  	if mi.methods.Merge == nil {
 149  		mi.methods.Merge = mi.merge
 150  	}
 151  	if mi.methods.Equal == nil {
 152  		mi.methods.Equal = equal
 153  	}
 154  }
 155