| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | package yaml | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-12-29 02:04:39 +09:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-01-12 02:50:51 +09:00
										 |  |  | 	"encoding" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	"encoding/base64" | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	"io" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2019-10-31 17:38:53 +09:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml/ast" | 
					
						
							| 
									
										
										
										
											2019-10-24 11:07:40 +09:00
										 |  |  | 	"github.com/goccy/go-yaml/internal/errors" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	"github.com/goccy/go-yaml/parser" | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml/token" | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	"golang.org/x/xerrors" | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-21 12:53:30 +09:00
										 |  |  | // Decoder reads and decodes YAML values from an input stream. | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | type Decoder struct { | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 	reader               io.Reader | 
					
						
							|  |  |  | 	referenceReaders     []io.Reader | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 	anchorNodeMap        map[string]ast.Node | 
					
						
							|  |  |  | 	anchorValueMap       map[string]reflect.Value | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 	opts                 []DecodeOption | 
					
						
							|  |  |  | 	referenceFiles       []string | 
					
						
							|  |  |  | 	referenceDirs        []string | 
					
						
							|  |  |  | 	isRecursiveDir       bool | 
					
						
							|  |  |  | 	isResolvedReference  bool | 
					
						
							|  |  |  | 	validator            StructValidator | 
					
						
							|  |  |  | 	disallowUnknownField bool | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 	disallowDuplicateKey bool | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 	useOrderedMap        bool | 
					
						
							| 
									
										
										
										
											2020-10-26 19:00:49 +09:00
										 |  |  | 	useJSONUnmarshaler   bool | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	parsedFile           *ast.File | 
					
						
							|  |  |  | 	streamIndex          int | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-21 12:53:30 +09:00
										 |  |  | // NewDecoder returns a new decoder that reads from r. | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | func NewDecoder(r io.Reader, opts ...DecodeOption) *Decoder { | 
					
						
							| 
									
										
										
										
											2019-10-18 14:27:49 +09:00
										 |  |  | 	return &Decoder{ | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 		reader:               r, | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		anchorNodeMap:        map[string]ast.Node{}, | 
					
						
							|  |  |  | 		anchorValueMap:       map[string]reflect.Value{}, | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 		opts:                 opts, | 
					
						
							|  |  |  | 		referenceReaders:     []io.Reader{}, | 
					
						
							|  |  |  | 		referenceFiles:       []string{}, | 
					
						
							|  |  |  | 		referenceDirs:        []string{}, | 
					
						
							|  |  |  | 		isRecursiveDir:       false, | 
					
						
							|  |  |  | 		isResolvedReference:  false, | 
					
						
							|  |  |  | 		disallowUnknownField: false, | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 		disallowDuplicateKey: false, | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 		useOrderedMap:        false, | 
					
						
							| 
									
										
										
										
											2019-10-18 14:27:49 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 17:38:53 +09:00
										 |  |  | func (d *Decoder) castToFloat(v interface{}) interface{} { | 
					
						
							|  |  |  | 	switch vv := v.(type) { | 
					
						
							|  |  |  | 	case int: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case int8: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case int16: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case int32: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case int64: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case uint: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case uint8: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case uint16: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case uint32: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case uint64: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							| 
									
										
										
										
											2019-11-01 11:26:36 +09:00
										 |  |  | 	case float32: | 
					
						
							|  |  |  | 		return float64(vv) | 
					
						
							|  |  |  | 	case float64: | 
					
						
							|  |  |  | 		return vv | 
					
						
							| 
									
										
										
										
											2019-10-31 17:38:53 +09:00
										 |  |  | 	case string: | 
					
						
							| 
									
										
										
										
											2019-11-01 11:26:36 +09:00
										 |  |  | 		// if error occurred, return zero value | 
					
						
							| 
									
										
										
										
											2019-10-31 17:38:53 +09:00
										 |  |  | 		f, _ := strconv.ParseFloat(vv, 64) | 
					
						
							|  |  |  | 		return f | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | func (d *Decoder) mergeValueNode(value ast.Node) ast.Node { | 
					
						
							|  |  |  | 	if value.Type() == ast.AliasType { | 
					
						
							|  |  |  | 		aliasNode := value.(*ast.AliasNode) | 
					
						
							|  |  |  | 		aliasName := aliasNode.Value.GetToken().Value | 
					
						
							|  |  |  | 		return d.anchorNodeMap[aliasName] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return value | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | func (d *Decoder) mapKeyNodeToString(node ast.Node) string { | 
					
						
							|  |  |  | 	key := d.nodeToValue(node) | 
					
						
							|  |  |  | 	if key == nil { | 
					
						
							|  |  |  | 		return "null" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if k, ok := key.(string); ok { | 
					
						
							|  |  |  | 		return k | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprint(key) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | func (d *Decoder) setToMapValue(node ast.Node, m map[string]interface{}) { | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.MappingValueNode: | 
					
						
							| 
									
										
										
										
											2020-06-11 20:58:37 +09:00
										 |  |  | 		if n.Key.Type() == ast.MergeKeyType { | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | 			d.setToMapValue(d.mergeValueNode(n.Value), m) | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 			key := d.mapKeyNodeToString(n.Key) | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 			m[key] = d.nodeToValue(n.Value) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							|  |  |  | 		for _, value := range n.Values { | 
					
						
							|  |  |  | 			d.setToMapValue(value, m) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-03-02 12:24:12 +09:00
										 |  |  | 	case *ast.AnchorNode: | 
					
						
							|  |  |  | 		anchorName := n.Name.GetToken().Value | 
					
						
							|  |  |  | 		d.anchorNodeMap[anchorName] = n.Value | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | func (d *Decoder) setToOrderedMapValue(node ast.Node, m *MapSlice) { | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.MappingValueNode: | 
					
						
							| 
									
										
										
										
											2020-06-11 20:58:37 +09:00
										 |  |  | 		if n.Key.Type() == ast.MergeKeyType { | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | 			d.setToOrderedMapValue(d.mergeValueNode(n.Value), m) | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 			key := d.mapKeyNodeToString(n.Key) | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 			*m = append(*m, MapItem{Key: key, Value: d.nodeToValue(n.Value)}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							|  |  |  | 		for _, value := range n.Values { | 
					
						
							|  |  |  | 			d.setToOrderedMapValue(value, m) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | func (d *Decoder) nodeToValue(node ast.Node) interface{} { | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.NullNode: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	case *ast.StringNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.IntegerNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.FloatNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.BoolNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.InfinityNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.NanNode: | 
					
						
							|  |  |  | 		return n.GetValue() | 
					
						
							|  |  |  | 	case *ast.TagNode: | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 		switch token.ReservedTagKeyword(n.Start.Value) { | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 		case token.TimestampTag: | 
					
						
							|  |  |  | 			t, _ := d.castToTime(n.Value) | 
					
						
							|  |  |  | 			return t | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 		case token.IntegerTag: | 
					
						
							|  |  |  | 			i, _ := strconv.Atoi(fmt.Sprint(d.nodeToValue(n.Value))) | 
					
						
							|  |  |  | 			return i | 
					
						
							| 
									
										
										
										
											2019-10-31 17:38:53 +09:00
										 |  |  | 		case token.FloatTag: | 
					
						
							|  |  |  | 			return d.castToFloat(d.nodeToValue(n.Value)) | 
					
						
							|  |  |  | 		case token.NullTag: | 
					
						
							|  |  |  | 			return nil | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		case token.BinaryTag: | 
					
						
							|  |  |  | 			b, _ := base64.StdEncoding.DecodeString(d.nodeToValue(n.Value).(string)) | 
					
						
							|  |  |  | 			return b | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 		case token.StringTag: | 
					
						
							|  |  |  | 			return d.nodeToValue(n.Value) | 
					
						
							|  |  |  | 		case token.MappingTag: | 
					
						
							|  |  |  | 			return d.nodeToValue(n.Value) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-18 14:27:49 +09:00
										 |  |  | 	case *ast.AnchorNode: | 
					
						
							|  |  |  | 		anchorName := n.Name.GetToken().Value | 
					
						
							|  |  |  | 		anchorValue := d.nodeToValue(n.Value) | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		d.anchorNodeMap[anchorName] = n.Value | 
					
						
							| 
									
										
										
										
											2019-10-18 14:27:49 +09:00
										 |  |  | 		return anchorValue | 
					
						
							|  |  |  | 	case *ast.AliasNode: | 
					
						
							|  |  |  | 		aliasName := n.Value.GetToken().Value | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		node := d.anchorNodeMap[aliasName] | 
					
						
							|  |  |  | 		return d.nodeToValue(node) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	case *ast.LiteralNode: | 
					
						
							|  |  |  | 		return n.Value.GetValue() | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 	case *ast.MappingKeyNode: | 
					
						
							|  |  |  | 		return d.nodeToValue(n.Value) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	case *ast.MappingValueNode: | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | 		if n.Key.Type() == ast.MergeKeyType { | 
					
						
							|  |  |  | 			value := d.mergeValueNode(n.Value) | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 			if d.useOrderedMap { | 
					
						
							|  |  |  | 				m := MapSlice{} | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | 				d.setToOrderedMapValue(value, &m) | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 				return m | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 			m := map[string]interface{}{} | 
					
						
							| 
									
										
										
										
											2020-06-15 12:14:02 +09:00
										 |  |  | 			d.setToMapValue(value, m) | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 			return m | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 		key := d.mapKeyNodeToString(n.Key) | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 		if d.useOrderedMap { | 
					
						
							|  |  |  | 			return MapSlice{{Key: key, Value: d.nodeToValue(n.Value)}} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 		return map[string]interface{}{ | 
					
						
							|  |  |  | 			key: d.nodeToValue(n.Value), | 
					
						
							| 
									
										
										
										
											2019-10-21 14:54:26 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-31 12:14:39 +09:00
										 |  |  | 	case *ast.MappingNode: | 
					
						
							| 
									
										
										
										
											2020-05-29 19:47:47 +09:00
										 |  |  | 		if d.useOrderedMap { | 
					
						
							|  |  |  | 			m := make(MapSlice, 0, len(n.Values)) | 
					
						
							|  |  |  | 			for _, value := range n.Values { | 
					
						
							|  |  |  | 				d.setToOrderedMapValue(value, &m) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return m | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 		m := make(map[string]interface{}, len(n.Values)) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		for _, value := range n.Values { | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 			d.setToMapValue(value, m) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return m | 
					
						
							|  |  |  | 	case *ast.SequenceNode: | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 		v := make([]interface{}, 0, len(n.Values)) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		for _, value := range n.Values { | 
					
						
							|  |  |  | 			v = append(v, d.nodeToValue(value)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return v | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | func (d *Decoder) resolveAlias(node ast.Node) ast.Node { | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							|  |  |  | 		for idx, value := range n.Values { | 
					
						
							|  |  |  | 			n.Values[idx] = d.resolveAlias(value).(*ast.MappingValueNode) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 	case *ast.TagNode: | 
					
						
							|  |  |  | 		n.Value = d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 	case *ast.MappingKeyNode: | 
					
						
							|  |  |  | 		n.Value = d.resolveAlias(n.Value) | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	case *ast.MappingValueNode: | 
					
						
							| 
									
										
										
										
											2020-06-11 20:40:27 +09:00
										 |  |  | 		if n.Key.Type() == ast.MergeKeyType && n.Value.Type() == ast.AliasType { | 
					
						
							|  |  |  | 			value := d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 			keyColumn := n.Key.GetToken().Position.Column | 
					
						
							|  |  |  | 			requiredColumn := keyColumn + 2 | 
					
						
							| 
									
										
										
										
											2020-06-11 20:58:37 +09:00
										 |  |  | 			value.AddColumn(requiredColumn) | 
					
						
							| 
									
										
										
										
											2020-06-11 20:40:27 +09:00
										 |  |  | 			n.Value = value | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			n.Key = d.resolveAlias(n.Key) | 
					
						
							|  |  |  | 			n.Value = d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	case *ast.SequenceNode: | 
					
						
							|  |  |  | 		for idx, value := range n.Values { | 
					
						
							|  |  |  | 			n.Values[idx] = d.resolveAlias(value) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case *ast.AliasNode: | 
					
						
							|  |  |  | 		aliasName := n.Value.GetToken().Value | 
					
						
							| 
									
										
										
										
											2020-06-15 13:48:17 +09:00
										 |  |  | 		return d.resolveAlias(d.anchorNodeMap[aliasName]) | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return node | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | func (d *Decoder) getMapNode(node ast.Node) (ast.MapNode, error) { | 
					
						
							| 
									
										
										
										
											2019-11-01 12:42:41 +09:00
										 |  |  | 	if _, ok := node.(*ast.NullNode); ok { | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	if anchor, ok := node.(*ast.AnchorNode); ok { | 
					
						
							|  |  |  | 		mapNode, ok := anchor.Value.(ast.MapNode) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			return mapNode, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where MapNode is expected", anchor.Value.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if alias, ok := node.(*ast.AliasNode); ok { | 
					
						
							|  |  |  | 		aliasName := alias.Value.GetToken().Value | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		node := d.anchorNodeMap[aliasName] | 
					
						
							|  |  |  | 		if node == nil { | 
					
						
							|  |  |  | 			return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mapNode, ok := node.(ast.MapNode) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 		if ok { | 
					
						
							|  |  |  | 			return mapNode, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where MapNode is expected", node.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	mapNode, ok := node.(ast.MapNode) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where MapNode is expected", node.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return mapNode, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) getArrayNode(node ast.Node) (ast.ArrayNode, error) { | 
					
						
							| 
									
										
										
										
											2019-11-01 12:42:41 +09:00
										 |  |  | 	if _, ok := node.(*ast.NullNode); ok { | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	if anchor, ok := node.(*ast.AnchorNode); ok { | 
					
						
							|  |  |  | 		arrayNode, ok := anchor.Value.(ast.ArrayNode) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			return arrayNode, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where ArrayNode is expected", anchor.Value.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if alias, ok := node.(*ast.AliasNode); ok { | 
					
						
							|  |  |  | 		aliasName := alias.Value.GetToken().Value | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		node := d.anchorNodeMap[aliasName] | 
					
						
							|  |  |  | 		if node == nil { | 
					
						
							|  |  |  | 			return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		arrayNode, ok := node.(ast.ArrayNode) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 		if ok { | 
					
						
							|  |  |  | 			return arrayNode, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where ArrayNode is expected", node.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	arrayNode, ok := node.(ast.ArrayNode) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-09-19 08:06:17 +09:00
										 |  |  | 		return nil, xerrors.Errorf("%s node found where ArrayNode is expected", node.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return arrayNode, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-05 17:02:55 +09:00
										 |  |  | func (d *Decoder) fileToNode(f *ast.File) ast.Node { | 
					
						
							|  |  |  | 	for _, doc := range f.Docs { | 
					
						
							|  |  |  | 		if v := d.nodeToValue(doc.Body); v != nil { | 
					
						
							|  |  |  | 			return doc.Body | 
					
						
							| 
									
										
										
										
											2019-10-18 13:05:36 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type) (reflect.Value, error) { | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	if typ.Kind() != reflect.String { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		if !v.Type().ConvertibleTo(typ) { | 
					
						
							|  |  |  | 			return reflect.Zero(typ), errTypeMismatch(typ, v.Type()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return v.Convert(typ), nil | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// cast value to string | 
					
						
							|  |  |  | 	switch v.Type().Kind() { | 
					
						
							|  |  |  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return reflect.ValueOf(fmt.Sprint(v.Int())), nil | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	case reflect.Float32, reflect.Float64: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return reflect.ValueOf(fmt.Sprint(v.Float())), nil | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return reflect.ValueOf(fmt.Sprint(v.Uint())), nil | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	case reflect.Bool: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return reflect.ValueOf(fmt.Sprint(v.Bool())), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !v.Type().ConvertibleTo(typ) { | 
					
						
							|  |  |  | 		return reflect.Zero(typ), errTypeMismatch(typ, v.Type()) | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	return v.Convert(typ), nil | 
					
						
							| 
									
										
										
										
											2019-10-29 16:23:26 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | type overflowError struct { | 
					
						
							|  |  |  | 	dstType reflect.Type | 
					
						
							|  |  |  | 	srcNum  string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *overflowError) Error() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.srcNum, e.dstType) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func errOverflow(dstType reflect.Type, num string) *overflowError { | 
					
						
							|  |  |  | 	return &overflowError{dstType: dstType, srcNum: num} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type typeError struct { | 
					
						
							|  |  |  | 	dstType         reflect.Type | 
					
						
							|  |  |  | 	srcType         reflect.Type | 
					
						
							|  |  |  | 	structFieldName *string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *typeError) Error() string { | 
					
						
							|  |  |  | 	if e.structFieldName != nil { | 
					
						
							|  |  |  | 		return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.srcType, *e.structFieldName, e.dstType) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.srcType, e.dstType) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func errTypeMismatch(dstType, srcType reflect.Type) *typeError { | 
					
						
							|  |  |  | 	return &typeError{dstType: dstType, srcType: srcType} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 13:33:56 +09:00
										 |  |  | type unknownFieldError struct { | 
					
						
							| 
									
										
										
										
											2019-12-14 14:35:58 +09:00
										 |  |  | 	err error | 
					
						
							| 
									
										
										
										
											2019-12-13 13:33:56 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-14 14:35:58 +09:00
										 |  |  | func (e *unknownFieldError) Error() string { | 
					
						
							|  |  |  | 	return e.err.Error() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func errUnknownField(msg string, tk *token.Token) *unknownFieldError { | 
					
						
							|  |  |  | 	return &unknownFieldError{err: errors.ErrSyntax(msg, tk)} | 
					
						
							| 
									
										
										
										
											2019-12-13 13:33:56 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | type duplicateKeyError struct { | 
					
						
							|  |  |  | 	err error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *duplicateKeyError) Error() string { | 
					
						
							|  |  |  | 	return e.err.Error() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func errDuplicateKey(msg string, tk *token.Token) *duplicateKeyError { | 
					
						
							|  |  |  | 	return &duplicateKeyError{err: errors.ErrSyntax(msg, tk)} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-09 10:36:35 +09:00
										 |  |  | func (d *Decoder) deleteStructKeys(structType reflect.Type, unknownFields map[string]ast.Node) error { | 
					
						
							| 
									
										
										
										
											2020-06-08 23:06:16 +09:00
										 |  |  | 	if structType.Kind() == reflect.Ptr { | 
					
						
							|  |  |  | 		structType = structType.Elem() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	structFieldMap, err := structFieldMap(structType) | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to create struct field map") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 23:06:16 +09:00
										 |  |  | 	for j := 0; j < structType.NumField(); j++ { | 
					
						
							|  |  |  | 		field := structType.Field(j) | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 		if isIgnoredStructField(field) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 13:26:05 +03:00
										 |  |  | 		structField, exists := structFieldMap[field.Name] | 
					
						
							|  |  |  | 		if !exists { | 
					
						
							| 
									
										
										
										
											2019-12-16 23:30:53 +09:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if structField.IsInline { | 
					
						
							| 
									
										
										
										
											2020-06-09 10:36:35 +09:00
										 |  |  | 			d.deleteStructKeys(field.Type, unknownFields) | 
					
						
							| 
									
										
										
										
											2019-12-16 23:30:53 +09:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 			delete(unknownFields, structField.RenderName) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 22:37:59 +09:00
										 |  |  | func (d *Decoder) lastNode(node ast.Node) ast.Node { | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							|  |  |  | 		if len(n.Values) > 0 { | 
					
						
							|  |  |  | 			return d.lastNode(n.Values[len(n.Values)-1]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case *ast.MappingValueNode: | 
					
						
							|  |  |  | 		return d.lastNode(n.Value) | 
					
						
							|  |  |  | 	case *ast.SequenceNode: | 
					
						
							|  |  |  | 		if len(n.Values) > 0 { | 
					
						
							|  |  |  | 			return d.lastNode(n.Values[len(n.Values)-1]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return node | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | func (d *Decoder) unmarshalableDocument(node ast.Node) []byte { | 
					
						
							|  |  |  | 	node = d.resolveAlias(node) | 
					
						
							|  |  |  | 	doc := node.String() | 
					
						
							|  |  |  | 	last := d.lastNode(node) | 
					
						
							|  |  |  | 	if last != nil && last.Type() == ast.LiteralType { | 
					
						
							|  |  |  | 		doc += "\n" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return []byte(doc) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) unmarshalableText(node ast.Node) ([]byte, bool) { | 
					
						
							|  |  |  | 	node = d.resolveAlias(node) | 
					
						
							|  |  |  | 	if node.Type() == ast.AnchorType { | 
					
						
							|  |  |  | 		node = node.(*ast.AnchorNode).Value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.StringNode: | 
					
						
							|  |  |  | 		return []byte(n.Value), true | 
					
						
							|  |  |  | 	case *ast.LiteralNode: | 
					
						
							|  |  |  | 		return []byte(n.Value.GetToken().Value), true | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		scalar, ok := n.(ast.ScalarNode) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			return []byte(fmt.Sprint(scalar.GetValue())), true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 19:00:49 +09:00
										 |  |  | type jsonUnmarshaler interface { | 
					
						
							|  |  |  | 	UnmarshalJSON([]byte) error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) canDecodeByUnmarshaler(dst reflect.Value) bool { | 
					
						
							|  |  |  | 	iface := dst.Addr().Interface() | 
					
						
							|  |  |  | 	switch iface.(type) { | 
					
						
							|  |  |  | 	case BytesUnmarshalerContext: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case BytesUnmarshaler: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case InterfaceUnmarshalerContext: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case InterfaceUnmarshaler: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case *time.Time: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case encoding.TextUnmarshaler: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case jsonUnmarshaler: | 
					
						
							|  |  |  | 		return d.useJSONUnmarshaler | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							|  |  |  | 	iface := dst.Addr().Interface() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, ok := iface.(BytesUnmarshalerContext); ok { | 
					
						
							|  |  |  | 		if err := unmarshaler.UnmarshalYAML(ctx, d.unmarshalableDocument(src)); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							| 
									
										
										
										
											2020-03-02 22:51:53 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, ok := iface.(BytesUnmarshaler); ok { | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 		if err := unmarshaler.UnmarshalYAML(d.unmarshalableDocument(src)); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, ok := iface.(InterfaceUnmarshalerContext); ok { | 
					
						
							|  |  |  | 		if err := unmarshaler.UnmarshalYAML(ctx, func(v interface{}) error { | 
					
						
							|  |  |  | 			rv := reflect.ValueOf(v) | 
					
						
							|  |  |  | 			if rv.Type().Kind() != reflect.Ptr { | 
					
						
							|  |  |  | 				return errors.ErrDecodeRequiredPointerType | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err := d.decodeValue(ctx, rv.Elem(), src); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to decode value") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, ok := iface.(InterfaceUnmarshaler); ok { | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		if err := unmarshaler.UnmarshalYAML(func(v interface{}) error { | 
					
						
							|  |  |  | 			rv := reflect.ValueOf(v) | 
					
						
							|  |  |  | 			if rv.Type().Kind() != reflect.Ptr { | 
					
						
							|  |  |  | 				return errors.ErrDecodeRequiredPointerType | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			if err := d.decodeValue(ctx, rv.Elem(), src); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 				return errors.Wrapf(err, "failed to decode value") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, ok := iface.(*time.Time); ok { | 
					
						
							|  |  |  | 		return d.decodeTime(ctx, dst, src) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, isText := iface.(encoding.TextUnmarshaler); isText { | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 		b, ok := d.unmarshalableText(src) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			if err := unmarshaler.UnmarshalText(b); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to UnmarshalText") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							| 
									
										
										
										
											2020-01-12 02:50:51 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if d.useJSONUnmarshaler { | 
					
						
							|  |  |  | 		if unmarshaler, ok := iface.(jsonUnmarshaler); ok { | 
					
						
							| 
									
										
										
										
											2020-10-26 19:00:49 +09:00
										 |  |  | 			jsonBytes, err := YAMLToJSON(d.unmarshalableDocument(src)) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to convert yaml to json") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			jsonBytes = bytes.TrimRight(jsonBytes, "\n") | 
					
						
							|  |  |  | 			if err := unmarshaler.UnmarshalJSON(jsonBytes); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to UnmarshalJSON") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return xerrors.Errorf("does not implemented Unmarshaler") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 13:47:31 +09:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	astNodeType = reflect.TypeOf((*ast.Node)(nil)).Elem() | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							|  |  |  | 	if src.Type() == ast.AnchorType { | 
					
						
							|  |  |  | 		anchorName := src.(*ast.AnchorNode).Name.GetToken().Value | 
					
						
							|  |  |  | 		if _, exists := d.anchorValueMap[anchorName]; !exists { | 
					
						
							|  |  |  | 			d.anchorValueMap[anchorName] = dst | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if d.canDecodeByUnmarshaler(dst) { | 
					
						
							|  |  |  | 		if err := d.decodeByUnmarshaler(ctx, dst, src); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to decode by unmarshaler") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	valueType := dst.Type() | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	switch valueType.Kind() { | 
					
						
							|  |  |  | 	case reflect.Ptr: | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		if dst.IsNil() { | 
					
						
							|  |  |  | 			return nil | 
					
						
							| 
									
										
										
										
											2019-10-21 14:54:26 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		if src.Type() == ast.NullType { | 
					
						
							|  |  |  | 			// set nil value to pointer | 
					
						
							|  |  |  | 			dst.Set(reflect.Zero(valueType)) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		v := d.createDecodableValue(dst.Type()) | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		if err := d.decodeValue(ctx, v, src); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to decode ptr value") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		dst.Set(d.castToAssignableValue(v, dst.Type())) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	case reflect.Interface: | 
					
						
							| 
									
										
										
										
											2021-03-01 13:47:31 +09:00
										 |  |  | 		if dst.Type() == astNodeType { | 
					
						
							|  |  |  | 			dst.Set(reflect.ValueOf(src)) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 		v := reflect.ValueOf(d.nodeToValue(src)) | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		if v.IsValid() { | 
					
						
							|  |  |  | 			dst.Set(v) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	case reflect.Map: | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		return d.decodeMap(ctx, dst, src) | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 	case reflect.Array: | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		return d.decodeArray(ctx, dst, src) | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 	case reflect.Slice: | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 		if mapSlice, ok := dst.Addr().Interface().(*MapSlice); ok { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			return d.decodeMapSlice(ctx, mapSlice, src) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		return d.decodeSlice(ctx, dst, src) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	case reflect.Struct: | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 		if mapItem, ok := dst.Addr().Interface().(*MapItem); ok { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			return d.decodeMapItem(ctx, mapItem, src) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		return d.decodeStruct(ctx, dst, src) | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 
					
						
							|  |  |  | 		v := d.nodeToValue(src) | 
					
						
							|  |  |  | 		switch vv := v.(type) { | 
					
						
							|  |  |  | 		case int64: | 
					
						
							|  |  |  | 			if !dst.OverflowInt(vv) { | 
					
						
							|  |  |  | 				dst.SetInt(vv) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-29 20:15:27 +09:00
										 |  |  | 		case uint64: | 
					
						
							|  |  |  | 			if vv <= math.MaxInt64 && !dst.OverflowInt(int64(vv)) { | 
					
						
							|  |  |  | 				dst.SetInt(int64(vv)) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 		case float64: | 
					
						
							|  |  |  | 			if vv <= math.MaxInt64 && !dst.OverflowInt(int64(vv)) { | 
					
						
							|  |  |  | 				dst.SetInt(int64(vv)) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:36 +09:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			return errTypeMismatch(valueType, reflect.TypeOf(v)) | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return errOverflow(valueType, fmt.Sprint(v)) | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | 
					
						
							|  |  |  | 		v := d.nodeToValue(src) | 
					
						
							|  |  |  | 		switch vv := v.(type) { | 
					
						
							|  |  |  | 		case int64: | 
					
						
							| 
									
										
										
										
											2019-10-29 20:15:27 +09:00
										 |  |  | 			if 0 <= vv && !dst.OverflowUint(uint64(vv)) { | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 				dst.SetUint(uint64(vv)) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-29 20:15:27 +09:00
										 |  |  | 		case uint64: | 
					
						
							|  |  |  | 			if !dst.OverflowUint(vv) { | 
					
						
							|  |  |  | 				dst.SetUint(vv) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 		case float64: | 
					
						
							|  |  |  | 			if 0 <= vv && vv <= math.MaxUint64 && !dst.OverflowUint(uint64(vv)) { | 
					
						
							|  |  |  | 				dst.SetUint(uint64(vv)) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:36 +09:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			return errTypeMismatch(valueType, reflect.TypeOf(v)) | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return errOverflow(valueType, fmt.Sprint(v)) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	v := reflect.ValueOf(d.nodeToValue(src)) | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	if v.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		convertedValue, err := d.convertValue(v, dst.Type()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-11 00:41:05 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to convert value") | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		dst.Set(convertedValue) | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | func (d *Decoder) createDecodableValue(typ reflect.Type) reflect.Value { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		if typ.Kind() == reflect.Ptr { | 
					
						
							|  |  |  | 			typ = typ.Elem() | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reflect.New(typ).Elem() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) castToAssignableValue(value reflect.Value, target reflect.Type) reflect.Value { | 
					
						
							|  |  |  | 	if target.Kind() != reflect.Ptr { | 
					
						
							|  |  |  | 		return value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	maxTryCount := 5 | 
					
						
							|  |  |  | 	tryCount := 0 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		if tryCount > maxTryCount { | 
					
						
							|  |  |  | 			return value | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if value.Type().AssignableTo(target) { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		value = value.Addr() | 
					
						
							|  |  |  | 		tryCount++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return value | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) createDecodedNewValue(ctx context.Context, typ reflect.Type, node ast.Node) (reflect.Value, error) { | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 	if node.Type() == ast.AliasType { | 
					
						
							|  |  |  | 		aliasName := node.(*ast.AliasNode).Value.GetToken().Value | 
					
						
							|  |  |  | 		newValue := d.anchorValueMap[aliasName] | 
					
						
							|  |  |  | 		if newValue.IsValid() { | 
					
						
							|  |  |  | 			return newValue, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-22 11:43:45 +09:00
										 |  |  | 	if node.Type() == ast.NullType { | 
					
						
							|  |  |  | 		return reflect.Zero(typ), nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 	newValue := d.createDecodableValue(typ) | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	if err := d.decodeValue(ctx, newValue, node); err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		return newValue, errors.Wrapf(err, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return newValue, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | func (d *Decoder) keyToNodeMap(node ast.Node, ignoreMergeKey bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) { | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	mapNode, err := d.getMapNode(node) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrapf(err, "failed to get map node") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 	keyMap := map[string]struct{}{} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	keyToNodeMap := map[string]ast.Node{} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:42:41 +09:00
										 |  |  | 	if mapNode == nil { | 
					
						
							|  |  |  | 		return keyToNodeMap, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mapIter := mapNode.MapRange() | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	for mapIter.Next() { | 
					
						
							|  |  |  | 		keyNode := mapIter.Key() | 
					
						
							|  |  |  | 		if keyNode.Type() == ast.MergeKeyType { | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | 			if ignoreMergeKey { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			mergeMap, err := d.keyToNodeMap(mapIter.Value(), ignoreMergeKey, getKeyOrValueNode) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, errors.Wrapf(err, "failed to get keyToNodeMap by MergeKey node") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for k, v := range mergeMap { | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 				if err := d.validateDuplicateKey(keyMap, k, v); err != nil { | 
					
						
							|  |  |  | 					return nil, errors.Wrapf(err, "invalid struct key") | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 				keyToNodeMap[k] = v | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			key, ok := d.nodeToValue(keyNode).(string) | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				return nil, errors.Wrapf(err, "failed to decode map key") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 			if err := d.validateDuplicateKey(keyMap, key, keyNode); err != nil { | 
					
						
							|  |  |  | 				return nil, errors.Wrapf(err, "invalid struct key") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-11 15:42:22 +09:00
										 |  |  | 			keyToNodeMap[key] = getKeyOrValueNode(mapIter) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return keyToNodeMap, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | func (d *Decoder) keyToKeyNodeMap(node ast.Node, ignoreMergeKey bool) (map[string]ast.Node, error) { | 
					
						
							|  |  |  | 	m, err := d.keyToNodeMap(node, ignoreMergeKey, func(nodeMap *ast.MapNodeIter) ast.Node { return nodeMap.Key() }) | 
					
						
							| 
									
										
										
										
											2019-12-11 11:27:43 +09:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrapf(err, "failed to get keyToNodeMap") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m, nil | 
					
						
							| 
									
										
										
										
											2019-12-11 10:38:21 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | func (d *Decoder) keyToValueNodeMap(node ast.Node, ignoreMergeKey bool) (map[string]ast.Node, error) { | 
					
						
							|  |  |  | 	m, err := d.keyToNodeMap(node, ignoreMergeKey, func(nodeMap *ast.MapNodeIter) ast.Node { return nodeMap.Value() }) | 
					
						
							| 
									
										
										
										
											2019-12-11 11:27:43 +09:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrapf(err, "failed to get keyToNodeMap") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m, nil | 
					
						
							| 
									
										
										
										
											2019-12-11 10:38:21 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-28 22:44:21 +09:00
										 |  |  | func (d *Decoder) setDefaultValueIfConflicted(v reflect.Value, fieldMap StructFieldMap) error { | 
					
						
							|  |  |  | 	typ := v.Type() | 
					
						
							|  |  |  | 	if typ.Kind() != reflect.Struct { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	embeddedStructFieldMap, err := structFieldMap(typ) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get struct field map by embedded type") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for i := 0; i < typ.NumField(); i++ { | 
					
						
							|  |  |  | 		field := typ.Field(i) | 
					
						
							| 
									
										
										
										
											2019-11-06 19:44:18 +09:00
										 |  |  | 		if isIgnoredStructField(field) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-28 22:44:21 +09:00
										 |  |  | 		structField := embeddedStructFieldMap[field.Name] | 
					
						
							|  |  |  | 		if !fieldMap.isIncludedRenderName(structField.RenderName) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// if declared same key name, set default value | 
					
						
							|  |  |  | 		fieldValue := v.Field(i) | 
					
						
							|  |  |  | 		if fieldValue.CanSet() { | 
					
						
							|  |  |  | 			fieldValue.Set(reflect.Zero(fieldValue.Type())) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | // This is a subset of the formats allowed by the regular expression | 
					
						
							|  |  |  | // defined at http://yaml.org/type/timestamp.html. | 
					
						
							|  |  |  | var allowedTimestampFormats = []string{ | 
					
						
							|  |  |  | 	"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. | 
					
						
							|  |  |  | 	"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". | 
					
						
							|  |  |  | 	"2006-1-2 15:4:5.999999999",       // space separated with no time zone | 
					
						
							|  |  |  | 	"2006-1-2",                        // date only | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | func (d *Decoder) castToTime(src ast.Node) (time.Time, error) { | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	if src == nil { | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 		return time.Time{}, nil | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	v := d.nodeToValue(src) | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 	if t, ok := v.(time.Time); ok { | 
					
						
							|  |  |  | 		return t, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	s, ok := v.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v)) | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for _, format := range allowedTimestampFormats { | 
					
						
							|  |  |  | 		t, err := time.Parse(format, s) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			// invalid format | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 		return t, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return time.Time{}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeTime(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 	t, err := d.castToTime(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 	dst.Set(reflect.ValueOf(t)) | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 22:55:57 +09:00
										 |  |  | // getMergeAliasName support single alias only | 
					
						
							|  |  |  | func (d *Decoder) getMergeAliasName(src ast.Node) string { | 
					
						
							|  |  |  | 	mapNode, err := d.getMapNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if mapNode == nil { | 
					
						
							|  |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mapIter := mapNode.MapRange() | 
					
						
							|  |  |  | 	for mapIter.Next() { | 
					
						
							|  |  |  | 		key := mapIter.Key() | 
					
						
							|  |  |  | 		value := mapIter.Value() | 
					
						
							|  |  |  | 		if key.Type() == ast.MergeKeyType && value.Type() == ast.AliasType { | 
					
						
							|  |  |  | 			return value.(*ast.AliasNode).Value.GetToken().Value | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	if src == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	structType := dst.Type() | 
					
						
							| 
									
										
										
										
											2021-03-01 13:47:31 +09:00
										 |  |  | 	srcValue := reflect.ValueOf(src) | 
					
						
							|  |  |  | 	srcType := srcValue.Type() | 
					
						
							|  |  |  | 	if srcType.Kind() == reflect.Ptr { | 
					
						
							|  |  |  | 		srcType = srcType.Elem() | 
					
						
							|  |  |  | 		srcValue = srcValue.Elem() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if structType == srcType { | 
					
						
							|  |  |  | 		// dst value implements ast.Node | 
					
						
							|  |  |  | 		dst.Set(srcValue) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 	structFieldMap, err := structFieldMap(structType) | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		return errors.Wrapf(err, "failed to create struct field map") | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | 	ignoreMergeKey := structFieldMap.hasMergeProperty() | 
					
						
							|  |  |  | 	keyToNodeMap, err := d.keyToValueNodeMap(src, ignoreMergeKey) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-11 10:38:21 +09:00
										 |  |  | 		return errors.Wrapf(err, "failed to get keyToValueNodeMap") | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-11 13:07:34 +09:00
										 |  |  | 	var unknownFields map[string]ast.Node | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 	if d.disallowUnknownField { | 
					
						
							| 
									
										
										
										
											2020-03-02 22:53:33 +09:00
										 |  |  | 		unknownFields, err = d.keyToKeyNodeMap(src, ignoreMergeKey) | 
					
						
							| 
									
										
										
										
											2019-12-10 18:41:23 +09:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to get keyToKeyNodeMap") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 22:55:57 +09:00
										 |  |  | 	aliasName := d.getMergeAliasName(src) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	var foundErr error | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	for i := 0; i < structType.NumField(); i++ { | 
					
						
							|  |  |  | 		field := structType.Field(i) | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 		if isIgnoredStructField(field) { | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 		structField := structFieldMap[field.Name] | 
					
						
							| 
									
										
										
										
											2019-10-28 22:12:23 +09:00
										 |  |  | 		if structField.IsInline { | 
					
						
							| 
									
										
										
										
											2019-12-14 11:55:23 +09:00
										 |  |  | 			fieldValue := dst.FieldByName(field.Name) | 
					
						
							| 
									
										
										
										
											2020-03-02 22:55:57 +09:00
										 |  |  | 			if structField.IsAutoAlias { | 
					
						
							|  |  |  | 				if aliasName != "" { | 
					
						
							|  |  |  | 					newFieldValue := d.anchorValueMap[aliasName] | 
					
						
							|  |  |  | 					if newFieldValue.IsValid() { | 
					
						
							|  |  |  | 						fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-28 22:12:23 +09:00
										 |  |  | 			if !fieldValue.CanSet() { | 
					
						
							|  |  |  | 				return xerrors.Errorf("cannot set embedded type as unexported field %s.%s", field.PkgPath, field.Name) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 			if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { | 
					
						
							|  |  |  | 				// set nil value to pointer | 
					
						
							|  |  |  | 				fieldValue.Set(reflect.Zero(fieldValue.Type())) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-03-02 22:55:57 +09:00
										 |  |  | 			mapNode := ast.Mapping(nil, false) | 
					
						
							|  |  |  | 			for k, v := range keyToNodeMap { | 
					
						
							| 
									
										
										
										
											2020-06-21 16:22:04 +09:00
										 |  |  | 				key := &ast.StringNode{BaseNode: &ast.BaseNode{}, Value: k} | 
					
						
							|  |  |  | 				mapNode.Values = append(mapNode.Values, ast.MappingValue(nil, key, v)) | 
					
						
							| 
									
										
										
										
											2020-03-02 22:55:57 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), mapNode) | 
					
						
							| 
									
										
										
										
											2019-12-18 13:26:59 +09:00
										 |  |  | 			if d.disallowUnknownField { | 
					
						
							|  |  |  | 				var ufe *unknownFieldError | 
					
						
							|  |  |  | 				if xerrors.As(err, &ufe) { | 
					
						
							|  |  |  | 					err = nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-09 10:36:35 +09:00
										 |  |  | 				if err = d.deleteStructKeys(fieldValue.Type(), unknownFields); err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-18 13:26:59 +09:00
										 |  |  | 					return errors.Wrapf(err, "cannot delete struct keys") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 				if foundErr != nil { | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 				var te *typeError | 
					
						
							|  |  |  | 				if xerrors.As(err, &te) { | 
					
						
							| 
									
										
										
										
											2019-12-11 00:41:05 +09:00
										 |  |  | 					if te.structFieldName != nil { | 
					
						
							|  |  |  | 						fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.structFieldName) | 
					
						
							|  |  |  | 						te.structFieldName = &fieldName | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) | 
					
						
							|  |  |  | 						te.structFieldName = &fieldName | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 					foundErr = te | 
					
						
							| 
									
										
										
										
											2019-12-13 13:33:56 +09:00
										 |  |  | 					continue | 
					
						
							| 
									
										
										
										
											2019-12-16 23:30:53 +09:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2019-12-18 13:26:59 +09:00
										 |  |  | 					foundErr = err | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-12-18 13:26:59 +09:00
										 |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2019-10-28 22:12:23 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 			d.setDefaultValueIfConflicted(newFieldValue, structFieldMap) | 
					
						
							| 
									
										
										
										
											2019-10-28 22:12:23 +09:00
										 |  |  | 			fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 		v, exists := keyToNodeMap[structField.RenderName] | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 		if !exists { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-11 13:07:34 +09:00
										 |  |  | 		delete(unknownFields, structField.RenderName) | 
					
						
							| 
									
										
										
										
											2019-12-14 11:55:23 +09:00
										 |  |  | 		fieldValue := dst.FieldByName(field.Name) | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { | 
					
						
							|  |  |  | 			// set nil value to pointer | 
					
						
							|  |  |  | 			fieldValue.Set(reflect.Zero(fieldValue.Type())) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), v) | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			if foundErr != nil { | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			var te *typeError | 
					
						
							|  |  |  | 			if xerrors.As(err, &te) { | 
					
						
							|  |  |  | 				fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) | 
					
						
							|  |  |  | 				te.structFieldName = &fieldName | 
					
						
							|  |  |  | 				foundErr = te | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				foundErr = err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-12 19:02:23 +03:00
										 |  |  | 	if foundErr != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(foundErr, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(unknownFields) != 0 && d.disallowUnknownField { | 
					
						
							|  |  |  | 		for key, node := range unknownFields { | 
					
						
							|  |  |  | 			return errUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 10:08:44 +09:00
										 |  |  | 	if d.validator != nil { | 
					
						
							| 
									
										
										
										
											2019-12-14 11:55:23 +09:00
										 |  |  | 		if err := d.validator.Struct(dst.Interface()); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-26 10:08:44 +09:00
										 |  |  | 			ev := reflect.ValueOf(err) | 
					
						
							|  |  |  | 			if ev.Type().Kind() == reflect.Slice { | 
					
						
							|  |  |  | 				for i := 0; i < ev.Len(); i++ { | 
					
						
							|  |  |  | 					fieldErr, ok := ev.Index(i).Interface().(FieldError) | 
					
						
							|  |  |  | 					if !ok { | 
					
						
							|  |  |  | 						continue | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					fieldName := fieldErr.StructField() | 
					
						
							| 
									
										
										
										
											2020-07-03 13:28:59 +03:00
										 |  |  | 					structField, exists := structFieldMap[fieldName] | 
					
						
							|  |  |  | 					if !exists { | 
					
						
							| 
									
										
										
										
											2020-06-28 22:16:03 +03:00
										 |  |  | 						continue | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-10-26 10:08:44 +09:00
										 |  |  | 					node, exists := keyToNodeMap[structField.RenderName] | 
					
						
							|  |  |  | 					if exists { | 
					
						
							|  |  |  | 						// TODO: to make FieldError message cutomizable | 
					
						
							|  |  |  | 						return errors.ErrSyntax(fmt.Sprintf("%s", err), node.GetToken()) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeArray(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 	arrayNode, err := d.getArrayNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get array node") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if arrayNode == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	iter := arrayNode.ArrayRange() | 
					
						
							|  |  |  | 	arrayValue := reflect.New(dst.Type()).Elem() | 
					
						
							|  |  |  | 	arrayType := dst.Type() | 
					
						
							|  |  |  | 	elemType := arrayType.Elem() | 
					
						
							|  |  |  | 	idx := 0 | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var foundErr error | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 	for iter.Next() { | 
					
						
							|  |  |  | 		v := iter.Value() | 
					
						
							|  |  |  | 		if elemType.Kind() == reflect.Ptr && v.Type() == ast.NullType { | 
					
						
							|  |  |  | 			// set nil value to pointer | 
					
						
							|  |  |  | 			arrayValue.Index(idx).Set(reflect.Zero(elemType)) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			dstValue, err := d.createDecodedNewValue(ctx, elemType, v) | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 				if foundErr == nil { | 
					
						
							|  |  |  | 					foundErr = err | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				arrayValue.Index(idx).Set(d.castToAssignableValue(dstValue, elemType)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		idx++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dst.Set(arrayValue) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	if foundErr != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(foundErr, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:57 +09:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeSlice(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	arrayNode, err := d.getArrayNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get array node") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:42:41 +09:00
										 |  |  | 	if arrayNode == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	iter := arrayNode.ArrayRange() | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	sliceType := dst.Type() | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	sliceValue := reflect.MakeSlice(sliceType, 0, iter.Len()) | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	elemType := sliceType.Elem() | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var foundErr error | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	for iter.Next() { | 
					
						
							|  |  |  | 		v := iter.Value() | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		if elemType.Kind() == reflect.Ptr && v.Type() == ast.NullType { | 
					
						
							|  |  |  | 			// set nil value to pointer | 
					
						
							|  |  |  | 			sliceValue = reflect.Append(sliceValue, reflect.Zero(elemType)) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		dstValue, err := d.createDecodedNewValue(ctx, elemType, v) | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			if foundErr == nil { | 
					
						
							|  |  |  | 				foundErr = err | 
					
						
							| 
									
										
										
										
											2019-10-31 17:56:04 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 		sliceValue = reflect.Append(sliceValue, d.castToAssignableValue(dstValue, elemType)) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	dst.Set(sliceValue) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	if foundErr != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(foundErr, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeMapItem(ctx context.Context, dst *MapItem, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 	mapNode, err := d.getMapNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get map node") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if mapNode == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mapIter := mapNode.MapRange() | 
					
						
							|  |  |  | 	if !mapIter.Next() { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	key := mapIter.Key() | 
					
						
							|  |  |  | 	value := mapIter.Value() | 
					
						
							|  |  |  | 	if key.Type() == ast.MergeKeyType { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		if err := d.decodeMapItem(ctx, dst, value); err != nil { | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to decode map with merge key") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*dst = MapItem{ | 
					
						
							|  |  |  | 		Key:   d.nodeToValue(key), | 
					
						
							|  |  |  | 		Value: d.nodeToValue(value), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | func (d *Decoder) validateDuplicateKey(keyMap map[string]struct{}, key interface{}, keyNode ast.Node) error { | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 	k, ok := key.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if d.disallowDuplicateKey { | 
					
						
							|  |  |  | 		if _, exists := keyMap[k]; exists { | 
					
						
							|  |  |  | 			return errDuplicateKey(fmt.Sprintf(`duplicate key "%s"`, k), keyNode.GetToken()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	keyMap[k] = struct{}{} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeMapSlice(ctx context.Context, dst *MapSlice, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 	mapNode, err := d.getMapNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get map node") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if mapNode == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mapSlice := MapSlice{} | 
					
						
							|  |  |  | 	mapIter := mapNode.MapRange() | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 	keyMap := map[string]struct{}{} | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 	for mapIter.Next() { | 
					
						
							|  |  |  | 		key := mapIter.Key() | 
					
						
							|  |  |  | 		value := mapIter.Value() | 
					
						
							|  |  |  | 		if key.Type() == ast.MergeKeyType { | 
					
						
							|  |  |  | 			var m MapSlice | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			if err := d.decodeMapSlice(ctx, &m, value); err != nil { | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 				return errors.Wrapf(err, "failed to decode map with merge key") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for _, v := range m { | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 				if err := d.validateDuplicateKey(keyMap, v.Key, value); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 					return errors.Wrapf(err, "invalid map key") | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 				mapSlice = append(mapSlice, v) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 		k := d.nodeToValue(key) | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 		if err := d.validateDuplicateKey(keyMap, k, key); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 			return errors.Wrapf(err, "invalid map key") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 		mapSlice = append(mapSlice, MapItem{ | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 			Key:   k, | 
					
						
							| 
									
										
										
										
											2020-05-28 17:30:19 +09:00
										 |  |  | 			Value: d.nodeToValue(value), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*dst = mapSlice | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	mapNode, err := d.getMapNode(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to get map node") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:42:41 +09:00
										 |  |  | 	if mapNode == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	mapType := dst.Type() | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	mapValue := reflect.MakeMap(mapType) | 
					
						
							|  |  |  | 	keyType := mapValue.Type().Key() | 
					
						
							|  |  |  | 	valueType := mapValue.Type().Elem() | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	mapIter := mapNode.MapRange() | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 	keyMap := map[string]struct{}{} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	var foundErr error | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	for mapIter.Next() { | 
					
						
							|  |  |  | 		key := mapIter.Key() | 
					
						
							|  |  |  | 		value := mapIter.Value() | 
					
						
							| 
									
										
										
										
											2020-03-02 16:18:13 +09:00
										 |  |  | 		if key.Type() == ast.MergeKeyType { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			if err := d.decodeMap(ctx, dst, value); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-02 16:18:13 +09:00
										 |  |  | 				return errors.Wrapf(err, "failed to decode map with merge key") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			iter := dst.MapRange() | 
					
						
							|  |  |  | 			for iter.Next() { | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 				if err := d.validateDuplicateKey(keyMap, iter.Key(), value); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 					return errors.Wrapf(err, "invalid map key") | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-03-02 16:18:13 +09:00
										 |  |  | 				mapValue.SetMapIndex(iter.Key(), iter.Value()) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		k := reflect.ValueOf(d.nodeToValue(key)) | 
					
						
							|  |  |  | 		if k.IsValid() && k.Type().ConvertibleTo(keyType) { | 
					
						
							|  |  |  | 			k = k.Convert(keyType) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-01 17:31:07 +09:00
										 |  |  | 		if k.IsValid() { | 
					
						
							| 
									
										
										
										
											2020-06-08 23:34:34 +09:00
										 |  |  | 			if err := d.validateDuplicateKey(keyMap, k.Interface(), key); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 17:31:07 +09:00
										 |  |  | 				return errors.Wrapf(err, "invalid map key") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-06-01 17:26:27 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		if valueType.Kind() == reflect.Ptr && value.Type() == ast.NullType { | 
					
						
							|  |  |  | 			// set nil value to pointer | 
					
						
							|  |  |  | 			mapValue.SetMapIndex(k, reflect.Zero(valueType)) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		dstValue, err := d.createDecodedNewValue(ctx, valueType, value) | 
					
						
							| 
									
										
										
										
											2020-01-09 21:49:52 +09:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			if foundErr == nil { | 
					
						
							|  |  |  | 				foundErr = err | 
					
						
							| 
									
										
										
										
											2019-10-29 19:46:55 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		if !k.IsValid() { | 
					
						
							|  |  |  | 			// expect nil key | 
					
						
							|  |  |  | 			mapValue.SetMapIndex(d.createDecodableValue(keyType), d.castToAssignableValue(dstValue, valueType)) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mapValue.SetMapIndex(k, d.castToAssignableValue(dstValue, valueType)) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	dst.Set(mapValue) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 	if foundErr != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(foundErr, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-24 17:18:03 +09:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | func (d *Decoder) fileToReader(file string) (io.Reader, error) { | 
					
						
							|  |  |  | 	reader, err := os.Open(file) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return nil, errors.Wrapf(err, "failed to open file") | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	return reader, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) isYAMLFile(file string) bool { | 
					
						
							|  |  |  | 	ext := filepath.Ext(file) | 
					
						
							|  |  |  | 	if ext == ".yml" { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ext == ".yaml" { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) readersUnderDir(dir string) ([]io.Reader, error) { | 
					
						
							|  |  |  | 	pattern := fmt.Sprintf("%s/*", dir) | 
					
						
							|  |  |  | 	matches, err := filepath.Glob(pattern) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return nil, errors.Wrapf(err, "failed to get files by %s", pattern) | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	readers := []io.Reader{} | 
					
						
							|  |  |  | 	for _, match := range matches { | 
					
						
							|  |  |  | 		if !d.isYAMLFile(match) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		reader, err := d.fileToReader(match) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return nil, errors.Wrapf(err, "failed to get reader") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		readers = append(readers, reader) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return readers, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) readersUnderDirRecursive(dir string) ([]io.Reader, error) { | 
					
						
							|  |  |  | 	readers := []io.Reader{} | 
					
						
							|  |  |  | 	if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { | 
					
						
							|  |  |  | 		if !d.isYAMLFile(path) { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		reader, err := d.fileToReader(path) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to get reader") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		readers = append(readers, reader) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return nil, errors.Wrapf(err, "interrupt walk in %s", dir) | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return readers, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) resolveReference() error { | 
					
						
							|  |  |  | 	for _, opt := range d.opts { | 
					
						
							|  |  |  | 		if err := opt(d); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to exec option") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, file := range d.referenceFiles { | 
					
						
							|  |  |  | 		reader, err := d.fileToReader(file) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to get reader") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		d.referenceReaders = append(d.referenceReaders, reader) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, dir := range d.referenceDirs { | 
					
						
							|  |  |  | 		if !d.isRecursiveDir { | 
					
						
							|  |  |  | 			readers, err := d.readersUnderDir(dir) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 				return errors.Wrapf(err, "failed to get readers from under the %s", dir) | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			d.referenceReaders = append(d.referenceReaders, readers...) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			readers, err := d.readersUnderDirRecursive(dir) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 				return errors.Wrapf(err, "failed to get readers from under the %s", dir) | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			d.referenceReaders = append(d.referenceReaders, readers...) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	for _, reader := range d.referenceReaders { | 
					
						
							|  |  |  | 		bytes, err := ioutil.ReadAll(reader) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to read buffer") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// assign new anchor definition to anchorMap | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 		if _, err := d.parse(bytes); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to decode") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	d.isResolvedReference = true | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | func (d *Decoder) parse(bytes []byte) (*ast.File, error) { | 
					
						
							| 
									
										
										
										
											2019-11-05 17:02:55 +09:00
										 |  |  | 	f, err := parser.ParseBytes(bytes, 0) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return nil, errors.Wrapf(err, "failed to parse yaml") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	normalizedFile := &ast.File{} | 
					
						
							|  |  |  | 	for _, doc := range f.Docs { | 
					
						
							|  |  |  | 		// try to decode ast.Node to value and map anchor value to anchorMap | 
					
						
							|  |  |  | 		if v := d.nodeToValue(doc.Body); v != nil { | 
					
						
							|  |  |  | 			normalizedFile.Docs = append(normalizedFile.Docs, doc) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return normalizedFile, nil | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | func (d *Decoder) isInitialized() bool { | 
					
						
							|  |  |  | 	return d.parsedFile != nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) decodeInit() error { | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	if !d.isResolvedReference { | 
					
						
							|  |  |  | 		if err := d.resolveReference(); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 			return errors.Wrapf(err, "failed to resolve reference") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-29 02:04:39 +09:00
										 |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	if _, err := io.Copy(&buf, d.reader); err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to copy from reader") | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	file, err := d.parse(buf.Bytes()) | 
					
						
							| 
									
										
										
										
											2019-10-18 15:20:09 +09:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return errors.Wrapf(err, "failed to decode") | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	d.parsedFile = file | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) decode(ctx context.Context, v reflect.Value) error { | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	if len(d.parsedFile.Docs) <= d.streamIndex { | 
					
						
							|  |  |  | 		return io.EOF | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	body := d.parsedFile.Docs[d.streamIndex].Body | 
					
						
							|  |  |  | 	if body == nil { | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	if err := d.decodeValue(ctx, v.Elem(), body); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-23 16:40:26 +09:00
										 |  |  | 		return errors.Wrapf(err, "failed to decode value") | 
					
						
							| 
									
										
										
										
											2019-10-18 12:55:38 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	d.streamIndex++ | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Decode reads the next YAML-encoded value from its input | 
					
						
							|  |  |  | // and stores it in the value pointed to by v. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // See the documentation for Unmarshal for details about the | 
					
						
							|  |  |  | // conversion of YAML into a Go value. | 
					
						
							|  |  |  | func (d *Decoder) Decode(v interface{}) error { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	return d.DecodeContext(context.Background(), v) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DecodeContext reads the next YAML-encoded value from its input | 
					
						
							|  |  |  | // and stores it in the value pointed to by v with context.Context. | 
					
						
							|  |  |  | func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error { | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	rv := reflect.ValueOf(v) | 
					
						
							|  |  |  | 	if rv.Type().Kind() != reflect.Ptr { | 
					
						
							|  |  |  | 		return errors.ErrDecodeRequiredPointerType | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if d.isInitialized() { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 		if err := d.decode(ctx, rv); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 			if err == io.EOF { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to decode") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := d.decodeInit(); err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to decodInit") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	if err := d.decode(ctx, rv); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 		if err == io.EOF { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to decode") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } |