//
// Copyright (c) 2011-2019 Canonical Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package yaml

import (
	
	
	
	
	
	
	
	
)

// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.

type parser struct {
	parser   yaml_parser_t
	event    yaml_event_t
	doc      *Node
	anchors  map[string]*Node
	doneInit bool
	textless bool
}

func newParser( []byte) *parser {
	 := parser{}
	if !yaml_parser_initialize(&.parser) {
		panic("failed to initialize YAML emitter")
	}
	if len() == 0 {
		 = []byte{'\n'}
	}
	yaml_parser_set_input_string(&.parser, )
	return &
}

func newParserFromReader( io.Reader) *parser {
	 := parser{}
	if !yaml_parser_initialize(&.parser) {
		panic("failed to initialize YAML emitter")
	}
	yaml_parser_set_input_reader(&.parser, )
	return &
}

func ( *parser) () {
	if .doneInit {
		return
	}
	.anchors = make(map[string]*Node)
	.expect(yaml_STREAM_START_EVENT)
	.doneInit = true
}

func ( *parser) () {
	if .event.typ != yaml_NO_EVENT {
		yaml_event_delete(&.event)
	}
	yaml_parser_delete(&.parser)
}

// expect consumes an event from the event stream and
// checks that it's of the expected type.
func ( *parser) ( yaml_event_type_t) {
	if .event.typ == yaml_NO_EVENT {
		if !yaml_parser_parse(&.parser, &.event) {
			.fail()
		}
	}
	if .event.typ == yaml_STREAM_END_EVENT {
		failf("attempted to go past the end of stream; corrupted value?")
	}
	if .event.typ !=  {
		.parser.problem = fmt.Sprintf("expected %s event but got %s", , .event.typ)
		.fail()
	}
	yaml_event_delete(&.event)
	.event.typ = yaml_NO_EVENT
}

// peek peeks at the next event in the event stream,
// puts the results into p.event and returns the event type.
func ( *parser) () yaml_event_type_t {
	if .event.typ != yaml_NO_EVENT {
		return .event.typ
	}
	// It's curious choice from the underlying API to generally return a
	// positive result on success, but on this case return true in an error
	// scenario. This was the source of bugs in the past (issue #666).
	if !yaml_parser_parse(&.parser, &.event) || .parser.error != yaml_NO_ERROR {
		.fail()
	}
	return .event.typ
}

func ( *parser) () {
	var  string
	var  int
	if .parser.context_mark.line != 0 {
		 = .parser.context_mark.line
		// Scanner errors don't iterate line before returning error
		if .parser.error == yaml_SCANNER_ERROR {
			++
		}
	} else if .parser.problem_mark.line != 0 {
		 = .parser.problem_mark.line
		// Scanner errors don't iterate line before returning error
		if .parser.error == yaml_SCANNER_ERROR {
			++
		}
	}
	if  != 0 {
		 = "line " + strconv.Itoa() + ": "
	}
	var  string
	if len(.parser.problem) > 0 {
		 = .parser.problem
	} else {
		 = "unknown problem parsing YAML content"
	}
	failf("%s%s", , )
}

func ( *parser) ( *Node,  []byte) {
	if  != nil {
		.Anchor = string()
		.anchors[.Anchor] = 
	}
}

func ( *parser) () *Node {
	.init()
	switch .peek() {
	case yaml_SCALAR_EVENT:
		return .scalar()
	case yaml_ALIAS_EVENT:
		return .alias()
	case yaml_MAPPING_START_EVENT:
		return .mapping()
	case yaml_SEQUENCE_START_EVENT:
		return .sequence()
	case yaml_DOCUMENT_START_EVENT:
		return .document()
	case yaml_STREAM_END_EVENT:
		// Happens when attempting to decode an empty buffer.
		return nil
	case yaml_TAIL_COMMENT_EVENT:
		panic("internal error: unexpected tail comment event (please report)")
	default:
		panic("internal error: attempted to parse unknown event (please report): " + .event.typ.String())
	}
}

