vendor/gopkg.in/yaml.v3/decode.go
author Mikael Berthe <mikael@lilotux.net>
Sun, 11 Jul 2021 10:35:56 +0200
changeset 256 6d9efbef00a9
child 260 445e01aede7e
permissions -rw-r--r--
Update dependencies
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
256
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     1
//
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     2
// Copyright (c) 2011-2019 Canonical Ltd
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
//
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
// Licensed under the Apache License, Version 2.0 (the "License");
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
// you may not use this file except in compliance with the License.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     6
// You may obtain a copy of the License at
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     7
//
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
//     http://www.apache.org/licenses/LICENSE-2.0
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
//
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
// Unless required by applicable law or agreed to in writing, software
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
// distributed under the License is distributed on an "AS IS" BASIS,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
// See the License for the specific language governing permissions and
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
// limitations under the License.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    15
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    16
package yaml
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    17
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
import (
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
	"encoding"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
	"encoding/base64"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
	"fmt"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    22
	"io"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
	"math"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
	"reflect"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
	"strconv"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    26
	"time"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
// ----------------------------------------------------------------------------
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
// Parser, produces a node tree out of a libyaml event stream.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
type parser struct {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
	parser   yaml_parser_t
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
	event    yaml_event_t
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
	doc      *Node
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
	anchors  map[string]*Node
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
	doneInit bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
	textless bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
func newParser(b []byte) *parser {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
	p := parser{}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
	if !yaml_parser_initialize(&p.parser) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
		panic("failed to initialize YAML emitter")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
	if len(b) == 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
		b = []byte{'\n'}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
	yaml_parser_set_input_string(&p.parser, b)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
	return &p
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    52
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    53
func newParserFromReader(r io.Reader) *parser {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    54
	p := parser{}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    55
	if !yaml_parser_initialize(&p.parser) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
		panic("failed to initialize YAML emitter")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
	yaml_parser_set_input_reader(&p.parser, r)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
	return &p
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    62
func (p *parser) init() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
	if p.doneInit {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    64
		return
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
	p.anchors = make(map[string]*Node)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
	p.expect(yaml_STREAM_START_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
	p.doneInit = true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
func (p *parser) destroy() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
	if p.event.typ != yaml_NO_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
		yaml_event_delete(&p.event)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
	yaml_parser_delete(&p.parser)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    78
// expect consumes an event from the event stream and
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    79
// checks that it's of the expected type.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    80
func (p *parser) expect(e yaml_event_type_t) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    81
	if p.event.typ == yaml_NO_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    82
		if !yaml_parser_parse(&p.parser, &p.event) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    83
			p.fail()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    84
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    85
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    86
	if p.event.typ == yaml_STREAM_END_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    87
		failf("attempted to go past the end of stream; corrupted value?")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    88
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    89
	if p.event.typ != e {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    90
		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    91
		p.fail()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    92
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    93
	yaml_event_delete(&p.event)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    94
	p.event.typ = yaml_NO_EVENT
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    95
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    96
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    97
// peek peeks at the next event in the event stream,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
// puts the results into p.event and returns the event type.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
func (p *parser) peek() yaml_event_type_t {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
	if p.event.typ != yaml_NO_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
		return p.event.typ
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   102
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   103
	if !yaml_parser_parse(&p.parser, &p.event) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   104
		p.fail()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   105
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   106
	return p.event.typ
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
func (p *parser) fail() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
	var where string
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
	var line int
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
	if p.parser.context_mark.line != 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
		line = p.parser.context_mark.line
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
		// Scanner errors don't iterate line before returning error
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
		if p.parser.error == yaml_SCANNER_ERROR {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
			line++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   118
	} else if p.parser.problem_mark.line != 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   119
		line = p.parser.problem_mark.line
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   120
		// Scanner errors don't iterate line before returning error
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   121
		if p.parser.error == yaml_SCANNER_ERROR {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   122
			line++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   123
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   124
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   125
	if line != 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   126
		where = "line " + strconv.Itoa(line) + ": "
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   127
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   128
	var msg string
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   129
	if len(p.parser.problem) > 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   130
		msg = p.parser.problem
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   131
	} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   132
		msg = "unknown problem parsing YAML content"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   133
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   134
	failf("%s%s", where, msg)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   135
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   136
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   137
func (p *parser) anchor(n *Node, anchor []byte) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   138
	if anchor != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   139
		n.Anchor = string(anchor)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   140
		p.anchors[n.Anchor] = n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   141
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   142
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   143
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   144
func (p *parser) parse() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   145
	p.init()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   146
	switch p.peek() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   147
	case yaml_SCALAR_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   148
		return p.scalar()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   149
	case yaml_ALIAS_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   150
		return p.alias()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   151
	case yaml_MAPPING_START_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   152
		return p.mapping()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   153
	case yaml_SEQUENCE_START_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   154
		return p.sequence()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   155
	case yaml_DOCUMENT_START_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   156
		return p.document()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   157
	case yaml_STREAM_END_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   158
		// Happens when attempting to decode an empty buffer.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   159
		return nil
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   160
	case yaml_TAIL_COMMENT_EVENT:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   161
		panic("internal error: unexpected tail comment event (please report)")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   162
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   163
		panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   164
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   165
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   166
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   167
func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   168
	var style Style
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   169
	if tag != "" && tag != "!" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   170
		tag = shortTag(tag)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   171
		style = TaggedStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   172
	} else if defaultTag != "" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   173
		tag = defaultTag
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   174
	} else if kind == ScalarNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   175
		tag, _ = resolve("", value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   176
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   177
	n := &Node{
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   178
		Kind:  kind,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   179
		Tag:   tag,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   180
		Value: value,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   181
		Style: style,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   182
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   183
	if !p.textless {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   184
		n.Line = p.event.start_mark.line + 1
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   185
		n.Column = p.event.start_mark.column + 1
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   186
		n.HeadComment = string(p.event.head_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   187
		n.LineComment = string(p.event.line_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   188
		n.FootComment = string(p.event.foot_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   189
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   190
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   191
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   192
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   193
func (p *parser) parseChild(parent *Node) *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   194
	child := p.parse()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   195
	parent.Content = append(parent.Content, child)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   196
	return child
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   197
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   198
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   199
func (p *parser) document() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   200
	n := p.node(DocumentNode, "", "", "")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   201
	p.doc = n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   202
	p.expect(yaml_DOCUMENT_START_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   203
	p.parseChild(n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   204
	if p.peek() == yaml_DOCUMENT_END_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   205
		n.FootComment = string(p.event.foot_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   206
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   207
	p.expect(yaml_DOCUMENT_END_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   208
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   209
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   210
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   211
func (p *parser) alias() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   212
	n := p.node(AliasNode, "", "", string(p.event.anchor))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   213
	n.Alias = p.anchors[n.Value]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   214
	if n.Alias == nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   215
		failf("unknown anchor '%s' referenced", n.Value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   216
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   217
	p.expect(yaml_ALIAS_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   218
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   219
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   220
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   221
func (p *parser) scalar() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   222
	var parsedStyle = p.event.scalar_style()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   223
	var nodeStyle Style
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   224
	switch {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   225
	case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   226
		nodeStyle = DoubleQuotedStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   227
	case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   228
		nodeStyle = SingleQuotedStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   229
	case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   230
		nodeStyle = LiteralStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   231
	case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   232
		nodeStyle = FoldedStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   233
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   234
	var nodeValue = string(p.event.value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   235
	var nodeTag = string(p.event.tag)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   236
	var defaultTag string
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   237
	if nodeStyle == 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   238
		if nodeValue == "<<" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   239
			defaultTag = mergeTag
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   240
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   241
	} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   242
		defaultTag = strTag
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   243
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   244
	n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   245
	n.Style |= nodeStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   246
	p.anchor(n, p.event.anchor)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   247
	p.expect(yaml_SCALAR_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   248
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   249
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   250
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   251
func (p *parser) sequence() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   252
	n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   253
	if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   254
		n.Style |= FlowStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   255
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   256
	p.anchor(n, p.event.anchor)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   257
	p.expect(yaml_SEQUENCE_START_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   258
	for p.peek() != yaml_SEQUENCE_END_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   259
		p.parseChild(n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   260
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   261
	n.LineComment = string(p.event.line_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   262
	n.FootComment = string(p.event.foot_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   263
	p.expect(yaml_SEQUENCE_END_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   264
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   265
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   266
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   267
func (p *parser) mapping() *Node {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   268
	n := p.node(MappingNode, mapTag, string(p.event.tag), "")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   269
	block := true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   270
	if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   271
		block = false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   272
		n.Style |= FlowStyle
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   273
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   274
	p.anchor(n, p.event.anchor)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   275
	p.expect(yaml_MAPPING_START_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   276
	for p.peek() != yaml_MAPPING_END_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   277
		k := p.parseChild(n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   278
		if block && k.FootComment != "" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   279
			// Must be a foot comment for the prior value when being dedented.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   280
			if len(n.Content) > 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   281
				n.Content[len(n.Content)-3].FootComment = k.FootComment
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   282
				k.FootComment = ""
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   283
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   284
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   285
		v := p.parseChild(n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   286
		if k.FootComment == "" && v.FootComment != "" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   287
			k.FootComment = v.FootComment
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   288
			v.FootComment = ""
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   289
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   290
		if p.peek() == yaml_TAIL_COMMENT_EVENT {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   291
			if k.FootComment == "" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   292
				k.FootComment = string(p.event.foot_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   293
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   294
			p.expect(yaml_TAIL_COMMENT_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   295
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   296
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   297
	n.LineComment = string(p.event.line_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   298
	n.FootComment = string(p.event.foot_comment)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   299
	if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   300
		n.Content[len(n.Content)-2].FootComment = n.FootComment
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   301
		n.FootComment = ""
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   302
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   303
	p.expect(yaml_MAPPING_END_EVENT)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   304
	return n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   305
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   306
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   307
// ----------------------------------------------------------------------------
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   308
// Decoder, unmarshals a node into a provided value.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   309
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   310
type decoder struct {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   311
	doc     *Node
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   312
	aliases map[*Node]bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   313
	terrors []string
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   314
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   315
	stringMapType  reflect.Type
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   316
	generalMapType reflect.Type
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   317
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   318
	knownFields bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   319
	uniqueKeys  bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   320
	decodeCount int
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   321
	aliasCount  int
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   322
	aliasDepth  int
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   323
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   324
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   325
var (
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   326
	nodeType       = reflect.TypeOf(Node{})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   327
	durationType   = reflect.TypeOf(time.Duration(0))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   328
	stringMapType  = reflect.TypeOf(map[string]interface{}{})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   329
	generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   330
	ifaceType      = generalMapType.Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   331
	timeType       = reflect.TypeOf(time.Time{})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   332
	ptrTimeType    = reflect.TypeOf(&time.Time{})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   333
)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   334
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   335
func newDecoder() *decoder {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   336
	d := &decoder{
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   337
		stringMapType:  stringMapType,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   338
		generalMapType: generalMapType,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   339
		uniqueKeys:     true,
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   340
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   341
	d.aliases = make(map[*Node]bool)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   342
	return d
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   343
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   344
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   345
func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   346
	if n.Tag != "" {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   347
		tag = n.Tag
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   348
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   349
	value := n.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   350
	if tag != seqTag && tag != mapTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   351
		if len(value) > 10 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   352
			value = " `" + value[:7] + "...`"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   353
		} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   354
			value = " `" + value + "`"
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   355
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   356
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   357
	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   358
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   359
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   360
func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   361
	err := u.UnmarshalYAML(n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   362
	if e, ok := err.(*TypeError); ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   363
		d.terrors = append(d.terrors, e.Errors...)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   364
		return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   365
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   366
	if err != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   367
		fail(err)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   368
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   369
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   370
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   371
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   372
func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   373
	terrlen := len(d.terrors)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   374
	err := u.UnmarshalYAML(func(v interface{}) (err error) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   375
		defer handleErr(&err)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   376
		d.unmarshal(n, reflect.ValueOf(v))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   377
		if len(d.terrors) > terrlen {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   378
			issues := d.terrors[terrlen:]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   379
			d.terrors = d.terrors[:terrlen]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   380
			return &TypeError{issues}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   381
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   382
		return nil
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   383
	})
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   384
	if e, ok := err.(*TypeError); ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   385
		d.terrors = append(d.terrors, e.Errors...)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   386
		return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   387
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   388
	if err != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   389
		fail(err)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   390
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   391
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   392
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   393
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   394
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   395
// if a value is found to implement it.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   396
// It returns the initialized and dereferenced out value, whether
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   397
// unmarshalling was already done by UnmarshalYAML, and if so whether
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   398
// its types unmarshalled appropriately.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   399
//
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   400
// If n holds a null value, prepare returns before doing anything.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   401
func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   402
	if n.ShortTag() == nullTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   403
		return out, false, false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   404
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   405
	again := true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   406
	for again {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   407
		again = false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   408
		if out.Kind() == reflect.Ptr {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   409
			if out.IsNil() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   410
				out.Set(reflect.New(out.Type().Elem()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   411
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   412
			out = out.Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   413
			again = true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   414
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   415
		if out.CanAddr() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   416
			outi := out.Addr().Interface()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   417
			if u, ok := outi.(Unmarshaler); ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   418
				good = d.callUnmarshaler(n, u)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   419
				return out, true, good
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   420
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   421
			if u, ok := outi.(obsoleteUnmarshaler); ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   422
				good = d.callObsoleteUnmarshaler(n, u)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   423
				return out, true, good
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   424
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   425
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   426
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   427
	return out, false, false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   428
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   429
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   430
func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   431
	if n.ShortTag() == nullTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   432
		return reflect.Value{}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   433
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   434
	for _, num := range index {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   435
		for {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   436
			if v.Kind() == reflect.Ptr {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   437
				if v.IsNil() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   438
					v.Set(reflect.New(v.Type().Elem()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   439
				}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   440
				v = v.Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   441
				continue
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   442
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   443
			break
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   444
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   445
		v = v.Field(num)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   446
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   447
	return v
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   448
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   449
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   450
const (
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   451
	// 400,000 decode operations is ~500kb of dense object declarations, or
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   452
	// ~5kb of dense object declarations with 10000% alias expansion
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   453
	alias_ratio_range_low = 400000
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   454
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   455
	// 4,000,000 decode operations is ~5MB of dense object declarations, or
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   456
	// ~4.5MB of dense object declarations with 10% alias expansion
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   457
	alias_ratio_range_high = 4000000
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   458
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   459
	// alias_ratio_range is the range over which we scale allowed alias ratios
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   460
	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   461
)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   462
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   463
func allowedAliasRatio(decodeCount int) float64 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   464
	switch {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   465
	case decodeCount <= alias_ratio_range_low:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   466
		// allow 99% to come from alias expansion for small-to-medium documents
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   467
		return 0.99
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   468
	case decodeCount >= alias_ratio_range_high:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   469
		// allow 10% to come from alias expansion for very large documents
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   470
		return 0.10
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   471
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   472
		// scale smoothly from 99% down to 10% over the range.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   473
		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   474
		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   475
		return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   476
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   477
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   478
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   479
func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   480
	d.decodeCount++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   481
	if d.aliasDepth > 0 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   482
		d.aliasCount++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   483
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   484
	if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   485
		failf("document contains excessive aliasing")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   486
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   487
	if out.Type() == nodeType {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   488
		out.Set(reflect.ValueOf(n).Elem())
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   489
		return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   490
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   491
	switch n.Kind {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   492
	case DocumentNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   493
		return d.document(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   494
	case AliasNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   495
		return d.alias(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   496
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   497
	out, unmarshaled, good := d.prepare(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   498
	if unmarshaled {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   499
		return good
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   500
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   501
	switch n.Kind {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   502
	case ScalarNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   503
		good = d.scalar(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   504
	case MappingNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   505
		good = d.mapping(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   506
	case SequenceNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   507
		good = d.sequence(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   508
	case 0:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   509
		if n.IsZero() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   510
			return d.null(out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   511
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   512
		fallthrough
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   513
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   514
		failf("cannot decode node with unknown kind %d", n.Kind)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   515
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   516
	return good
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   517
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   518
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   519
func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   520
	if len(n.Content) == 1 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   521
		d.doc = n
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   522
		d.unmarshal(n.Content[0], out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   523
		return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   524
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   525
	return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   526
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   527
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   528
func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   529
	if d.aliases[n] {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   530
		// TODO this could actually be allowed in some circumstances.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   531
		failf("anchor '%s' value contains itself", n.Value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   532
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   533
	d.aliases[n] = true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   534
	d.aliasDepth++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   535
	good = d.unmarshal(n.Alias, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   536
	d.aliasDepth--
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   537
	delete(d.aliases, n)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   538
	return good
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   539
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   540
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   541
var zeroValue reflect.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   542
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   543
func resetMap(out reflect.Value) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   544
	for _, k := range out.MapKeys() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   545
		out.SetMapIndex(k, zeroValue)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   546
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   547
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   548
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   549
func (d *decoder) null(out reflect.Value) bool {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   550
	if out.CanAddr() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   551
		switch out.Kind() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   552
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   553
			out.Set(reflect.Zero(out.Type()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   554
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   555
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   556
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   557
	return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   558
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   559
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   560
func (d *decoder) scalar(n *Node, out reflect.Value) bool {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   561
	var tag string
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   562
	var resolved interface{}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   563
	if n.indicatedString() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   564
		tag = strTag
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   565
		resolved = n.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   566
	} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   567
		tag, resolved = resolve(n.Tag, n.Value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   568
		if tag == binaryTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   569
			data, err := base64.StdEncoding.DecodeString(resolved.(string))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   570
			if err != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   571
				failf("!!binary value contains invalid base64 data")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   572
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   573
			resolved = string(data)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   574
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   575
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   576
	if resolved == nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   577
		return d.null(out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   578
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   579
	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   580
		// We've resolved to exactly the type we want, so use that.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   581
		out.Set(resolvedv)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   582
		return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   583
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   584
	// Perhaps we can use the value as a TextUnmarshaler to
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   585
	// set its value.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   586
	if out.CanAddr() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   587
		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   588
		if ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   589
			var text []byte
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   590
			if tag == binaryTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   591
				text = []byte(resolved.(string))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   592
			} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   593
				// We let any value be unmarshaled into TextUnmarshaler.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   594
				// That might be more lax than we'd like, but the
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   595
				// TextUnmarshaler itself should bowl out any dubious values.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   596
				text = []byte(n.Value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   597
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   598
			err := u.UnmarshalText(text)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   599
			if err != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   600
				fail(err)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   601
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   602
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   603
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   604
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   605
	switch out.Kind() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   606
	case reflect.String:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   607
		if tag == binaryTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   608
			out.SetString(resolved.(string))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   609
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   610
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   611
		out.SetString(n.Value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   612
		return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   613
	case reflect.Interface:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   614
		out.Set(reflect.ValueOf(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   615
		return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   616
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   617
		// This used to work in v2, but it's very unfriendly.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   618
		isDuration := out.Type() == durationType
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   619
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   620
		switch resolved := resolved.(type) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   621
		case int:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   622
			if !isDuration && !out.OverflowInt(int64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   623
				out.SetInt(int64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   624
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   625
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   626
		case int64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   627
			if !isDuration && !out.OverflowInt(resolved) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   628
				out.SetInt(resolved)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   629
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   630
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   631
		case uint64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   632
			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   633
				out.SetInt(int64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   634
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   635
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   636
		case float64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   637
			if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   638
				out.SetInt(int64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   639
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   640
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   641
		case string:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   642
			if out.Type() == durationType {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   643
				d, err := time.ParseDuration(resolved)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   644
				if err == nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   645
					out.SetInt(int64(d))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   646
					return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   647
				}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   648
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   649
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   650
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   651
		switch resolved := resolved.(type) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   652
		case int:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   653
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   654
				out.SetUint(uint64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   655
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   656
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   657
		case int64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   658
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   659
				out.SetUint(uint64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   660
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   661
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   662
		case uint64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   663
			if !out.OverflowUint(uint64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   664
				out.SetUint(uint64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   665
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   666
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   667
		case float64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   668
			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   669
				out.SetUint(uint64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   670
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   671
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   672
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   673
	case reflect.Bool:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   674
		switch resolved := resolved.(type) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   675
		case bool:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   676
			out.SetBool(resolved)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   677
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   678
		case string:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   679
			// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   680
			// It only works if explicitly attempting to unmarshal into a typed bool value.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   681
			switch resolved {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   682
			case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   683
				out.SetBool(true)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   684
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   685
			case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   686
				out.SetBool(false)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   687
				return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   688
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   689
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   690
	case reflect.Float32, reflect.Float64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   691
		switch resolved := resolved.(type) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   692
		case int:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   693
			out.SetFloat(float64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   694
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   695
		case int64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   696
			out.SetFloat(float64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   697
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   698
		case uint64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   699
			out.SetFloat(float64(resolved))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   700
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   701
		case float64:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   702
			out.SetFloat(resolved)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   703
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   704
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   705
	case reflect.Struct:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   706
		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   707
			out.Set(resolvedv)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   708
			return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   709
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   710
	case reflect.Ptr:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   711
		panic("yaml internal error: please report the issue")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   712
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   713
	d.terror(n, tag, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   714
	return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   715
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   716
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   717
func settableValueOf(i interface{}) reflect.Value {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   718
	v := reflect.ValueOf(i)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   719
	sv := reflect.New(v.Type()).Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   720
	sv.Set(v)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   721
	return sv
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   722
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   723
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   724
func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   725
	l := len(n.Content)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   726
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   727
	var iface reflect.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   728
	switch out.Kind() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   729
	case reflect.Slice:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   730
		out.Set(reflect.MakeSlice(out.Type(), l, l))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   731
	case reflect.Array:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   732
		if l != out.Len() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   733
			failf("invalid array: want %d elements but got %d", out.Len(), l)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   734
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   735
	case reflect.Interface:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   736
		// No type hints. Will have to use a generic sequence.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   737
		iface = out
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   738
		out = settableValueOf(make([]interface{}, l))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   739
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   740
		d.terror(n, seqTag, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   741
		return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   742
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   743
	et := out.Type().Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   744
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   745
	j := 0
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   746
	for i := 0; i < l; i++ {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   747
		e := reflect.New(et).Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   748
		if ok := d.unmarshal(n.Content[i], e); ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   749
			out.Index(j).Set(e)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   750
			j++
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   751
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   752
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   753
	if out.Kind() != reflect.Array {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   754
		out.Set(out.Slice(0, j))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   755
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   756
	if iface.IsValid() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   757
		iface.Set(out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   758
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   759
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   760
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   761
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   762
func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   763
	l := len(n.Content)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   764
	if d.uniqueKeys {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   765
		nerrs := len(d.terrors)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   766
		for i := 0; i < l; i += 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   767
			ni := n.Content[i]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   768
			for j := i + 2; j < l; j += 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   769
				nj := n.Content[j]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   770
				if ni.Kind == nj.Kind && ni.Value == nj.Value {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   771
					d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   772
				}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   773
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   774
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   775
		if len(d.terrors) > nerrs {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   776
			return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   777
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   778
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   779
	switch out.Kind() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   780
	case reflect.Struct:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   781
		return d.mappingStruct(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   782
	case reflect.Map:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   783
		// okay
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   784
	case reflect.Interface:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   785
		iface := out
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   786
		if isStringMap(n) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   787
			out = reflect.MakeMap(d.stringMapType)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   788
		} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   789
			out = reflect.MakeMap(d.generalMapType)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   790
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   791
		iface.Set(out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   792
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   793
		d.terror(n, mapTag, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   794
		return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   795
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   796
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   797
	outt := out.Type()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   798
	kt := outt.Key()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   799
	et := outt.Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   800
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   801
	stringMapType := d.stringMapType
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   802
	generalMapType := d.generalMapType
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   803
	if outt.Elem() == ifaceType {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   804
		if outt.Key().Kind() == reflect.String {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   805
			d.stringMapType = outt
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   806
		} else if outt.Key() == ifaceType {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   807
			d.generalMapType = outt
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   808
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   809
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   810
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   811
	mapIsNew := false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   812
	if out.IsNil() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   813
		out.Set(reflect.MakeMap(outt))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   814
		mapIsNew = true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   815
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   816
	for i := 0; i < l; i += 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   817
		if isMerge(n.Content[i]) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   818
			d.merge(n.Content[i+1], out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   819
			continue
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   820
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   821
		k := reflect.New(kt).Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   822
		if d.unmarshal(n.Content[i], k) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   823
			kkind := k.Kind()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   824
			if kkind == reflect.Interface {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   825
				kkind = k.Elem().Kind()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   826
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   827
			if kkind == reflect.Map || kkind == reflect.Slice {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   828
				failf("invalid map key: %#v", k.Interface())
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   829
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   830
			e := reflect.New(et).Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   831
			if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   832
				out.SetMapIndex(k, e)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   833
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   834
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   835
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   836
	d.stringMapType = stringMapType
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   837
	d.generalMapType = generalMapType
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   838
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   839
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   840
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   841
func isStringMap(n *Node) bool {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   842
	if n.Kind != MappingNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   843
		return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   844
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   845
	l := len(n.Content)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   846
	for i := 0; i < l; i += 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   847
		if n.Content[i].ShortTag() != strTag {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   848
			return false
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   849
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   850
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   851
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   852
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   853
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   854
func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   855
	sinfo, err := getStructInfo(out.Type())
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   856
	if err != nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   857
		panic(err)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   858
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   859
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   860
	var inlineMap reflect.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   861
	var elemType reflect.Type
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   862
	if sinfo.InlineMap != -1 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   863
		inlineMap = out.Field(sinfo.InlineMap)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   864
		inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   865
		elemType = inlineMap.Type().Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   866
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   867
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   868
	for _, index := range sinfo.InlineUnmarshalers {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   869
		field := d.fieldByIndex(n, out, index)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   870
		d.prepare(n, field)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   871
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   872
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   873
	var doneFields []bool
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   874
	if d.uniqueKeys {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   875
		doneFields = make([]bool, len(sinfo.FieldsList))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   876
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   877
	name := settableValueOf("")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   878
	l := len(n.Content)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   879
	for i := 0; i < l; i += 2 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   880
		ni := n.Content[i]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   881
		if isMerge(ni) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   882
			d.merge(n.Content[i+1], out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   883
			continue
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   884
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   885
		if !d.unmarshal(ni, name) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   886
			continue
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   887
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   888
		if info, ok := sinfo.FieldsMap[name.String()]; ok {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   889
			if d.uniqueKeys {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   890
				if doneFields[info.Id] {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   891
					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   892
					continue
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   893
				}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   894
				doneFields[info.Id] = true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   895
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   896
			var field reflect.Value
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   897
			if info.Inline == nil {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   898
				field = out.Field(info.Num)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   899
			} else {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   900
				field = d.fieldByIndex(n, out, info.Inline)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   901
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   902
			d.unmarshal(n.Content[i+1], field)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   903
		} else if sinfo.InlineMap != -1 {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   904
			if inlineMap.IsNil() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   905
				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   906
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   907
			value := reflect.New(elemType).Elem()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   908
			d.unmarshal(n.Content[i+1], value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   909
			inlineMap.SetMapIndex(name, value)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   910
		} else if d.knownFields {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   911
			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   912
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   913
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   914
	return true
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   915
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   916
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   917
func failWantMap() {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   918
	failf("map merge requires map or sequence of maps as the value")
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   919
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   920
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   921
func (d *decoder) merge(n *Node, out reflect.Value) {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   922
	switch n.Kind {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   923
	case MappingNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   924
		d.unmarshal(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   925
	case AliasNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   926
		if n.Alias != nil && n.Alias.Kind != MappingNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   927
			failWantMap()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   928
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   929
		d.unmarshal(n, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   930
	case SequenceNode:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   931
		// Step backwards as earlier nodes take precedence.
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   932
		for i := len(n.Content) - 1; i >= 0; i-- {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   933
			ni := n.Content[i]
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   934
			if ni.Kind == AliasNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   935
				if ni.Alias != nil && ni.Alias.Kind != MappingNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   936
					failWantMap()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   937
				}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   938
			} else if ni.Kind != MappingNode {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   939
				failWantMap()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   940
			}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   941
			d.unmarshal(ni, out)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   942
		}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   943
	default:
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   944
		failWantMap()
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   945
	}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   946
}
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   947
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   948
func isMerge(n *Node) bool {
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   949
	return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
6d9efbef00a9 Update dependencies
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   950
}