// 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 proto

import (
	
	
	
	
)

// Size returns the size in bytes of the wire-format encoding of m.
func ( Message) int {
	return MarshalOptions{}.Size()
}

// Size returns the size in bytes of the wire-format encoding of m.
func ( MarshalOptions) ( Message) int {
	// Treat a nil message interface as an empty message; nothing to output.
	if  == nil {
		return 0
	}

	return .size(.ProtoReflect())
}

// size is a centralized function that all size operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for size that do not go through this.
func ( MarshalOptions) ( protoreflect.Message) ( int) {
	 := protoMethods()
	if  != nil && .Size != nil {
		 := .Size(protoiface.SizeInput{
			Message: ,
		})
		return .Size
	}
	if  != nil && .Marshal != nil {
		// This is not efficient, but we don't have any choice.
		// This case is mainly used for legacy types with a Marshal method.
		,  := .Marshal(protoiface.MarshalInput{
			Message: ,
		})
		return len(.Buf)
	}
	return .sizeMessageSlow()
}

func ( MarshalOptions) ( protoreflect.Message) ( int) {
	if messageset.IsMessageSet(.Descriptor()) {
		return .sizeMessageSet()
	}
	.Range(func( protoreflect.FieldDescriptor,  protoreflect.Value) bool {
		 += .sizeField(, )
		return true
	})
	 += len(.GetUnknown())
	return 
}

func ( MarshalOptions) ( protoreflect.FieldDescriptor,  protoreflect.Value) ( int) {
	 := .Number()
	switch {
	case .IsList():
		return .sizeList(, , .List())
	case .IsMap():
		return .sizeMap(, , .Map())
	default:
		return protowire.SizeTag() + .sizeSingular(, .Kind(), )
	}
}

func ( MarshalOptions) ( protowire.Number,  protoreflect.FieldDescriptor,  protoreflect.List) ( int) {
	if .IsPacked() && .Len() > 0 {
		 := 0
		for ,  := 0, .Len();  < ; ++ {
			 += .sizeSingular(, .Kind(), .Get())
		}
		return protowire.SizeTag() + protowire.SizeBytes()
	}

	for ,  := 0, .Len();  < ; ++ {
		 += protowire.SizeTag() + .sizeSingular(, .Kind(), .Get())
	}
	return 
}

func ( MarshalOptions) ( protowire.Number,  protoreflect.FieldDescriptor,  protoreflect.Map) ( int) {
	.Range(func( protoreflect.MapKey,  protoreflect.Value) bool {
		 += protowire.SizeTag()
		 += protowire.SizeBytes(.sizeField(.MapKey(), .Value()) + .sizeField(.MapValue(), ))
		return true
	})
	return 
}