func ( *parser) ( Kind, , ,  string) *Node {
	var  Style
	if  != "" &&  != "!" {
		 = shortTag()
		 = TaggedStyle
	} else if  != "" {
		 = 
	} else if  == ScalarNode {
		, _ = resolve("", )
	}
	 := &Node{
		Kind:  ,
		Tag:   ,
		Value: ,
		Style: ,
	}
	if !.textless {
		.Line = .event.start_mark.line + 1
		.Column = .event.start_mark.column + 1
		.HeadComment = string(.event.head_comment)
		.LineComment = string(.event.line_comment)
		.FootComment = string(.event.foot_comment)
	}
	return 
}

func ( *parser) ( *Node) *Node {
	 := .parse()
	.Content = append(.Content, )
	return 
}

func ( *parser) () *Node {
	 := .node(DocumentNode, "", "", "")
	.doc = 
	.expect(yaml_DOCUMENT_START_EVENT)
	.parseChild()
	if .peek() == yaml_DOCUMENT_END_EVENT {
		.FootComment = string(.event.foot_comment)
	}
	.expect(yaml_DOCUMENT_END_EVENT)
	return 
}

func ( *parser) () *Node {
	 := .node(AliasNode, "", "", string(.event.anchor))
	.Alias = .anchors[.Value]
	if .Alias == nil {
		failf("unknown anchor '%s' referenced", .Value)
	}
	.expect(yaml_ALIAS_EVENT)
	return 
}

func ( *parser) () *Node {
	var  = .event.scalar_style()
	var  Style
	switch {
	case &yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
		 = DoubleQuotedStyle
	case &yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
		 = SingleQuotedStyle
	case &yaml_LITERAL_SCALAR_STYLE != 0:
		 = LiteralStyle
	case &yaml_FOLDED_SCALAR_STYLE != 0:
		 = FoldedStyle
	}
	var  = string(.event.value)
	var  = string(.event.tag)
	var  string
	if  == 0 {
		if  == "<<" {
			 = mergeTag
		}
	} else {
		 = strTag
	}
	 := .node(ScalarNode, , , )
	.Style |= 
	.anchor(, .event.anchor)
	.expect(yaml_SCALAR_EVENT)
	return 
}

func ( *parser) () *Node {
	 := .node(SequenceNode, seqTag, string(.event.tag), "")
	if .event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
		.Style |= FlowStyle
	}
	.anchor(, .event.anchor)
	.expect(yaml_SEQUENCE_START_EVENT)
	for .peek() != yaml_SEQUENCE_END_EVENT {
		.parseChild()
	}
	.LineComment = string(.event.line_comment)
	.FootComment = string(.event.foot_comment)
	.expect(yaml_SEQUENCE_END_EVENT)
	return 
}

func ( *parser) () *Node {
	 := .node(MappingNode, mapTag, string(.event.tag), "")
	 := true
	if .event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
		 = false
		.Style |= FlowStyle
	}
	.anchor(, .event.anchor)
	.expect(yaml_MAPPING_START_EVENT)
	for .peek() != yaml_MAPPING_END_EVENT {
		 := .parseChild()
		if  && .FootComment != "" {
			// Must be a foot comment for the prior value when being dedented.
			if len(.Content) > 2 {
				.Content[len(.Content)-3].FootComment = .FootComment
				.FootComment = ""
			}
		}
		 := .parseChild()
		if .FootComment == "" && .FootComment != "" {
			.FootComment = .FootComment
			.FootComment = ""
		}
		if .peek() == yaml_TAIL_COMMENT_EVENT {
			if .FootComment == "" {
				.FootComment = string(.event.foot_comment)
			}
			.expect(yaml_TAIL_COMMENT_EVENT)
		}
	}
	.LineComment = string(.event.line_comment)
	.FootComment = string(.event.foot_comment)
	if .Style&FlowStyle == 0 && .FootComment != "" && len(.Content) > 1 {
		.Content[len(.Content)-2].FootComment = .FootComment
		.FootComment = ""
	}
	.expect(yaml_MAPPING_END_EVENT)
	return 
}

// ----------------------------------------------------------------------------
// Decoder, unmarshals a node into a provided value.

