yaml/decode.go

539 строки
12 KiB
Go
Исходник Обычный вид История

2014-03-05 22:48:33 +04:00
package yaml
2011-01-05 16:17:34 +03:00
import (
2011-04-14 01:20:44 +04:00
"reflect"
"strconv"
2014-04-06 17:56:05 +04:00
"time"
2011-01-05 16:17:34 +03:00
)
const (
2011-04-14 01:20:44 +04:00
documentNode = 1 << iota
mappingNode
sequenceNode
scalarNode
aliasNode
)
2011-01-05 16:17:34 +03:00
type node struct {
2011-04-14 01:20:44 +04:00
kind int
line, column int
tag string
value string
implicit bool
children []*node
anchors map[string]*node
}
// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.
type parser struct {
2013-04-25 23:24:26 +04:00
parser yaml_parser_t
event yaml_event_t
2011-04-14 01:20:44 +04:00
doc *node
2011-01-05 16:17:34 +03:00
}
func newParser(b []byte) *parser {
2011-04-14 01:20:44 +04:00
p := parser{}
2013-04-25 23:24:26 +04:00
if !yaml_parser_initialize(&p.parser) {
2011-04-14 01:20:44 +04:00
panic("Failed to initialize YAML emitter")
}
if len(b) == 0 {
b = []byte{'\n'}
}
2013-04-25 23:24:26 +04:00
yaml_parser_set_input_string(&p.parser, b)
2011-04-14 01:20:44 +04:00
p.skip()
2013-04-25 23:24:26 +04:00
if p.event.typ != yaml_STREAM_START_EVENT {
panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
2011-04-14 01:20:44 +04:00
}
p.skip()
return &p
2011-01-05 16:17:34 +03:00
}
func (p *parser) destroy() {
2013-04-25 23:24:26 +04:00
if p.event.typ != yaml_NO_EVENT {
yaml_event_delete(&p.event)
2011-04-14 01:20:44 +04:00
}
2013-04-25 23:24:26 +04:00
yaml_parser_delete(&p.parser)
2011-01-05 16:17:34 +03:00
}
func (p *parser) skip() {
2013-04-25 23:24:26 +04:00
if p.event.typ != yaml_NO_EVENT {
if p.event.typ == yaml_STREAM_END_EVENT {
2011-04-14 01:20:44 +04:00
panic("Attempted to go past the end of stream. Corrupted value?")
}
2013-04-25 23:24:26 +04:00
yaml_event_delete(&p.event)
2011-04-14 01:20:44 +04:00
}
2013-04-25 23:24:26 +04:00
if !yaml_parser_parse(&p.parser, &p.event) {
2011-04-14 01:20:44 +04:00
p.fail()
}
2011-01-10 21:03:42 +03:00
}
func (p *parser) fail() {
2011-04-14 01:20:44 +04:00
var where string
var line int
if p.parser.problem_mark.line != 0 {
2013-04-25 23:24:26 +04:00
line = p.parser.problem_mark.line
2011-04-14 01:20:44 +04:00
} else if p.parser.context_mark.line != 0 {
2013-04-25 23:24:26 +04:00
line = p.parser.context_mark.line
2011-04-14 01:20:44 +04:00
}
if line != 0 {
where = "line " + strconv.Itoa(line) + ": "
}
var msg string
2013-04-25 23:24:26 +04:00
if len(p.parser.problem) > 0 {
msg = p.parser.problem
2011-04-14 01:20:44 +04:00
} else {
msg = "Unknown problem parsing YAML content"
}
panic(where + msg)
2011-01-05 16:17:34 +03:00
}
2013-04-25 23:24:26 +04:00
func (p *parser) anchor(n *node, anchor []byte) {
2011-04-14 01:20:44 +04:00
if anchor != nil {
2013-04-25 23:24:26 +04:00
p.doc.anchors[string(anchor)] = n
2011-04-14 01:20:44 +04:00
}
}
func (p *parser) parse() *node {
2013-04-25 23:24:26 +04:00
switch p.event.typ {
case yaml_SCALAR_EVENT:
2011-04-14 01:20:44 +04:00
return p.scalar()
2013-04-25 23:24:26 +04:00
case yaml_ALIAS_EVENT:
2011-04-14 01:20:44 +04:00
return p.alias()
2013-04-25 23:24:26 +04:00
case yaml_MAPPING_START_EVENT:
2011-04-14 01:20:44 +04:00
return p.mapping()
2013-04-25 23:24:26 +04:00
case yaml_SEQUENCE_START_EVENT:
2011-04-14 01:20:44 +04:00
return p.sequence()
2013-04-25 23:24:26 +04:00
case yaml_DOCUMENT_START_EVENT:
2011-04-14 01:20:44 +04:00
return p.document()
2013-04-25 23:24:26 +04:00
case yaml_STREAM_END_EVENT:
2011-04-14 01:20:44 +04:00
// Happens when attempting to decode an empty buffer.
return nil
default:
panic("Attempted to parse unknown event: " +
2013-04-25 23:24:26 +04:00
strconv.Itoa(int(p.event.typ)))
2011-04-14 01:20:44 +04:00
}
panic("Unreachable")
}
func (p *parser) node(kind int) *node {
2013-04-25 23:24:26 +04:00
return &node{
kind: kind,
line: p.event.start_mark.line,
column: p.event.start_mark.column,
}
}
func (p *parser) document() *node {
2011-04-14 01:20:44 +04:00
n := p.node(documentNode)
n.anchors = make(map[string]*node)
p.doc = n
p.skip()
n.children = append(n.children, p.parse())
2013-04-25 23:24:26 +04:00
if p.event.typ != yaml_DOCUMENT_END_EVENT {
2011-04-14 01:20:44 +04:00
panic("Expected end of document event but got " +
2013-04-25 23:24:26 +04:00
strconv.Itoa(int(p.event.typ)))
2011-04-14 01:20:44 +04:00
}
p.skip()
return n
2011-01-05 16:17:34 +03:00
}
func (p *parser) alias() *node {
2011-04-14 01:20:44 +04:00
n := p.node(aliasNode)
n.value = string(p.event.anchor)
2011-04-14 01:20:44 +04:00
p.skip()
return n
}
func (p *parser) scalar() *node {
2011-04-14 01:20:44 +04:00
n := p.node(scalarNode)
n.value = string(p.event.value)
n.tag = string(p.event.tag)
n.implicit = p.event.implicit
p.anchor(n, p.event.anchor)
2011-04-14 01:20:44 +04:00
p.skip()
return n
}
2011-01-05 20:29:30 +03:00
func (p *parser) sequence() *node {
2011-04-14 01:20:44 +04:00
n := p.node(sequenceNode)
p.anchor(n, p.event.anchor)
2011-04-14 01:20:44 +04:00
p.skip()
2013-04-25 23:24:26 +04:00
for p.event.typ != yaml_SEQUENCE_END_EVENT {
2011-04-14 01:20:44 +04:00
n.children = append(n.children, p.parse())
}
p.skip()
return n
}
func (p *parser) mapping() *node {
2011-04-14 01:20:44 +04:00
n := p.node(mappingNode)
p.anchor(n, p.event.anchor)
2011-04-14 01:20:44 +04:00
p.skip()
2013-04-25 23:24:26 +04:00
for p.event.typ != yaml_MAPPING_END_EVENT {
2011-04-14 01:20:44 +04:00
n.children = append(n.children, p.parse(), p.parse())
}
p.skip()
return n
}
// ----------------------------------------------------------------------------
// Decoder, unmarshals a node into a provided value.
type decoder struct {
2011-04-14 01:20:44 +04:00
doc *node
aliases map[string]bool
}
func newDecoder() *decoder {
2011-04-14 01:20:44 +04:00
d := &decoder{}
d.aliases = make(map[string]bool)
return d
2011-01-05 20:29:30 +03:00
}
// d.setter deals with setters and pointer dereferencing and initialization.
//
// It's a slightly convoluted case to handle properly:
//
2011-12-20 17:31:40 +04:00
// - nil pointers should be initialized, unless being set to nil
// - we don't know at this point yet what's the value to SetYAML() with.
// - we can't separate pointer deref/init and setter checking, because
// a setter may be found while going down a pointer chain.
//
// Thus, here is how it takes care of it:
//
// - out is provided as a pointer, so that it can be replaced.
// - when looking at a non-setter ptr, *out=ptr.Elem(), unless tag=!!null
// - when a setter is found, *out=interface{}, and a set() function is
// returned to call SetYAML() with the value of *out once it's defined.
//
func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) {
if (*out).Kind() != reflect.Ptr && (*out).CanAddr() {
setter, _ := (*out).Addr().Interface().(Setter)
if setter != nil {
var arg interface{}
*out = reflect.ValueOf(&arg).Elem()
return func() {
*good = setter.SetYAML(tag, arg)
}
}
}
2011-04-14 01:20:44 +04:00
again := true
for again {
again = false
setter, _ := (*out).Interface().(Setter)
if tag != "!!null" || setter != nil {
2011-04-15 08:23:17 +04:00
if pv := (*out); pv.Kind() == reflect.Ptr {
2011-04-14 01:20:44 +04:00
if pv.IsNil() {
2011-04-28 16:55:23 +04:00
*out = reflect.New(pv.Type().Elem()).Elem()
2011-04-15 08:23:17 +04:00
pv.Set((*out).Addr())
2011-04-14 01:20:44 +04:00
} else {
*out = pv.Elem()
}
setter, _ = pv.Interface().(Setter)
again = true
}
}
if setter != nil {
var arg interface{}
2011-04-28 16:55:23 +04:00
*out = reflect.ValueOf(&arg).Elem()
2011-04-14 01:20:44 +04:00
return func() {
*good = setter.SetYAML(tag, arg)
}
}
}
return nil
}
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
switch n.kind {
case documentNode:
good = d.document(n, out)
case scalarNode:
good = d.scalar(n, out)
case aliasNode:
good = d.alias(n, out)
case mappingNode:
good = d.mapping(n, out)
case sequenceNode:
good = d.sequence(n, out)
default:
panic("Internal error: unknown node kind: " + strconv.Itoa(n.kind))
}
return
2011-01-05 16:17:34 +03:00
}
func (d *decoder) document(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
if len(n.children) == 1 {
d.doc = n
d.unmarshal(n.children[0], out)
return true
}
return false
}
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
an, ok := d.doc.anchors[n.value]
if !ok {
panic("Unknown anchor '" + n.value + "' referenced")
}
if d.aliases[n.value] {
panic("Anchor '" + n.value + "' value contains itself")
}
d.aliases[n.value] = true
good = d.unmarshal(an, out)
2011-11-24 23:47:20 +04:00
delete(d.aliases, n.value)
2011-04-14 01:20:44 +04:00
return good
2011-01-05 16:17:34 +03:00
}
2014-04-06 17:56:05 +04:00
var durationType = reflect.TypeOf(time.Duration(0))
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
var tag string
var resolved interface{}
if n.tag == "" && !n.implicit {
tag = "!!str"
2011-04-14 01:20:44 +04:00
resolved = n.value
} else {
tag, resolved = resolve(n.tag, n.value)
}
if set := d.setter(tag, &out, &good); set != nil {
defer set()
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
switch out.Kind() {
case reflect.String:
if resolved != nil {
out.SetString(n.value)
good = true
}
2011-04-15 08:23:17 +04:00
case reflect.Interface:
if resolved == nil {
out.Set(reflect.Zero(out.Type()))
} else {
2011-04-28 16:55:23 +04:00
out.Set(reflect.ValueOf(resolved))
2011-04-15 08:23:17 +04:00
}
2011-04-14 01:20:44 +04:00
good = true
2011-04-15 08:23:17 +04:00
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
2011-04-14 01:20:44 +04:00
switch resolved := resolved.(type) {
case int:
2011-04-15 08:23:17 +04:00
if !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
2011-04-14 01:20:44 +04:00
good = true
}
case int64:
2011-04-15 08:23:17 +04:00
if !out.OverflowInt(resolved) {
out.SetInt(resolved)
2011-04-14 01:20:44 +04:00
good = true
}
case float64:
if resolved < 1<<63-1 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
good = true
}
2014-04-06 17:56:05 +04:00
case string:
if out.Type() == durationType {
d, err := time.ParseDuration(resolved)
if err == nil {
out.SetInt(int64(d))
good = true
}
}
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
2011-04-14 01:20:44 +04:00
switch resolved := resolved.(type) {
case int:
if resolved >= 0 {
2011-04-15 08:23:17 +04:00
out.SetUint(uint64(resolved))
2011-04-14 01:20:44 +04:00
good = true
}
case int64:
if resolved >= 0 {
2011-04-15 08:23:17 +04:00
out.SetUint(uint64(resolved))
2011-04-14 01:20:44 +04:00
good = true
}
case float64:
if resolved < 1<<64-1 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
good = true
}
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
case reflect.Bool:
2011-04-14 01:20:44 +04:00
switch resolved := resolved.(type) {
case bool:
2011-04-15 08:23:17 +04:00
out.SetBool(resolved)
2011-04-14 01:20:44 +04:00
good = true
}
2011-04-15 08:23:17 +04:00
case reflect.Float32, reflect.Float64:
2011-04-14 01:20:44 +04:00
switch resolved := resolved.(type) {
case int:
out.SetFloat(float64(resolved))
good = true
case int64:
out.SetFloat(float64(resolved))
good = true
2011-04-14 01:20:44 +04:00
case float64:
2011-04-15 08:23:17 +04:00
out.SetFloat(resolved)
2011-04-14 01:20:44 +04:00
good = true
}
2011-04-15 08:23:17 +04:00
case reflect.Ptr:
2011-11-24 23:47:20 +04:00
switch resolved.(type) {
2011-04-14 01:20:44 +04:00
case nil:
2011-04-15 08:23:17 +04:00
out.Set(reflect.Zero(out.Type()))
2011-04-14 01:20:44 +04:00
good = true
default:
if out.Type().Elem() == reflect.TypeOf(resolved) {
elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved))
out.Set(elem)
good = true
}
2011-04-14 01:20:44 +04:00
}
}
return good
2011-01-05 16:17:34 +03:00
}
2011-04-28 16:55:23 +04:00
func settableValueOf(i interface{}) reflect.Value {
v := reflect.ValueOf(i)
sv := reflect.New(v.Type()).Elem()
sv.Set(v)
return sv
}
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
if set := d.setter("!!seq", &out, &good); set != nil {
defer set()
}
var iface reflect.Value
2011-04-15 08:23:17 +04:00
if out.Kind() == reflect.Interface {
2011-04-14 01:20:44 +04:00
// No type hints. Will have to use a generic sequence.
iface = out
2011-04-28 16:55:23 +04:00
out = settableValueOf(make([]interface{}, 0))
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
if out.Kind() != reflect.Slice {
2011-04-14 01:20:44 +04:00
return false
}
2011-04-15 08:23:17 +04:00
et := out.Type().Elem()
2011-04-14 01:20:44 +04:00
l := len(n.children)
for i := 0; i < l; i++ {
2011-04-28 16:55:23 +04:00
e := reflect.New(et).Elem()
2011-04-14 01:20:44 +04:00
if ok := d.unmarshal(n.children[i], e); ok {
2011-04-15 08:23:17 +04:00
out.Set(reflect.Append(out, e))
2011-04-14 01:20:44 +04:00
}
}
if iface.IsValid() {
iface.Set(out)
}
2011-04-14 01:20:44 +04:00
return true
2011-01-05 16:17:34 +03:00
}
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
2011-04-14 01:20:44 +04:00
if set := d.setter("!!map", &out, &good); set != nil {
defer set()
}
2011-04-15 08:23:17 +04:00
if out.Kind() == reflect.Struct {
return d.mappingStruct(n, out)
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
if out.Kind() == reflect.Interface {
2011-04-14 01:20:44 +04:00
// No type hints. Will have to use a generic map.
2011-04-15 08:23:17 +04:00
iface := out
2011-04-28 16:55:23 +04:00
out = settableValueOf(make(map[interface{}]interface{}))
2011-04-15 08:23:17 +04:00
iface.Set(out)
2011-04-14 01:20:44 +04:00
}
2011-04-15 08:23:17 +04:00
if out.Kind() != reflect.Map {
2011-04-14 01:20:44 +04:00
return false
}
2011-04-15 08:23:17 +04:00
outt := out.Type()
kt := outt.Key()
et := outt.Elem()
2011-04-14 01:20:44 +04:00
2011-12-20 17:36:25 +04:00
if out.IsNil() {
out.Set(reflect.MakeMap(outt))
}
2011-04-14 01:20:44 +04:00
l := len(n.children)
for i := 0; i < l; i += 2 {
2014-04-12 00:06:50 +04:00
if isMerge(n.children[i]) {
d.merge(n.children[i+1], out)
continue
}
2011-04-28 16:55:23 +04:00
k := reflect.New(kt).Elem()
2011-04-14 01:20:44 +04:00
if d.unmarshal(n.children[i], k) {
2011-04-28 16:55:23 +04:00
e := reflect.New(et).Elem()
2011-04-14 01:20:44 +04:00
if d.unmarshal(n.children[i+1], e) {
2011-04-15 08:23:17 +04:00
out.SetMapIndex(k, e)
2011-04-14 01:20:44 +04:00
}
}
}
return true
2011-01-05 20:29:30 +03:00
}
2011-04-15 08:23:17 +04:00
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
sinfo, err := getStructInfo(out.Type())
2011-04-14 01:20:44 +04:00
if err != nil {
panic(err)
}
2011-04-28 16:55:23 +04:00
name := settableValueOf("")
2011-04-14 01:20:44 +04:00
l := len(n.children)
for i := 0; i < l; i += 2 {
2014-04-12 00:06:50 +04:00
ni := n.children[i]
if isMerge(ni) {
d.merge(n.children[i+1], out)
continue
}
if !d.unmarshal(ni, name) {
2011-04-14 01:20:44 +04:00
continue
}
if info, ok := sinfo.FieldsMap[name.String()]; ok {
var field reflect.Value
if info.Inline == nil {
field = out.Field(info.Num)
} else {
field = out.FieldByIndex(info.Inline)
}
d.unmarshal(n.children[i+1], field)
2011-04-14 01:20:44 +04:00
}
}
return true
2011-01-05 16:17:34 +03:00
}
2014-04-12 00:06:50 +04:00
func (d *decoder) merge(n *node, out reflect.Value) {
const wantMap = "map merge requires map or sequence of maps as the value"
switch n.kind {
case mappingNode:
d.unmarshal(n, out)
case aliasNode:
an, ok := d.doc.anchors[n.value]
if ok && an.kind != mappingNode {
panic(wantMap)
}
d.unmarshal(n, out)
case sequenceNode:
// Step backwards as earlier nodes take precedence.
for i := len(n.children)-1; i >= 0; i-- {
ni := n.children[i]
if ni.kind == aliasNode {
an, ok := d.doc.anchors[ni.value]
if ok && an.kind != mappingNode {
panic(wantMap)
}
} else if ni.kind != mappingNode {
panic(wantMap)
}
d.unmarshal(ni, out)
}
default:
panic(wantMap)
}
}
func isMerge(n *node) bool {
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == "!!merge" || n.tag == "tag:yaml.org,2002:merge")
}