// 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 (
	
	
	
	
	
	
)

// MarshalOptions configures the marshaler.
//
// Example usage:
//
//	b, err := MarshalOptions{Deterministic: true}.Marshal(m)
type MarshalOptions struct {
	pragma.NoUnkeyedLiterals

	// AllowPartial allows messages that have missing required fields to marshal
	// without returning an error. If AllowPartial is false (the default),
	// Marshal will return an error if there are any missing required fields.
	AllowPartial bool

	// Deterministic controls whether the same message will always be
	// serialized to the same bytes within the same binary.
	//
	// Setting this option guarantees that repeated serialization of
	// the same message will return the same bytes, and that different
	// processes of the same binary (which may be executing on different
	// machines) will serialize equal messages to the same bytes.
	// It has no effect on the resulting size of the encoded message compared
	// to a non-deterministic marshal.
	//
	// Note that the deterministic serialization is NOT canonical across
	// languages. It is not guaranteed to remain stable over time. It is
	// unstable across different builds with schema changes due to unknown
	// fields. Users who need canonical serialization (e.g., persistent
	// storage in a canonical form, fingerprinting, etc.) must define
	// their own canonicalization specification and implement their own
	// serializer rather than relying on this API.
	//
	// If deterministic serialization is requested, map entries will be
	// sorted by keys in lexographical order. This is an implementation
	// detail and subject to change.
	Deterministic bool

	// UseCachedSize indicates that the result of a previous Size call
	// may be reused.
	//
	// Setting this option asserts that:
	//
	// 1. Size has previously been called on this message with identical
	// options (except for UseCachedSize itself).
	//
	// 2. The message and all its submessages have not changed in any
	// way since the Size call.
	//
	// If either of these invariants is violated,
	// the results are undefined and may include panics or corrupted output.
	//
	// Implementations MAY take this option into account to provide
	// better performance, but there is no guarantee that they will do so.
	// There is absolutely no guarantee that Size followed by Marshal with
	// UseCachedSize set will perform equivalently to Marshal alone.
	UseCachedSize bool
}

// Marshal returns the wire-format encoding of m.
func ( Message) ([]byte, error) {
	// Treat nil message interface as an empty message; nothing to output.
	if  == nil {
		return nil, nil
	}

	,  := MarshalOptions{}.marshal(nil, .ProtoReflect())
	if len(.Buf) == 0 &&  == nil {
		.Buf = emptyBytesForMessage()
	}
	return .Buf, 
}

// Marshal returns the wire-format encoding of m.
func ( MarshalOptions) ( Message) ([]byte, error) {
	// Treat nil message interface as an empty message; nothing to output.
	if  == nil {
		return nil, nil
	}

	,  := .marshal(nil, .ProtoReflect())
	if len(.Buf) == 0 &&  == nil {
		.Buf = emptyBytesForMessage()
	}
	return .Buf, 
}

// emptyBytesForMessage returns a nil buffer if and only if m is invalid,
// otherwise it returns a non-nil empty buffer.
//
// This is to assist the edge-case where user-code does the following:
//
//	m1.OptionalBytes, _ = proto.Marshal(m2)
//
// where they expect the proto2 "optional_bytes" field to be populated
// if any only if m2 is a valid message.
func ( Message) []byte {
	if  == nil || !.ProtoReflect().IsValid() {
		return nil
	}
	return emptyBuf[:]
}

// MarshalAppend appends the wire-format encoding of m to b,
// returning the result.
func ( MarshalOptions) ( []byte,  Message) ([]byte, error) {
	// Treat nil message interface as an empty message; nothing to append.
	if  == nil {
		return , nil
	}

	,  := .marshal(, .ProtoReflect())
	return .Buf, 
}

// MarshalState returns the wire-format encoding of a message.
//
// This method permits fine-grained control over the marshaler.
// Most users should use Marshal instead.
func ( MarshalOptions) ( protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
	return .marshal(.Buf, .Message)
}

// marshal is a centralized function that all marshal operations go through.
// For profiling purposes, avoid changing the name of this function or
// introducing other code paths for marshal that do not go through this.
func ( MarshalOptions) ( []byte,  protoreflect.Message) ( protoiface.MarshalOutput,  error) {
	 := .AllowPartial
	.AllowPartial = true
	if  := protoMethods();  != nil && .Marshal != nil &&
		!(.Deterministic && .Flags&protoiface.SupportMarshalDeterministic == 0) {
		 := protoiface.MarshalInput{
			Message: ,
			Buf:     ,
		}
		if .Deterministic {
			.Flags |= protoiface.MarshalDeterministic
		}
		if .UseCachedSize {
			.Flags |= protoiface.MarshalUseCachedSize
		}
		if .Size != nil {
			 := .Size(protoiface.SizeInput{
				Message: ,
				Flags:   .Flags,
			})
			if cap() < len()+.Size {
				.Buf = make([]byte, len(), growcap(cap(), len()+.Size))
				copy(.Buf, )
			}
			.Flags |= protoiface.MarshalUseCachedSize
		}
		,  = .Marshal()
	} else {
		.Buf,  = .marshalMessageSlow(, )
	}
	if  != nil {
		return , 
	}
	if  {
		return , nil
	}
	return , checkInitialized()
}