type decoder struct {
	doc     *Node
	aliases map[*Node]bool
	terrors []string

	stringMapType  reflect.Type
	generalMapType reflect.Type

	knownFields bool
	uniqueKeys  bool
	decodeCount int
	aliasCount  int
	aliasDepth  int

	mergedFields map[interface{}]bool
}

var (
	nodeType       = reflect.TypeOf(Node{})
	durationType   = reflect.TypeOf(time.Duration(0))
	stringMapType  = reflect.TypeOf(map[string]interface{}{})
	generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
	ifaceType      = generalMapType.Elem()
	timeType       = reflect.TypeOf(time.Time{})
	ptrTimeType    = reflect.TypeOf(&time.Time{})
)

func newDecoder() *decoder {
	 := &decoder{
		stringMapType:  stringMapType,
		generalMapType: generalMapType,
		uniqueKeys:     true,
	}
	.aliases = make(map[*Node]bool)
	return 
}

func ( *decoder) ( *Node,  string,  reflect.Value) {
	if .Tag != "" {
		 = .Tag
	}
	 := .Value
	if  != seqTag &&  != mapTag {
		if len() > 10 {
			 = " `" + [:7] + "...`"
		} else {
			 = " `" +  + "`"
		}
	}
	.terrors = append(.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", .Line, shortTag(), , .Type()))
}

func ( *decoder) ( *Node,  Unmarshaler) ( bool) {
	 := .UnmarshalYAML()
	if ,  := .(*TypeError);  {
		.terrors = append(.terrors, .Errors...)
		return false
	}
	if  != nil {
		fail()
	}
	return true
}

func ( *decoder) ( *Node,  obsoleteUnmarshaler) ( bool) {
	 := len(.terrors)
	 := .UnmarshalYAML(func( interface{}) ( error) {
		defer handleErr(&)
		.unmarshal(, reflect.ValueOf())
		if len(.terrors) >  {
			 := .terrors[:]
			.terrors = .terrors[:]
			return &TypeError{}
		}
		return nil
	})
	if ,  := .(*TypeError);  {
		.terrors = append(.terrors, .Errors...)
		return false
	}
	if  != nil {
		fail()
	}
	return true
}

// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
// if a value is found to implement it.
// It returns the initialized and dereferenced out value, whether
// unmarshalling was already done by UnmarshalYAML, and if so whether
// its types unmarshalled appropriately.
//
// If n holds a null value, prepare returns before doing anything.
func ( *decoder) ( *Node,  reflect.Value) ( reflect.Value, ,  bool) {
	if .ShortTag() == nullTag {
		return , false, false
	}
	 := true
	for  {
		 = false
		if .Kind() == reflect.Ptr {
			if .IsNil() {
				.Set(reflect.New(.Type().Elem()))
			}
			 = .Elem()
			 = true
		}
		if .CanAddr() {
			 := .Addr().Interface()
			if ,  := .(Unmarshaler);  {
				 = .callUnmarshaler(, )
				return , true, 
			}
			if ,  := .(obsoleteUnmarshaler);  {
				 = .callObsoleteUnmarshaler(, )
				return , true, 
			}
		}
	}
	return , false, false
}

func ( *decoder) ( *Node,  reflect.Value,  []int) ( reflect.Value) {
	if .ShortTag() == nullTag {
		return reflect.Value{}
	}
	for ,  := range  {
		for {
			if .Kind() == reflect.Ptr {
				if .IsNil() {
					.Set(reflect.New(.Type().Elem()))
				}
				 = .Elem()
				continue
			}
			break
		}
		 = .Field()
	}
	return 
}

const (
	// 400,000 decode operations is ~500kb of dense object declarations, or
	// ~5kb of dense object declarations with 10000% alias expansion
	alias_ratio_range_low = 400000

	// 4,000,000 decode operations is ~5MB of dense object declarations, or
	// ~4.5MB of dense object declarations with 10% alias expansion
	alias_ratio_range_high = 4000000

	// alias_ratio_range is the range over which we scale allowed alias ratios
	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
)

func allowedAliasRatio( int) float64 {
	switch {
	case  <= alias_ratio_range_low:
		// allow 99% to come from alias expansion for small-to-medium documents
		return 0.99
	case  >= alias_ratio_range_high:
		// allow 10% to come from alias expansion for very large documents
		return 0.10
	default:
		// scale smoothly from 99% down to 10% over the range.
		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
		return 0.99 - 0.89*(float64(-alias_ratio_range_low)/alias_ratio_range)
	}
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	.decodeCount++
	if .aliasDepth > 0 {
		.aliasCount++
	}
	if .aliasCount > 100 && .decodeCount > 1000 && float64(.aliasCount)/float64(.decodeCount) > allowedAliasRatio(.decodeCount) {
		failf("document contains excessive aliasing")
	}
	if .Type() == nodeType {
		.Set(reflect.ValueOf().Elem())
		return true
	}
	switch .Kind {
	case DocumentNode:
		return .document(, )
	case AliasNode:
		return .alias(, )
	}
	, ,  := .prepare(, )
	if  {
		return 
	}
	switch .Kind {
	case ScalarNode:
		 = .scalar(, )
	case MappingNode:
		 = .mapping(, )
	case SequenceNode:
		 = .sequence(, )
	case 0:
		if .IsZero() {
			return .null()
		}
		fallthrough
	default:
		failf("cannot decode node with unknown kind %d", .Kind)
	}
	return 
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	if len(.Content) == 1 {
		.doc = 
		.unmarshal(.Content[0], )
		return true
	}
	return false
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	if .aliases[] {
		// TODO this could actually be allowed in some circumstances.
		failf("anchor '%s' value contains itself", .Value)
	}
	.aliases[] = true
	.aliasDepth++
	 = .unmarshal(.Alias, )
	.aliasDepth--
	delete(.aliases, )
	return 
}

var zeroValue reflect.Value

func resetMap( reflect.Value) {
	for ,  := range .MapKeys() {
		.SetMapIndex(, zeroValue)
	}
}

func ( *decoder) ( reflect.Value) bool {
	if .CanAddr() {
		switch .Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
			.Set(reflect.Zero(.Type()))
			return true
		}
	}
	return false
}

