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)
			}
		}
	}
	again := true
	for again {
		again = false
		setter, _ := (*out).Interface().(Setter)
		if tag != "!!null" || setter != nil {
			if pv := (*out); pv.Kind() == reflect.Ptr {
				if pv.IsNil() {
					*out = reflect.New(pv.Type().Elem()).Elem()
					pv.Set((*out).Addr())
				} else {
					*out = pv.Elem()
				}
				setter, _ = pv.Interface().(Setter)
				again = true
			}
		}
		if setter != nil {
			var arg interface{}
			*out = reflect.ValueOf(&arg).Elem()
			return func() {
				*good = setter.SetYAML(tag, arg)
			}
		}
	}
	return nil
}
d.setter deals with setters and pointer dereferencing and initialization.

It's a slightly convoluted case to handle properly:

- 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.
package yaml
import (
	"reflect"
	"strconv"
	"time"
)
const (
	documentNode = 1 << iota
	mappingNode
	sequenceNode
	scalarNode
	aliasNode
)
type node struct {
	kind         int
	line, column int
	tag          string
	value        string
	implicit     bool
	children     []*node
	anchors      map[string]*node
}
type parser struct {
	parser yaml_parser_t
	event  yaml_event_t
	doc    *node
}
func newParser(b []byte) *parser {
	p := parser{}
	if !yaml_parser_initialize(&p.parser) {
		panic("Failed to initialize YAML emitter")
	}
	if len(b) == 0 {
		b = []byte{'\n'}
	}
	yaml_parser_set_input_string(&p.parser, b)
	p.skip()
	if p.event.typ != yaml_STREAM_START_EVENT {
		panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
	}
	p.skip()
	return &p
}
func (p *parser) destroy() {
	if p.event.typ != yaml_NO_EVENT {
		yaml_event_delete(&p.event)
	}
	yaml_parser_delete(&p.parser)
}
func (p *parser) skip() {
	if p.event.typ != yaml_NO_EVENT {
		if p.event.typ == yaml_STREAM_END_EVENT {
			panic("Attempted to go past the end of stream. Corrupted value?")
		}
		yaml_event_delete(&p.event)
	}
	if !yaml_parser_parse(&p.parser, &p.event) {
		p.fail()
	}
}
func (p *parser) fail() {
	var where string
	var line int
	if p.parser.problem_mark.line != 0 {
		line = p.parser.problem_mark.line
	} else if p.parser.context_mark.line != 0 {
		line = p.parser.context_mark.line
	}
	if line != 0 {
		where = "line " + strconv.Itoa(line) + ": "
	}
	var msg string
	if len(p.parser.problem) > 0 {
		msg = p.parser.problem
	} else {
		msg = "Unknown problem parsing YAML content"
	}
	panic(where + msg)
}
func (p *parser) anchor(n *node, anchor []byte) {
	if anchor != nil {
		p.doc.anchors[string(anchor)] = n
	}
}
func (p *parser) parse() *node {
	switch p.event.typ {
	case yaml_SCALAR_EVENT:
		return p.scalar()
	case yaml_ALIAS_EVENT:
		return p.alias()
	case yaml_MAPPING_START_EVENT:
		return p.mapping()
	case yaml_SEQUENCE_START_EVENT:
		return p.sequence()
	case yaml_DOCUMENT_START_EVENT:
		return p.document()
	case yaml_STREAM_END_EVENT:
		return nil
	default:
		panic("Attempted to parse unknown event: " +
			strconv.Itoa(int(p.event.typ)))
	}
	panic("Unreachable")
}
func (p *parser) node(kind int) *node {
	return &node{
		kind:   kind,
		line:   p.event.start_mark.line,
		column: p.event.start_mark.column,
	}
}
func (p *parser) document() *node {
	n := p.node(documentNode)
	n.anchors = make(map[string]*node)
	p.doc = n
	p.skip()
	n.children = append(n.children, p.parse())
	if p.event.typ != yaml_DOCUMENT_END_EVENT {
		panic("Expected end of document event but got " +
			strconv.Itoa(int(p.event.typ)))
	}
	p.skip()
	return n
}
func (p *parser) alias() *node {
	n := p.node(aliasNode)
	n.value = string(p.event.anchor)
	p.skip()
	return n
}
func (p *parser) scalar() *node {
	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)
	p.skip()
	return n
}
func (p *parser) sequence() *node {
	n := p.node(sequenceNode)
	p.anchor(n, p.event.anchor)
	p.skip()
	for p.event.typ != yaml_SEQUENCE_END_EVENT {
		n.children = append(n.children, p.parse())
	}
	p.skip()
	return n
}
func (p *parser) mapping() *node {
	n := p.node(mappingNode)
	p.anchor(n, p.event.anchor)
	p.skip()
	for p.event.typ != yaml_MAPPING_END_EVENT {
		n.children = append(n.children, p.parse(), p.parse())
	}
	p.skip()
	return n
}
type decoder struct {
	doc     *node
	aliases map[string]bool
}
func newDecoder() *decoder {
	d := &decoder{}
	d.aliases = make(map[string]bool)
	return d
}