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

	
	
	
	piface 
)

type marshalOptions struct {
	flags piface.MarshalInputFlags
}

func ( marshalOptions) () proto.MarshalOptions {
	return proto.MarshalOptions{
		AllowPartial:  true,
		Deterministic: .Deterministic(),
		UseCachedSize: .UseCachedSize(),
	}
}

func ( marshalOptions) () bool { return .flags&piface.MarshalDeterministic != 0 }
func ( marshalOptions) () bool { return .flags&piface.MarshalUseCachedSize != 0 }

// size is protoreflect.Methods.Size.
func ( *MessageInfo) ( piface.SizeInput) piface.SizeOutput {
	var  pointer
	if ,  := .Message.(*messageState);  {
		 = .pointer()
	} else {
		 = .Message.(*messageReflectWrapper).pointer()
	}
	 := .sizePointer(, marshalOptions{
		flags: .Flags,
	})
	return piface.SizeOutput{Size: }
}

func ( *MessageInfo) ( pointer,  marshalOptions) ( int) {
	.init()
	if .IsNil() {
		return 0
	}
	if .UseCachedSize() && .sizecacheOffset.IsValid() {
		// The size cache contains the size + 1, to allow the
		// zero value to be invalid, while also allowing for a
		// 0 size to be cached.
		if  := atomic.LoadInt32(.Apply(.sizecacheOffset).Int32());  > 0 {
			return int( - 1)
		}
	}
	return .sizePointerSlow(, )
}

func ( *MessageInfo) ( pointer,  marshalOptions) ( int) {
	if flags.ProtoLegacy && .isMessageSet {
		 = sizeMessageSet(, , )
		if .sizecacheOffset.IsValid() {
			atomic.StoreInt32(.Apply(.sizecacheOffset).Int32(), int32(+1))
		}
		return 
	}
	if .extensionOffset.IsValid() {
		 := .Apply(.extensionOffset).Extensions()
		 += .sizeExtensions(, )
	}

	var  **protolazy.XXX_lazyUnmarshalInfo
	var  presence
	if .presenceOffset.IsValid() {
		 = .Apply(.presenceOffset).PresenceInfo()
		if .lazyOffset.IsValid() {
			 = .Apply(.lazyOffset).LazyInfoPtr()
		}
	}

	for ,  := range .orderedCoderFields {
		if .funcs.size == nil {
			continue
		}
		 := .Apply(.offset)

		if .presenceIndex != noPresence {
			if !.Present(.presenceIndex) {
				continue
			}

			if .isLazy && .AtomicGetPointer().IsNil() {
				if lazyFields() {
					 += (*).SizeField(uint32(.num))
					continue
				} else {
					.lazyUnmarshal(, .num)
				}
			}
			 += .funcs.size(, , )
			continue
		}

		if .isPointer && .Elem().IsNil() {
			continue
		}
		 += .funcs.size(, , )
	}
	if .unknownOffset.IsValid() {
		if  := .getUnknownBytes();  != nil {
			 += len(*)
		}
	}
	if .sizecacheOffset.IsValid() {
		if  > (math.MaxInt32 - 1) {
			// The size is too large for the int32 sizecache field.
			// We will need to recompute the size when encoding;
			// unfortunately expensive, but better than invalid output.
			atomic.StoreInt32(.Apply(.sizecacheOffset).Int32(), 0)
		} else {
			// The size cache contains the size + 1, to allow the
			// zero value to be invalid, while also allowing for a
			// 0 size to be cached.
			atomic.StoreInt32(.Apply(.sizecacheOffset).Int32(), int32(+1))
		}
	}
	return 
}

// marshal is protoreflect.Methods.Marshal.
func ( *MessageInfo) ( piface.MarshalInput) ( piface.MarshalOutput,  error) {
	var  pointer
	if ,  := .Message.(*messageState);  {
		 = .pointer()
	} else {
		 = .Message.(*messageReflectWrapper).pointer()
	}
	,  := .marshalAppendPointer(.Buf, , marshalOptions{
		flags: .Flags,
	})
	return piface.MarshalOutput{Buf: }, 
}

func ( *MessageInfo) ( []byte,  pointer,  marshalOptions) ([]byte, error) {
	.init()
	if .IsNil() {
		return , nil
	}
	if flags.ProtoLegacy && .isMessageSet {
		return marshalMessageSet(, , , )
	}
	var  error
	// The old marshaler encodes extensions at beginning.
	if .extensionOffset.IsValid() {
		 := .Apply(.extensionOffset).Extensions()
		// TODO: Special handling for MessageSet?
		,  = .appendExtensions(, , )
		if  != nil {
			return , 
		}
	}

	var  **protolazy.XXX_lazyUnmarshalInfo
	var  presence
	if .presenceOffset.IsValid() {
		 = .Apply(.presenceOffset).PresenceInfo()
		if .lazyOffset.IsValid() {
			 = .Apply(.lazyOffset).LazyInfoPtr()
		}
	}

	for ,  := range .orderedCoderFields {
		if .funcs.marshal == nil {
			continue
		}
		 := .Apply(.offset)

		if .presenceIndex != noPresence {
			if !.Present(.presenceIndex) {
				continue
			}
			if .isLazy {
				// Be careful, this field needs to be read atomically, like for a get
				if .isPointer && .AtomicGetPointer().IsNil() {
					if lazyFields() {
						, _ = (*).AppendField(, uint32(.num))
						continue
					} else {
						.lazyUnmarshal(, .num)
					}
				}

				,  = .funcs.marshal(, , , )
				if  != nil {
					return , 
				}
				continue
			} else if .isPointer && .Elem().IsNil() {
				continue
			}
			,  = .funcs.marshal(, , , )
			if  != nil {
				return , 
			}
			continue
		}

		if .isPointer && .Elem().IsNil() {
			continue
		}
		,  = .funcs.marshal(, , , )
		if  != nil {
			return , 
		}
	}
	if .unknownOffset.IsValid() && !.isMessageSet {
		if  := .getUnknownBytes();  != nil {
			 = append(, (*)...)
		}
	}
	return , nil
}

// fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal.
func ( marshalOptions) bool {
	// When deterministic marshaling is requested, force an unmarshal for lazy
	// extensions to produce a deterministic result, instead of passing through
	// bytes lazily that may or may not match what Go Protobuf would produce.
	return .flags&piface.MarshalDeterministic == 0
}

// lazyFields returns true if we should attempt to keep fields lazy over size and marshal.
func ( marshalOptions) bool {
	// When deterministic marshaling is requested, force an unmarshal for lazy
	// fields to produce a deterministic result, instead of passing through
	// bytes lazily that may or may not match what Go Protobuf would produce.
	return .flags&piface.MarshalDeterministic == 0
}

func ( *MessageInfo) ( *map[int32]ExtensionField,  marshalOptions) ( int) {
	if  == nil {
		return 0
	}
	for ,  := range * {
		 := getExtensionFieldInfo(.Type())
		if .funcs.size == nil {
			continue
		}
		if fullyLazyExtensions() {
			// Don't expand the extension, instead use the buffer to calculate size
			if  := .lazyBuffer();  != nil {
				// We got hold of the buffer, so it's still lazy.
				 += len()
				continue
			}
		}
		 += .funcs.size(.Value(), .tagsize, )
	}
	return 
}

func ( *MessageInfo) ( []byte,  *map[int32]ExtensionField,  marshalOptions) ([]byte, error) {
	if  == nil {
		return , nil
	}

	switch len(*) {
	case 0:
		return , nil
	case 1:
		// Fast-path for one extension: Don't bother sorting the keys.
		var  error
		for ,  := range * {
			 := getExtensionFieldInfo(.Type())
			if fullyLazyExtensions() {
				// Don't expand the extension if it's still in wire format, instead use the buffer content.
				if  := .lazyBuffer();  != nil {
					 = append(, ...)
					continue
				}
			}
			,  = .funcs.marshal(, .Value(), .wiretag, )
		}
		return , 
	default:
		// Sort the keys to provide a deterministic encoding.
		// Not sure this is required, but the old code does it.
		 := make([]int, 0, len(*))
		for  := range * {
			 = append(, int())
		}
		sort.Ints()
		var  error
		for ,  := range  {
			 := (*)[int32()]
			 := getExtensionFieldInfo(.Type())
			if fullyLazyExtensions() {
				// Don't expand the extension if it's still in wire format, instead use the buffer content.
				if  := .lazyBuffer();  != nil {
					 = append(, ...)
					continue
				}
			}
			,  = .funcs.marshal(, .Value(), .wiretag, )
			if  != nil {
				return , 
			}
		}
		return , nil
	}
}