func ( *decoder) ( *Node,  reflect.Value) bool {
	var  string
	var  interface{}
	if .indicatedString() {
		 = strTag
		 = .Value
	} else {
		,  = resolve(.Tag, .Value)
		if  == binaryTag {
			,  := base64.StdEncoding.DecodeString(.(string))
			if  != nil {
				failf("!!binary value contains invalid base64 data")
			}
			 = string()
		}
	}
	if  == nil {
		return .null()
	}
	if  := reflect.ValueOf(); .Type() == .Type() {
		// We've resolved to exactly the type we want, so use that.
		.Set()
		return true
	}
	// Perhaps we can use the value as a TextUnmarshaler to
	// set its value.
	if .CanAddr() {
		,  := .Addr().Interface().(encoding.TextUnmarshaler)
		if  {
			var  []byte
			if  == binaryTag {
				 = []byte(.(string))
			} else {
				// We let any value be unmarshaled into TextUnmarshaler.
				// That might be more lax than we'd like, but the
				// TextUnmarshaler itself should bowl out any dubious values.
				 = []byte(.Value)
			}
			 := .UnmarshalText()
			if  != nil {
				fail()
			}
			return true
		}
	}
	switch .Kind() {
	case reflect.String:
		if  == binaryTag {
			.SetString(.(string))
			return true
		}
		.SetString(.Value)
		return true
	case reflect.Interface:
		.Set(reflect.ValueOf())
		return true
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		// This used to work in v2, but it's very unfriendly.
		 := .Type() == durationType

		switch resolved := .(type) {
		case int:
			if ! && !.OverflowInt(int64()) {
				.SetInt(int64())
				return true
			}
		case int64:
			if ! && !.OverflowInt() {
				.SetInt()
				return true
			}
		case uint64:
			if ! &&  <= math.MaxInt64 && !.OverflowInt(int64()) {
				.SetInt(int64())
				return true
			}
		case float64:
			if ! &&  <= math.MaxInt64 && !.OverflowInt(int64()) {
				.SetInt(int64())
				return true
			}
		case string:
			if .Type() == durationType {
				,  := time.ParseDuration()
				if  == nil {
					.SetInt(int64())
					return true
				}
			}
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		switch resolved := .(type) {
		case int:
			if  >= 0 && !.OverflowUint(uint64()) {
				.SetUint(uint64())
				return true
			}
		case int64:
			if  >= 0 && !.OverflowUint(uint64()) {
				.SetUint(uint64())
				return true
			}
		case uint64:
			if !.OverflowUint(uint64()) {
				.SetUint(uint64())
				return true
			}
		case float64:
			if  <= math.MaxUint64 && !.OverflowUint(uint64()) {
				.SetUint(uint64())
				return true
			}
		}
	case reflect.Bool:
		switch resolved := .(type) {
		case bool:
			.SetBool()
			return true
		case string:
			// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
			// It only works if explicitly attempting to unmarshal into a typed bool value.
			switch  {
			case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
				.SetBool(true)
				return true
			case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
				.SetBool(false)
				return true
			}
		}
	case reflect.Float32, reflect.Float64:
		switch resolved := .(type) {
		case int:
			.SetFloat(float64())
			return true
		case int64:
			.SetFloat(float64())
			return true
		case uint64:
			.SetFloat(float64())
			return true
		case float64:
			.SetFloat()
			return true
		}
	case reflect.Struct:
		if  := reflect.ValueOf(); .Type() == .Type() {
			.Set()
			return true
		}
	case reflect.Ptr:
		panic("yaml internal error: please report the issue")
	}
	.terror(, , )
	return false
}

func settableValueOf( interface{}) reflect.Value {
	 := reflect.ValueOf()
	 := reflect.New(.Type()).Elem()
	.Set()
	return 
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	 := len(.Content)

	var  reflect.Value
	switch .Kind() {
	case reflect.Slice:
		.Set(reflect.MakeSlice(.Type(), , ))
	case reflect.Array:
		if  != .Len() {
			failf("invalid array: want %d elements but got %d", .Len(), )
		}
	case reflect.Interface:
		// No type hints. Will have to use a generic sequence.
		 = 
		 = settableValueOf(make([]interface{}, ))
	default:
		.terror(, seqTag, )
		return false
	}
	 := .Type().Elem()

	 := 0
	for  := 0;  < ; ++ {
		 := reflect.New().Elem()
		if  := .unmarshal(.Content[], );  {
			.Index().Set()
			++
		}
	}
	if .Kind() != reflect.Array {
		.Set(.Slice(0, ))
	}
	if .IsValid() {
		.Set()
	}
	return true
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	 := len(.Content)
	if .uniqueKeys {
		 := len(.terrors)
		for  := 0;  < ;  += 2 {
			 := .Content[]
			for  :=  + 2;  < ;  += 2 {
				 := .Content[]
				if .Kind == .Kind && .Value == .Value {
					.terrors = append(.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", .Line, .Value, .Line))
				}
			}
		}
		if len(.terrors) >  {
			return false
		}
	}
	switch .Kind() {
	case reflect.Struct:
		return .mappingStruct(, )
	case reflect.Map:
		// okay
	case reflect.Interface:
		 := 
		if isStringMap() {
			 = reflect.MakeMap(.stringMapType)
		} else {
			 = reflect.MakeMap(.generalMapType)
		}
		.Set()
	default:
		.terror(, mapTag, )
		return false
	}

	 := .Type()
	 := .Key()
	 := .Elem()

	 := .stringMapType
	 := .generalMapType
	if .Elem() == ifaceType {
		if .Key().Kind() == reflect.String {
			.stringMapType = 
		} else if .Key() == ifaceType {
			.generalMapType = 
		}
	}

	 := .mergedFields
	.mergedFields = nil

	var  *Node

	 := false
	if .IsNil() {
		.Set(reflect.MakeMap())
		 = true
	}
	for  := 0;  < ;  += 2 {
		if isMerge(.Content[]) {
			 = .Content[+1]
			continue
		}
		 := reflect.New().Elem()
		if .unmarshal(.Content[], ) {
			if  != nil {
				 := .Interface()
				if [] {
					continue
				}
				[] = true
			}
			 := .Kind()
			if  == reflect.Interface {
				 = .Elem().Kind()
			}
			if  == reflect.Map ||  == reflect.Slice {
				failf("invalid map key: %#v", .Interface())
			}
			 := reflect.New().Elem()
			if .unmarshal(.Content[+1], ) || .Content[+1].ShortTag() == nullTag && ( || !.MapIndex().IsValid()) {
				.SetMapIndex(, )
			}
		}
	}

	.mergedFields = 
	if  != nil {
		.merge(, , )
	}

	.stringMapType = 
	.generalMapType = 
	return true
}

func isStringMap( *Node) bool {
	if .Kind != MappingNode {
		return false
	}
	 := len(.Content)
	for  := 0;  < ;  += 2 {
		 := .Content[].ShortTag()
		if  != strTag &&  != mergeTag {
			return false
		}
	}
	return true
}

func ( *decoder) ( *Node,  reflect.Value) ( bool) {
	,  := getStructInfo(.Type())
	if  != nil {
		panic()
	}

	var  reflect.Value
	var  reflect.Type
	if .InlineMap != -1 {
		 = .Field(.InlineMap)
		 = .Type().Elem()
	}

	for ,  := range .InlineUnmarshalers {
		 := .fieldByIndex(, , )
		.prepare(, )
	}

	 := .mergedFields
	.mergedFields = nil
	var  *Node
	var  []bool
	if .uniqueKeys {
		 = make([]bool, len(.FieldsList))
	}
	 := settableValueOf("")
	 := len(.Content)
	for  := 0;  < ;  += 2 {
		 := .Content[]
		if isMerge() {
			 = .Content[+1]
			continue
		}
		if !.unmarshal(, ) {
			continue
		}
		 := .String()
		if  != nil {
			if [] {
				continue
			}
			[] = true
		}
		if ,  := .FieldsMap[];  {
			if .uniqueKeys {
				if [.Id] {
					.terrors = append(.terrors, fmt.Sprintf("line %d: field %s already set in type %s", .Line, .String(), .Type()))
					continue
				}
				[.Id] = true
			}
			var  reflect.Value
			if .Inline == nil {
				 = .Field(.Num)
			} else {
				 = .fieldByIndex(, , .Inline)
			}
			.unmarshal(.Content[+1], )
		} else if .InlineMap != -1 {
			if .IsNil() {
				.Set(reflect.MakeMap(.Type()))
			}
			 := reflect.New().Elem()
			.unmarshal(.Content[+1], )
			.SetMapIndex(, )
		} else if .knownFields {
			.terrors = append(.terrors, fmt.Sprintf("line %d: field %s not found in type %s", .Line, .String(), .Type()))
		}
	}

	.mergedFields = 
	if  != nil {
		.merge(, , )
	}
	return true
}

func failWantMap() {
	failf("map merge requires map or sequence of maps as the value")
}

func ( *decoder) ( *Node,  *Node,  reflect.Value) {
	 := .mergedFields
	if  == nil {
		.mergedFields = make(map[interface{}]bool)
		for  := 0;  < len(.Content);  += 2 {
			 := reflect.New(ifaceType).Elem()
			if .unmarshal(.Content[], ) {
				.mergedFields[.Interface()] = true
			}
		}
	}

	switch .Kind {
	case MappingNode:
		.unmarshal(, )
	case AliasNode:
		if .Alias != nil && .Alias.Kind != MappingNode {
			failWantMap()
		}
		.unmarshal(, )
	case SequenceNode:
		for  := 0;  < len(.Content); ++ {
			 := .Content[]
			if .Kind == AliasNode {
				if .Alias != nil && .Alias.Kind != MappingNode {
					failWantMap()
				}
			} else if .Kind != MappingNode {
				failWantMap()
			}
			.unmarshal(, )
		}
	default:
		failWantMap()
	}

	.mergedFields = 
}

func isMerge( *Node) bool {
	return .Kind == ScalarNode && .Value == "<<" && (.Tag == "" || .Tag == "!" || shortTag(.Tag) == mergeTag)
}