1package yamlpatch
2
3import "reflect"
4
5// Node holds a YAML document that has not yet been processed into a NodeMap or
6// NodeSlice
7type Node struct {
8	raw       *interface{}
9	container Container
10}
11
12// NewNode returns a new Node. It expects a pointer to an interface{}
13func NewNode(raw *interface{}) *Node {
14	return &Node{
15		raw: raw,
16	}
17}
18
19// MarshalYAML implements yaml.Marshaler, and returns the correct interface{}
20// to be marshaled
21func (n *Node) MarshalYAML() (interface{}, error) {
22	if n.container != nil {
23		return n.container, nil
24	}
25
26	return *n.raw, nil
27}
28
29// UnmarshalYAML implements yaml.Unmarshaler
30func (n *Node) UnmarshalYAML(unmarshal func(interface{}) error) error {
31	var data interface{}
32
33	err := unmarshal(&data)
34	if err != nil {
35		return err
36	}
37
38	n.raw = &data
39	return nil
40}
41
42// Empty returns whether the raw value is nil
43func (n *Node) Empty() bool {
44	return *n.raw == nil
45}
46
47// Container returns the node as a Container
48func (n *Node) Container() Container {
49	if n.container != nil {
50		return n.container
51	}
52
53	switch rt := (*n.raw).(type) {
54	case []interface{}:
55		c := make(nodeSlice, len(rt))
56		n.container = &c
57
58		for i := range rt {
59			c[i] = NewNode(&rt[i])
60		}
61	case map[interface{}]interface{}:
62		c := make(nodeMap, len(rt))
63		n.container = &c
64
65		for k := range rt {
66			v := rt[k]
67			c[k] = NewNode(&v)
68		}
69	}
70
71	return n.container
72}
73
74// Equal compares the values of the raw interfaces that the YAML was
75// unmarshaled into
76func (n *Node) Equal(other *Node) bool {
77	return reflect.DeepEqual(*n.raw, *other.raw)
78}
79
80// Value returns the raw value of the node
81func (n *Node) Value() interface{} {
82	return *n.raw
83}
84