func ( MarshalOptions) ( []byte,  protoreflect.Message) ([]byte, error) {
	,  := .marshal(, )
	return .Buf, 
}

// growcap scales up the capacity of a slice.
//
// Given a slice with a current capacity of oldcap and a desired
// capacity of wantcap, growcap returns a new capacity >= wantcap.
//
// The algorithm is mostly identical to the one used by append as of Go 1.14.
func (,  int) ( int) {
	if  > *2 {
		 = 
	} else if  < 1024 {
		// The Go 1.14 runtime takes this case when len(s) < 1024,
		// not when cap(s) < 1024. The difference doesn't seem
		// significant here.
		 =  * 2
	} else {
		 = 
		for 0 <  &&  <  {
			 +=  / 4
		}
		if  <= 0 {
			 = 
		}
	}
	return 
}

func ( MarshalOptions) ( []byte,  protoreflect.Message) ([]byte, error) {
	if messageset.IsMessageSet(.Descriptor()) {
		return .marshalMessageSet(, )
	}
	 := order.AnyFieldOrder
	if .Deterministic {
		// TODO: This should use a more natural ordering like NumberFieldOrder,
		// but doing so breaks golden tests that make invalid assumption about
		// output stability of this implementation.
		 = order.LegacyFieldOrder
	}
	var  error
	order.RangeFields(, , func( protoreflect.FieldDescriptor,  protoreflect.Value) bool {
		,  = .marshalField(, , )
		return  == nil
	})
	if  != nil {
		return , 
	}
	 = append(, .GetUnknown()...)
	return , nil
}

func ( MarshalOptions) ( []byte,  protoreflect.FieldDescriptor,  protoreflect.Value) ([]byte, error) {
	switch {
	case .IsList():
		return .marshalList(, , .List())
	case .IsMap():
		return .marshalMap(, , .Map())
	default:
		 = protowire.AppendTag(, .Number(), wireTypes[.Kind()])
		return .marshalSingular(, , )
	}
}

func ( MarshalOptions) ( []byte,  protoreflect.FieldDescriptor,  protoreflect.List) ([]byte, error) {
	if .IsPacked() && .Len() > 0 {
		 = protowire.AppendTag(, .Number(), protowire.BytesType)
		,  := appendSpeculativeLength()
		for ,  := 0, .Len();  < ; ++ {
			var  error
			,  = .marshalSingular(, , .Get())
			if  != nil {
				return , 
			}
		}
		 = finishSpeculativeLength(, )
		return , nil
	}

	 := .Kind()
	for ,  := 0, .Len();  < ; ++ {
		var  error
		 = protowire.AppendTag(, .Number(), wireTypes[])
		,  = .marshalSingular(, , .Get())
		if  != nil {
			return , 
		}
	}
	return , nil
}

func ( MarshalOptions) ( []byte,  protoreflect.FieldDescriptor,  protoreflect.Map) ([]byte, error) {
	 := .MapKey()
	 := .MapValue()
	 := order.AnyKeyOrder
	if .Deterministic {
		 = order.GenericKeyOrder
	}
	var  error
	order.RangeEntries(, , func( protoreflect.MapKey,  protoreflect.Value) bool {
		 = protowire.AppendTag(, .Number(), protowire.BytesType)
		var  int
		,  = appendSpeculativeLength()

		,  = .marshalField(, , .Value())
		if  != nil {
			return false
		}
		,  = .marshalField(, , )
		if  != nil {
			return false
		}
		 = finishSpeculativeLength(, )
		return true
	})
	return , 
}

// When encoding length-prefixed fields, we speculatively set aside some number of bytes
// for the length, encode the data, and then encode the length (shifting the data if necessary
// to make room).
const speculativeLength = 1

func ( []byte) ([]byte, int) {
	 := len()
	 = append(, "\x00\x00\x00\x00"[:speculativeLength]...)
	return , 
}

func ( []byte,  int) []byte {
	 := len() -  - speculativeLength
	 := protowire.SizeVarint(uint64())
	if  != speculativeLength {
		for  := 0;  < -speculativeLength; ++ {
			 = append(, 0)
		}
		copy([+:], [+speculativeLength:])
		 = [:++]
	}
	protowire.AppendVarint([:], uint64())
	return 
}