Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package impl

import (
	
	
	

	
	
	
	pref 
	piface 
)
coderMessageInfo contains per-message information used by the fast-path functions. This is a different type from MessageInfo to keep MessageInfo as general-purpose as possible.
type coderMessageInfo struct {
	methods piface.Methods

	orderedCoderFields []*coderFieldInfo
	denseCoderFields   []*coderFieldInfo
	coderFields        map[protowire.Number]*coderFieldInfo
	sizecacheOffset    offset
	unknownOffset      offset
	extensionOffset    offset
	needsInitCheck     bool
	isMessageSet       bool
	numRequiredFields  uint8
}

type coderFieldInfo struct {
	funcs      pointerCoderFuncs // fast-path per-field functions
	mi         *MessageInfo      // field's message
	ft         reflect.Type
	validation validationInfo   // information used by message validation
	num        pref.FieldNumber // field number
	offset     offset           // struct field offset
	wiretag    uint64           // field tag (number + wire type)
	tagsize    int              // size of the varint-encoded tag
	isPointer  bool             // true if IsNil may be called on the struct field
	isRequired bool             // true if field is required
}

func ( *MessageInfo) ( reflect.Type,  structInfo) {
	.sizecacheOffset = .sizecacheOffset
	.unknownOffset = .unknownOffset
	.extensionOffset = .extensionOffset

	.coderFields = make(map[protowire.Number]*coderFieldInfo)
	 := .Desc.Fields()
	 := make([]coderFieldInfo, .Len())
	for  := 0;  < .Len(); ++ {
		 := .Get()

		 := .fieldsByNumber[.Number()]
		 := .ContainingOneof() != nil && !.ContainingOneof().IsSynthetic()
		if  {
			 = .oneofsByName[.ContainingOneof().Name()]
		}
		 := .Type
		var  uint64
		if !.IsPacked() {
			 = protowire.EncodeTag(.Number(), wireTypes[.Kind()])
		} else {
			 = protowire.EncodeTag(.Number(), protowire.BytesType)
		}
		var  offset
		var  pointerCoderFuncs
		var  *MessageInfo
		switch {
		case :
			 = offsetOf(, .Exporter)
		case .IsWeak():
			 = .weakOffset
			 = makeWeakMessageFieldCoder()
		default:
			 = offsetOf(, .Exporter)
			,  = fieldCoder(, )
		}
		 := &[]
		* = coderFieldInfo{
			num:        .Number(),
			offset:     ,
			wiretag:    ,
			ft:         ,
			tagsize:    protowire.SizeVarint(),
			funcs:      ,
			mi:         ,
			validation: newFieldValidationInfo(, , , ),
			isPointer:  .Cardinality() == pref.Repeated || .HasPresence(),
			isRequired: .Cardinality() == pref.Required,
		}
		.orderedCoderFields = append(.orderedCoderFields, )
		.coderFields[.num] = 
	}
	for ,  := 0, .Desc.Oneofs();  < .Len(); ++ {
		if  := .Get(); !.IsSynthetic() {
			.initOneofFieldCoders(, )
		}
	}
	if messageset.IsMessageSet(.Desc) {
		if !.extensionOffset.IsValid() {
			panic(fmt.Sprintf("%v: MessageSet with no extensions field", .Desc.FullName()))
		}
		if !.unknownOffset.IsValid() {
			panic(fmt.Sprintf("%v: MessageSet with no unknown field", .Desc.FullName()))
		}
		.isMessageSet = true
	}
	sort.Slice(.orderedCoderFields, func(,  int) bool {
		return .orderedCoderFields[].num < .orderedCoderFields[].num
	})

	var  pref.FieldNumber
	for ,  := range .orderedCoderFields {
		if .num >= 16 && .num >= 2* {
			break
		}
		 = .num
	}
	.denseCoderFields = make([]*coderFieldInfo, +1)
	for ,  := range .orderedCoderFields {
		if int(.num) >= len(.denseCoderFields) {
			break
		}
		.denseCoderFields[.num] = 
	}
To preserve compatibility with historic wire output, marshal oneofs last.