yaml.go

 1package orderedmap
 2
 3import (
 4	"fmt"
 5
 6	"gopkg.in/yaml.v3"
 7)
 8
 9var (
10	_ yaml.Marshaler   = &OrderedMap[int, any]{}
11	_ yaml.Unmarshaler = &OrderedMap[int, any]{}
12)
13
14// MarshalYAML implements the yaml.Marshaler interface.
15func (om *OrderedMap[K, V]) MarshalYAML() (interface{}, error) {
16	if om == nil {
17		return []byte("null"), nil
18	}
19
20	node := yaml.Node{
21		Kind: yaml.MappingNode,
22	}
23
24	for pair := om.Oldest(); pair != nil; pair = pair.Next() {
25		key, value := pair.Key, pair.Value
26
27		keyNode := &yaml.Node{}
28
29		// serialize key to yaml, then deserialize it back into the node
30		// this is a hack to get the correct tag for the key
31		if err := keyNode.Encode(key); err != nil {
32			return nil, err
33		}
34
35		valueNode := &yaml.Node{}
36		if err := valueNode.Encode(value); err != nil {
37			return nil, err
38		}
39
40		node.Content = append(node.Content, keyNode, valueNode)
41	}
42
43	return &node, nil
44}
45
46// UnmarshalYAML implements the yaml.Unmarshaler interface.
47func (om *OrderedMap[K, V]) UnmarshalYAML(value *yaml.Node) error {
48	if value.Kind != yaml.MappingNode {
49		return fmt.Errorf("pipeline must contain YAML mapping, has %v", value.Kind)
50	}
51
52	if om.list == nil {
53		om.initialize(0)
54	}
55
56	for index := 0; index < len(value.Content); index += 2 {
57		var key K
58		var val V
59
60		if err := value.Content[index].Decode(&key); err != nil {
61			return err
62		}
63		if err := value.Content[index+1].Decode(&val); err != nil {
64			return err
65		}
66
67		om.Set(key, val)
68	}
69
70	return nil
71}