| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-19 11:51:44 +03:00
										 |  |  | 	"golang.org/x/xerrors" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-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 | 
					
						
							| 
									
										
										
										
											2023-04-02 10:50:03 +09:00
										 |  |  | 	customUnmarshalerMap map[reflect.Type]func(interface{}, []byte) error | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	toCommentMap         CommentMap | 
					
						
							| 
									
										
										
										
											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{}, | 
					
						
							| 
									
										
										
										
											2023-04-02 10:50:03 +09:00
										 |  |  | 		customUnmarshalerMap: map[reflect.Type]func(interface{}, []byte) error{}, | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 13:26:00 +09:00
										 |  |  | func (d *Decoder) mapKeyNodeToString(node ast.MapKeyNode) string { | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 	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{}) { | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	d.setPathToCommentMap(node) | 
					
						
							| 
									
										
										
										
											2019-12-29 00:06:46 +09:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | func (d *Decoder) setPathToCommentMap(node ast.Node) { | 
					
						
							|  |  |  | 	if d.toCommentMap == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 	d.addHeadOrLineCommentToMap(node) | 
					
						
							|  |  |  | 	d.addFootCommentToMap(node) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) addHeadOrLineCommentToMap(node ast.Node) { | 
					
						
							|  |  |  | 	sequence, ok := node.(*ast.SequenceNode) | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		d.addSequenceNodeCommentToMap(sequence) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	commentGroup := node.GetComment() | 
					
						
							|  |  |  | 	if commentGroup == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	texts := []string{} | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 	targetLine := node.GetToken().Position.Line | 
					
						
							| 
									
										
										
										
											2023-03-28 17:49:13 +09:00
										 |  |  | 	minCommentLine := math.MaxInt | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	for _, comment := range commentGroup.Comments { | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 		if minCommentLine > comment.Token.Position.Line { | 
					
						
							|  |  |  | 			minCommentLine = comment.Token.Position.Line | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 		texts = append(texts, comment.Token.Value) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(texts) == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 	commentPath := node.GetPath() | 
					
						
							|  |  |  | 	if minCommentLine < targetLine { | 
					
						
							|  |  |  | 		d.addCommentToMap(commentPath, HeadComment(texts...)) | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 		d.addCommentToMap(commentPath, LineComment(texts[0])) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) addSequenceNodeCommentToMap(node *ast.SequenceNode) { | 
					
						
							|  |  |  | 	if len(node.ValueHeadComments) != 0 { | 
					
						
							|  |  |  | 		for idx, headComment := range node.ValueHeadComments { | 
					
						
							|  |  |  | 			if headComment == nil { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			texts := make([]string, 0, len(headComment.Comments)) | 
					
						
							|  |  |  | 			for _, comment := range headComment.Comments { | 
					
						
							|  |  |  | 				texts = append(texts, comment.Token.Value) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if len(texts) != 0 { | 
					
						
							|  |  |  | 				d.addCommentToMap(node.Values[idx].GetPath(), HeadComment(texts...)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	firstElemHeadComment := node.GetComment() | 
					
						
							|  |  |  | 	if firstElemHeadComment != nil { | 
					
						
							|  |  |  | 		texts := make([]string, 0, len(firstElemHeadComment.Comments)) | 
					
						
							|  |  |  | 		for _, comment := range firstElemHeadComment.Comments { | 
					
						
							|  |  |  | 			texts = append(texts, comment.Token.Value) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(texts) != 0 { | 
					
						
							|  |  |  | 			d.addCommentToMap(node.Values[0].GetPath(), HeadComment(texts...)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) addFootCommentToMap(node ast.Node) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		footComment     *ast.CommentGroupNode | 
					
						
							|  |  |  | 		footCommentPath string = node.GetPath() | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.SequenceNode: | 
					
						
							|  |  |  | 		if len(n.Values) != 0 { | 
					
						
							|  |  |  | 			footCommentPath = n.Values[len(n.Values)-1].GetPath() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		footComment = n.FootComment | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							|  |  |  | 		footComment = n.FootComment | 
					
						
							|  |  |  | 	case *ast.MappingValueNode: | 
					
						
							|  |  |  | 		footComment = n.FootComment | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if footComment == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var texts []string | 
					
						
							|  |  |  | 	for _, comment := range footComment.Comments { | 
					
						
							|  |  |  | 		texts = append(texts, comment.Token.Value) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(texts) != 0 { | 
					
						
							|  |  |  | 		d.addCommentToMap(footCommentPath, FootComment(texts...)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) addCommentToMap(path string, comment *Comment) { | 
					
						
							|  |  |  | 	for _, c := range d.toCommentMap[path] { | 
					
						
							|  |  |  | 		if c.Position == comment.Position { | 
					
						
							|  |  |  | 			// already added same comment | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-03-01 16:59:07 +09:00
										 |  |  | 	d.toCommentMap[path] = append(d.toCommentMap[path], comment) | 
					
						
							|  |  |  | 	sort.Slice(d.toCommentMap[path], func(i, j int) bool { | 
					
						
							|  |  |  | 		return d.toCommentMap[path][i].Position < d.toCommentMap[path][j].Position | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | func (d *Decoder) nodeToValue(node ast.Node) interface{} { | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	d.setPathToCommentMap(node) | 
					
						
							| 
									
										
										
										
											2019-10-18 00:00:58 +09:00
										 |  |  | 	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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.MappingNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		for idx, v := range n.Values { | 
					
						
							|  |  |  | 			value, err := d.resolveAlias(v) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			n.Values[idx] = value.(*ast.MappingValueNode) | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 	case *ast.TagNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		value, err := d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		n.Value = value | 
					
						
							| 
									
										
										
										
											2020-07-02 17:26:35 +09:00
										 |  |  | 	case *ast.MappingKeyNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		value, err := d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		n.Value = 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 { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 			value, err := d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-06-11 20:40:27 +09:00
										 |  |  | 			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 { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 			key, err := d.resolveAlias(n.Key) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			n.Key = key.(ast.MapKeyNode) | 
					
						
							|  |  |  | 			value, err := d.resolveAlias(n.Value) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			n.Value = value | 
					
						
							| 
									
										
										
										
											2020-06-11 20:40:27 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	case *ast.SequenceNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		for idx, v := range n.Values { | 
					
						
							|  |  |  | 			value, err := d.resolveAlias(v) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			n.Values[idx] = value | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	case *ast.AliasNode: | 
					
						
							|  |  |  | 		aliasName := n.Value.GetToken().Value | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		node := d.anchorNodeMap[aliasName] | 
					
						
							|  |  |  | 		if node == nil { | 
					
						
							|  |  |  | 			return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return d.resolveAlias(node) | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 	return node, nil | 
					
						
							| 
									
										
										
										
											2020-06-11 19:42:23 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 		return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.MappingType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 		return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	mapNode, ok := node.(ast.MapNode) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 		return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.SequenceType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 		return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											2019-10-24 23:54:17 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	arrayNode, ok := node.(ast.ArrayNode) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | 		return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (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) { | 
					
						
							| 
									
										
										
										
											2024-07-16 11:38:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Special case for "strings -> floats" aka scientific notation | 
					
						
							|  |  |  | 			// If the destination type is a float and the source type is a string, check if we can | 
					
						
							|  |  |  | 			// use strconv.ParseFloat to convert the string to a float. | 
					
						
							|  |  |  | 			if (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && | 
					
						
							|  |  |  | 				v.Type().Kind() == reflect.String { | 
					
						
							|  |  |  | 				if f, err := strconv.ParseFloat(v.String(), 64); err == nil { | 
					
						
							|  |  |  | 					if typ.Kind() == reflect.Float32 { | 
					
						
							|  |  |  | 						return reflect.ValueOf(float32(f)), nil | 
					
						
							|  |  |  | 					} else if typ.Kind() == reflect.Float64 { | 
					
						
							|  |  |  | 						return reflect.ValueOf(f), nil | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					// else, fall through to the error below | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 			return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 		return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) | 
					
						
							| 
									
										
										
										
											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} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | func errTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *errors.TypeError { | 
					
						
							|  |  |  | 	return &errors.TypeError{DstType: dstType, SrcType: srcType, Token: token} | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04:00
										 |  |  | func errUnexpectedNodeType(actual, expected ast.NodeType, tk *token.Token) error { | 
					
						
							| 
									
										
										
										
											2021-06-29 16:33:16 -04:00
										 |  |  | 	return errors.ErrSyntax(fmt.Sprintf("%s was used where %s is expected", actual.YAMLName(), expected.YAMLName()), tk) | 
					
						
							| 
									
										
										
										
											2021-06-25 12:34:27 -04: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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | func (d *Decoder) unmarshalableDocument(node ast.Node) ([]byte, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	node, err = d.resolveAlias(node) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 	doc := node.String() | 
					
						
							|  |  |  | 	last := d.lastNode(node) | 
					
						
							|  |  |  | 	if last != nil && last.Type() == ast.LiteralType { | 
					
						
							|  |  |  | 		doc += "\n" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 	return []byte(doc), nil | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | func (d *Decoder) unmarshalableText(node ast.Node) ([]byte, bool, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	node, err = d.resolveAlias(node) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, false, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 	if node.Type() == ast.AnchorType { | 
					
						
							|  |  |  | 		node = node.(*ast.AnchorNode).Value | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *ast.StringNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		return []byte(n.Value), true, nil | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 	case *ast.LiteralNode: | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		return []byte(n.Value.GetToken().Value), true, nil | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		scalar, ok := n.(ast.ScalarNode) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 			return []byte(fmt.Sprint(scalar.GetValue())), true, nil | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 	return nil, false, nil | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 19:00:49 +09:00
										 |  |  | type jsonUnmarshaler interface { | 
					
						
							|  |  |  | 	UnmarshalJSON([]byte) error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-02 10:50:03 +09:00
										 |  |  | func (d *Decoder) existsTypeInCustomUnmarshalerMap(t reflect.Type) bool { | 
					
						
							|  |  |  | 	if _, exists := d.customUnmarshalerMap[t]; exists { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	globalCustomUnmarshalerMu.Lock() | 
					
						
							|  |  |  | 	defer globalCustomUnmarshalerMu.Unlock() | 
					
						
							|  |  |  | 	if _, exists := globalCustomUnmarshalerMap[t]; exists { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) unmarshalerFromCustomUnmarshalerMap(t reflect.Type) (func(interface{}, []byte) error, bool) { | 
					
						
							|  |  |  | 	if unmarshaler, exists := d.customUnmarshalerMap[t]; exists { | 
					
						
							|  |  |  | 		return unmarshaler, exists | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	globalCustomUnmarshalerMu.Lock() | 
					
						
							|  |  |  | 	defer globalCustomUnmarshalerMu.Unlock() | 
					
						
							|  |  |  | 	if unmarshaler, exists := globalCustomUnmarshalerMap[t]; exists { | 
					
						
							|  |  |  | 		return unmarshaler, exists | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | func (d *Decoder) canDecodeByUnmarshaler(dst reflect.Value) bool { | 
					
						
							| 
									
										
										
										
											2023-04-02 10:50:03 +09:00
										 |  |  | 	ptrValue := dst.Addr() | 
					
						
							|  |  |  | 	if d.existsTypeInCustomUnmarshalerMap(ptrValue.Type()) { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	iface := ptrValue.Interface() | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	switch iface.(type) { | 
					
						
							|  |  |  | 	case BytesUnmarshalerContext: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case BytesUnmarshaler: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case InterfaceUnmarshalerContext: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case InterfaceUnmarshaler: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	case *time.Time: | 
					
						
							|  |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2021-08-11 15:02:20 -04:00
										 |  |  | 	case *time.Duration: | 
					
						
							|  |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2023-04-02 10:50:03 +09:00
										 |  |  | 	ptrValue := dst.Addr() | 
					
						
							|  |  |  | 	if unmarshaler, exists := d.unmarshalerFromCustomUnmarshalerMap(ptrValue.Type()); exists { | 
					
						
							|  |  |  | 		b, err := d.unmarshalableDocument(src) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := unmarshaler(ptrValue.Interface(), b); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	iface := ptrValue.Interface() | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if unmarshaler, ok := iface.(BytesUnmarshalerContext); ok { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		b, err := d.unmarshalableDocument(src) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := unmarshaler.UnmarshalYAML(ctx, b); err != nil { | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 			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 { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		b, err := d.unmarshalableDocument(src) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalYAML") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := unmarshaler.UnmarshalYAML(b); 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) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 15:02:20 -04:00
										 |  |  | 	if _, ok := iface.(*time.Duration); ok { | 
					
						
							|  |  |  | 		return d.decodeDuration(ctx, dst, src) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 19:27:58 +09:00
										 |  |  | 	if unmarshaler, isText := iface.(encoding.TextUnmarshaler); isText { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 		b, ok, err := d.unmarshalableText(src) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to UnmarshalText") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-23 12:39:50 +09:00
										 |  |  | 		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 { | 
					
						
							| 
									
										
										
										
											2022-09-16 12:52:14 +02:00
										 |  |  | 			b, err := d.unmarshalableDocument(src) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to UnmarshalJSON") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			jsonBytes, err := YAMLToJSON(b) | 
					
						
							| 
									
										
										
										
											2020-10-26 19:00:49 +09:00
										 |  |  | 			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 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-07-16 11:38:06 +01:00
										 |  |  | 		case string: // handle scientific notation | 
					
						
							|  |  |  | 			if i, err := strconv.ParseFloat(vv, 64); err == nil { | 
					
						
							|  |  |  | 				if 0 <= i && i <= math.MaxUint64 && !dst.OverflowInt(int64(i)) { | 
					
						
							|  |  |  | 					dst.SetInt(int64(i)) | 
					
						
							|  |  |  | 					return nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { // couldn't be parsed as float | 
					
						
							|  |  |  | 				return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:36 +09:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 			return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-07-16 11:38:06 +01:00
										 |  |  | 		case string: // handle scientific notation | 
					
						
							|  |  |  | 			if i, err := strconv.ParseFloat(vv, 64); err == nil { | 
					
						
							|  |  |  | 				if 0 <= i && i <= math.MaxUint64 && !dst.OverflowUint(uint64(i)) { | 
					
						
							|  |  |  | 					dst.SetUint(uint64(i)) | 
					
						
							|  |  |  | 					return nil | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { // couldn't be parsed as float | 
					
						
							|  |  |  | 				return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-01 12:43:36 +09:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 			return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) | 
					
						
							| 
									
										
										
										
											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() { | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 		convertedValue, err := d.convertValue(v, dst.Type(), src) | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 		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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | func (d *Decoder) createDecodedNewValue( | 
					
						
							|  |  |  | 	ctx context.Context, typ reflect.Type, defaultVal reflect.Value, 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) | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 	for defaultVal.Kind() == reflect.Ptr { | 
					
						
							|  |  |  | 		defaultVal = defaultVal.Elem() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if defaultVal.IsValid() && defaultVal.Type().AssignableTo(newValue.Type()) { | 
					
						
							|  |  |  | 		newValue.Set(defaultVal) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 		return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v), src.GetToken()) | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2021-08-18 01:13:25 -04:00
										 |  |  | 		return errors.Wrapf(err, "failed to convert to time") | 
					
						
							| 
									
										
										
										
											2019-11-01 14:09:33 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-01 14:22:06 +09:00
										 |  |  | 	dst.Set(reflect.ValueOf(t)) | 
					
						
							| 
									
										
										
										
											2021-08-11 15:02:20 -04:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) castToDuration(src ast.Node) (time.Duration, error) { | 
					
						
							|  |  |  | 	if src == nil { | 
					
						
							|  |  |  | 		return 0, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v := d.nodeToValue(src) | 
					
						
							|  |  |  | 	if t, ok := v.(time.Duration); ok { | 
					
						
							|  |  |  | 		return t, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s, ok := v.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2022-02-09 23:06:32 +00:00
										 |  |  | 		return 0, errTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v), src.GetToken()) | 
					
						
							| 
									
										
										
										
											2021-08-11 15:02:20 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	t, err := time.ParseDuration(s) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, errors.Wrapf(err, "failed to parse duration") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return t, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *Decoder) decodeDuration(ctx context.Context, dst reflect.Value, src ast.Node) error { | 
					
						
							|  |  |  | 	t, err := d.castToDuration(src) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-18 01:13:25 -04:00
										 |  |  | 		return errors.Wrapf(err, "failed to convert to duration") | 
					
						
							| 
									
										
										
										
											2021-08-11 15:02:20 -04: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
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 			newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), fieldValue, mapNode) | 
					
						
							| 
									
										
										
										
											2019-12-18 13:26:59 +09:00
										 |  |  | 			if d.disallowUnknownField { | 
					
						
							| 
									
										
										
										
											2021-08-10 00:33:19 -04: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 | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | 				var te *errors.TypeError | 
					
						
							| 
									
										
										
										
											2019-12-13 15:00:04 +09:00
										 |  |  | 				if xerrors.As(err, &te) { | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | 					if te.StructFieldName != nil { | 
					
						
							|  |  |  | 						fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.StructFieldName) | 
					
						
							|  |  |  | 						te.StructFieldName = &fieldName | 
					
						
							| 
									
										
										
										
											2019-12-11 00:41:05 +09:00
										 |  |  | 					} else { | 
					
						
							|  |  |  | 						fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | 						te.StructFieldName = &fieldName | 
					
						
							| 
									
										
										
										
											2019-12-11 00:41:05 +09:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 		newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), fieldValue, 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 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | 			var te *errors.TypeError | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 			if xerrors.As(err, &te) { | 
					
						
							|  |  |  | 				fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) | 
					
						
							| 
									
										
										
										
											2022-05-02 18:00:24 +00:00
										 |  |  | 				te.StructFieldName = &fieldName | 
					
						
							| 
									
										
										
										
											2019-12-10 14:33:08 +09:00
										 |  |  | 				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") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 00:04:14 -04:00
										 |  |  | 	// Ignore unknown fields when parsing an inline struct (recognized by a nil token). | 
					
						
							|  |  |  | 	// Unknown fields are expected (they could be fields from the parent struct). | 
					
						
							| 
									
										
										
										
											2021-08-10 03:38:16 -04:00
										 |  |  | 	if len(unknownFields) != 0 && d.disallowUnknownField && src.GetToken() != nil { | 
					
						
							| 
									
										
										
										
											2020-07-12 19:02:23 +03:00
										 |  |  | 		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()) | 
					
						
							| 
									
										
										
										
											2021-04-24 17:06:35 -04:00
										 |  |  | 					} else if t := src.GetToken(); t != nil && t.Prev != nil && t.Prev.Prev != nil { | 
					
						
							|  |  |  | 						// A missing required field will not be in the keyToNodeMap | 
					
						
							|  |  |  | 						// the error needs to be associated with the parent of the source node | 
					
						
							|  |  |  | 						return errors.ErrSyntax(fmt.Sprintf("%s", err), t.Prev.Prev) | 
					
						
							| 
									
										
										
										
											2019-10-26 10:08:44 +09:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-08-10 03:38:16 -04:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-10-26 10:08:44 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 			dstValue, err := d.createDecodedNewValue(ctx, elemType, reflect.Value{}, 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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 		dstValue, err := d.createDecodedNewValue(ctx, elemType, reflect.Value{}, 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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-06-19 11:51:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		k := d.createDecodableValue(keyType) | 
					
						
							|  |  |  | 		if d.canDecodeByUnmarshaler(k) { | 
					
						
							|  |  |  | 			if err := d.decodeByUnmarshaler(ctx, k, key); err != nil { | 
					
						
							|  |  |  | 				return errors.Wrapf(err, "failed to decode by unmarshaler") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			k = reflect.ValueOf(d.nodeToValue(key)) | 
					
						
							|  |  |  | 			if k.IsValid() && k.Type().ConvertibleTo(keyType) { | 
					
						
							|  |  |  | 				k = k.Convert(keyType) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-06-19 11:51:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-10-15 15:11:46 +02:00
										 |  |  | 		dstValue, err := d.createDecodedNewValue(ctx, valueType, reflect.Value{}, 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 { | 
					
						
							| 
									
										
										
										
											2024-02-26 01:11:21 -05:00
										 |  |  | 		bytes, err := io.ReadAll(reader) | 
					
						
							| 
									
										
										
										
											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 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) { | 
					
						
							| 
									
										
										
										
											2021-09-07 19:49:15 +09:00
										 |  |  | 	var parseMode parser.Mode | 
					
						
							|  |  |  | 	if d.toCommentMap != nil { | 
					
						
							|  |  |  | 		parseMode = parser.ParseComments | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	f, err := parser.ParseBytes(bytes, parseMode) | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2021-11-03 20:37:55 -04:00
										 |  |  | 		return errors.Wrapf(err, "failed to decodeInit") | 
					
						
							| 
									
										
										
										
											2020-06-01 16:14:20 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-19 20:49:54 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | // DecodeFromNode decodes node into the value pointed to by v. | 
					
						
							|  |  |  | func (d *Decoder) DecodeFromNode(node ast.Node, v interface{}) error { | 
					
						
							|  |  |  | 	return d.DecodeFromNodeContext(context.Background(), node, v) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DecodeFromNodeContext decodes node into the value pointed to by v with context.Context. | 
					
						
							|  |  |  | func (d *Decoder) DecodeFromNodeContext(ctx context.Context, node ast.Node, v interface{}) error { | 
					
						
							|  |  |  | 	rv := reflect.ValueOf(v) | 
					
						
							|  |  |  | 	if rv.Type().Kind() != reflect.Ptr { | 
					
						
							|  |  |  | 		return errors.ErrDecodeRequiredPointerType | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !d.isInitialized() { | 
					
						
							|  |  |  | 		if err := d.decodeInit(); err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to decodInit") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-20 02:13:35 +09:00
										 |  |  | 	// resolve references to the anchor on the same file | 
					
						
							|  |  |  | 	d.nodeToValue(node) | 
					
						
							| 
									
										
										
										
											2021-07-19 20:49:54 +09:00
										 |  |  | 	if err := d.decodeValue(ctx, rv.Elem(), node); err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "failed to decode value") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |