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

	
	
	
	
	
	
	
)

var errDecode = errors.New("cannot parse invalid wire-format data")
var errRecursionDepth = errors.New("exceeded maximum recursion depth")

type unmarshalOptions struct {
	flags    protoiface.UnmarshalInputFlags
	resolver interface {
		FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
		FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
	}
	depth int
}

func ( unmarshalOptions) () proto.UnmarshalOptions {
	return proto.UnmarshalOptions{
		Merge:          true,
		AllowPartial:   true,
		DiscardUnknown: .DiscardUnknown(),
		Resolver:       .resolver,
	}
}

func ( unmarshalOptions) () bool {
	return .flags&protoiface.UnmarshalDiscardUnknown != 0
}

func ( unmarshalOptions) () bool {
	return .flags == 0 && .resolver == protoregistry.GlobalTypes
}

var lazyUnmarshalOptions = unmarshalOptions{
	resolver: protoregistry.GlobalTypes,
	depth:    protowire.DefaultRecursionLimit,
}

type unmarshalOutput struct {
	n           int // number of bytes consumed
	initialized bool
}

// unmarshal is protoreflect.Methods.Unmarshal.
func ( *MessageInfo) ( protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
	var  pointer
	if ,  := .Message.(*messageState);  {
		 = .pointer()
	} else {
		 = .Message.(*messageReflectWrapper).pointer()
	}
	,  := .unmarshalPointer(.Buf, , 0, unmarshalOptions{
		flags:    .Flags,
		resolver: .Resolver,
		depth:    .Depth,
	})
	var  protoiface.UnmarshalOutputFlags
	if .initialized {
		 |= protoiface.UnmarshalInitialized
	}
	return protoiface.UnmarshalOutput{
		Flags: ,
	}, 
}

// errUnknown is returned during unmarshaling to indicate a parse error that
// should result in a field being placed in the unknown fields section (for example,
// when the wire type doesn't match) as opposed to the entire unmarshal operation
// failing (for example, when a field extends past the available input).
//
// This is a sentinel error which should never be visible to the user.
var errUnknown = errors.New("unknown")

func ( *MessageInfo) ( []byte,  pointer,  protowire.Number,  unmarshalOptions) ( unmarshalOutput,  error) {
	.init()
	.depth--
	if .depth < 0 {
		return , errRecursionDepth
	}
	if flags.ProtoLegacy && .isMessageSet {
		return unmarshalMessageSet(, , , )
	}
	 := true
	var  uint64
	var  *map[int32]ExtensionField
	 := len()
	for len() > 0 {
		// Parse the tag (field number and wire type).
		var  uint64
		if [0] < 0x80 {
			 = uint64([0])
			 = [1:]
		} else if len() >= 2 && [1] < 128 {
			 = uint64([0]&0x7f) + uint64([1])<<7
			 = [2:]
		} else {
			var  int
			,  = protowire.ConsumeVarint()
			if  < 0 {
				return , errDecode
			}
			 = [:]
		}
		var  protowire.Number
		if  :=  >> 3;  < uint64(protowire.MinValidNumber) ||  > uint64(protowire.MaxValidNumber) {
			return , errDecode
		} else {
			 = protowire.Number()
		}
		 := protowire.Type( & 7)

		if  == protowire.EndGroupType {
			if  !=  {
				return , errDecode
			}
			 = 0
			break
		}

		var  *coderFieldInfo
		if int() < len(.denseCoderFields) {
			 = .denseCoderFields[]
		} else {
			 = .coderFields[]
		}
		var  int
		 := errUnknown
		switch {
		case  != nil:
			if .funcs.unmarshal == nil {
				break
			}
			var  unmarshalOutput
			,  = .funcs.unmarshal(, .Apply(.offset), , , )
			 = .n
			if  != nil {
				break
			}
			 |= .validation.requiredBit
			if .funcs.isInit != nil && !.initialized {
				 = false
			}
		default:
			// Possible extension.
			if  == nil && .extensionOffset.IsValid() {
				 = .Apply(.extensionOffset).Extensions()
				if * == nil {
					* = make(map[int32]ExtensionField)
				}
			}
			if  == nil {
				break
			}
			var  unmarshalOutput
			,  = .unmarshalExtension(, , , *, )
			if  != nil {
				break
			}
			 = .n
			if !.initialized {
				 = false
			}
		}
		if  != nil {
			if  != errUnknown {
				return , 
			}
			 = protowire.ConsumeFieldValue(, , )
			if  < 0 {
				return , errDecode
			}
			if !.DiscardUnknown() && .unknownOffset.IsValid() {
				 := .mutableUnknownBytes()
				* = protowire.AppendTag(*, , )
				* = append(*, [:]...)
			}
		}
		 = [:]
	}
	if  != 0 {
		return , errDecode
	}
	if .numRequiredFields > 0 && bits.OnesCount64() != int(.numRequiredFields) {
		 = false
	}
	if  {
		.initialized = true
	}
	.n =  - len()
	return , nil
}

func ( *MessageInfo) ( []byte,  protowire.Number,  protowire.Type,  map[int32]ExtensionField,  unmarshalOptions) ( unmarshalOutput,  error) {
	 := [int32()]
	 := .Type()
	if  == nil {
		var  error
		,  = .resolver.FindExtensionByNumber(.Desc.FullName(), )
		if  != nil {
			if  == protoregistry.NotFound {
				return , errUnknown
			}
			return , errors.New("%v: unable to resolve extension %v: %v", .Desc.FullName(), , )
		}
	}
	 := getExtensionFieldInfo()
	if .funcs.unmarshal == nil {
		return , errUnknown
	}
	if flags.LazyUnmarshalExtensions {
		if .IsDefault() && .canLazy() {
			,  := skipExtension(, , , , )
			switch  {
			case ValidationValid:
				if .initialized {
					.appendLazyBytes(, , , , [:.n])
					[int32()] = 
					return , nil
				}
			case ValidationInvalid:
				return , errDecode
			case ValidationUnknown:
			}
		}
	}
	 := .Value()
	if !.IsValid() && .unmarshalNeedsValue {
		// Create a new message, list, or map value to fill in.
		// For enums, create a prototype value to let the unmarshal func know the
		// concrete type.
		 = .New()
	}
	, ,  := .funcs.unmarshal(, , , , )
	if  != nil {
		return , 
	}
	if .funcs.isInit == nil {
		.initialized = true
	}
	.Set(, )
	[int32()] = 
	return , nil
}

func ( []byte,  *extensionFieldInfo,  protowire.Number,  protowire.Type,  unmarshalOptions) ( unmarshalOutput,  ValidationStatus) {
	if .validation.mi == nil {
		return , ValidationUnknown
	}
	.validation.mi.init()
	switch .validation.typ {
	case validationTypeMessage:
		if  != protowire.BytesType {
			return , ValidationUnknown
		}
		,  := protowire.ConsumeBytes()
		if  < 0 {
			return , ValidationUnknown
		}
		,  := .validation.mi.validate(, 0, )
		.n = 
		return , 
	case validationTypeGroup:
		if  != protowire.StartGroupType {
			return , ValidationUnknown
		}
		,  := .validation.mi.validate(, , )
		return , 
	default:
		return , ValidationUnknown
	}
}