diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:41:41 +0000 |
commit | 5d920465245906e2250c288c2b1ffea608a37539 (patch) | |
tree | 8d52f82e5d4a1717f136c7e5f6c389464c403e79 /dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go | |
parent | Releasing progress-linux version 1.1.1-2~progress7.99u1. (diff) | |
download | icingadb-5d920465245906e2250c288c2b1ffea608a37539.tar.xz icingadb-5d920465245906e2250c288c2b1ffea608a37539.zip |
Merging upstream version 1.2.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go')
-rw-r--r-- | dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go | 1753 |
1 files changed, 0 insertions, 1753 deletions
diff --git a/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go b/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go deleted file mode 100644 index d3dbabc..0000000 --- a/dependencies/pkg/mod/github.com/goccy/go-yaml@v1.11.0/decode.go +++ /dev/null @@ -1,1753 +0,0 @@ -package yaml - -import ( - "bytes" - "context" - "encoding" - "encoding/base64" - "fmt" - "io" - "io/ioutil" - "math" - "os" - "path/filepath" - "reflect" - "sort" - "strconv" - "time" - - "github.com/goccy/go-yaml/ast" - "github.com/goccy/go-yaml/internal/errors" - "github.com/goccy/go-yaml/parser" - "github.com/goccy/go-yaml/token" - "golang.org/x/xerrors" -) - -// Decoder reads and decodes YAML values from an input stream. -type Decoder struct { - reader io.Reader - referenceReaders []io.Reader - anchorNodeMap map[string]ast.Node - anchorValueMap map[string]reflect.Value - customUnmarshalerMap map[reflect.Type]func(interface{}, []byte) error - toCommentMap CommentMap - opts []DecodeOption - referenceFiles []string - referenceDirs []string - isRecursiveDir bool - isResolvedReference bool - validator StructValidator - disallowUnknownField bool - disallowDuplicateKey bool - useOrderedMap bool - useJSONUnmarshaler bool - parsedFile *ast.File - streamIndex int -} - -// NewDecoder returns a new decoder that reads from r. -func NewDecoder(r io.Reader, opts ...DecodeOption) *Decoder { - return &Decoder{ - reader: r, - anchorNodeMap: map[string]ast.Node{}, - anchorValueMap: map[string]reflect.Value{}, - customUnmarshalerMap: map[reflect.Type]func(interface{}, []byte) error{}, - opts: opts, - referenceReaders: []io.Reader{}, - referenceFiles: []string{}, - referenceDirs: []string{}, - isRecursiveDir: false, - isResolvedReference: false, - disallowUnknownField: false, - disallowDuplicateKey: false, - useOrderedMap: false, - } -} - -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) - case float32: - return float64(vv) - case float64: - return vv - case string: - // if error occurred, return zero value - f, _ := strconv.ParseFloat(vv, 64) - return f - } - return 0 -} - -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 -} - -func (d *Decoder) mapKeyNodeToString(node ast.MapKeyNode) string { - key := d.nodeToValue(node) - if key == nil { - return "null" - } - if k, ok := key.(string); ok { - return k - } - return fmt.Sprint(key) -} - -func (d *Decoder) setToMapValue(node ast.Node, m map[string]interface{}) { - d.setPathToCommentMap(node) - switch n := node.(type) { - case *ast.MappingValueNode: - if n.Key.Type() == ast.MergeKeyType { - d.setToMapValue(d.mergeValueNode(n.Value), m) - } else { - key := d.mapKeyNodeToString(n.Key) - m[key] = d.nodeToValue(n.Value) - } - case *ast.MappingNode: - for _, value := range n.Values { - d.setToMapValue(value, m) - } - case *ast.AnchorNode: - anchorName := n.Name.GetToken().Value - d.anchorNodeMap[anchorName] = n.Value - } -} - -func (d *Decoder) setToOrderedMapValue(node ast.Node, m *MapSlice) { - switch n := node.(type) { - case *ast.MappingValueNode: - if n.Key.Type() == ast.MergeKeyType { - d.setToOrderedMapValue(d.mergeValueNode(n.Value), m) - } else { - key := d.mapKeyNodeToString(n.Key) - *m = append(*m, MapItem{Key: key, Value: d.nodeToValue(n.Value)}) - } - case *ast.MappingNode: - for _, value := range n.Values { - d.setToOrderedMapValue(value, m) - } - } -} - -func (d *Decoder) setPathToCommentMap(node ast.Node) { - if d.toCommentMap == nil { - return - } - d.addHeadOrLineCommentToMap(node) - d.addFootCommentToMap(node) -} - -func (d *Decoder) addHeadOrLineCommentToMap(node ast.Node) { - sequence, ok := node.(*ast.SequenceNode) - if ok { - d.addSequenceNodeCommentToMap(sequence) - return - } - commentGroup := node.GetComment() - if commentGroup == nil { - return - } - texts := []string{} - targetLine := node.GetToken().Position.Line - minCommentLine := math.MaxInt - for _, comment := range commentGroup.Comments { - if minCommentLine > comment.Token.Position.Line { - minCommentLine = comment.Token.Position.Line - } - texts = append(texts, comment.Token.Value) - } - if len(texts) == 0 { - return - } - commentPath := node.GetPath() - if minCommentLine < targetLine { - d.addCommentToMap(commentPath, HeadComment(texts...)) - } else { - 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 - } - } - 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 - }) -} - -func (d *Decoder) nodeToValue(node ast.Node) interface{} { - d.setPathToCommentMap(node) - 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: - switch token.ReservedTagKeyword(n.Start.Value) { - case token.TimestampTag: - t, _ := d.castToTime(n.Value) - return t - case token.IntegerTag: - i, _ := strconv.Atoi(fmt.Sprint(d.nodeToValue(n.Value))) - return i - case token.FloatTag: - return d.castToFloat(d.nodeToValue(n.Value)) - case token.NullTag: - return nil - case token.BinaryTag: - b, _ := base64.StdEncoding.DecodeString(d.nodeToValue(n.Value).(string)) - return b - case token.StringTag: - return d.nodeToValue(n.Value) - case token.MappingTag: - return d.nodeToValue(n.Value) - } - case *ast.AnchorNode: - anchorName := n.Name.GetToken().Value - anchorValue := d.nodeToValue(n.Value) - d.anchorNodeMap[anchorName] = n.Value - return anchorValue - case *ast.AliasNode: - aliasName := n.Value.GetToken().Value - node := d.anchorNodeMap[aliasName] - return d.nodeToValue(node) - case *ast.LiteralNode: - return n.Value.GetValue() - case *ast.MappingKeyNode: - return d.nodeToValue(n.Value) - case *ast.MappingValueNode: - if n.Key.Type() == ast.MergeKeyType { - value := d.mergeValueNode(n.Value) - if d.useOrderedMap { - m := MapSlice{} - d.setToOrderedMapValue(value, &m) - return m - } - m := map[string]interface{}{} - d.setToMapValue(value, m) - return m - } - key := d.mapKeyNodeToString(n.Key) - if d.useOrderedMap { - return MapSlice{{Key: key, Value: d.nodeToValue(n.Value)}} - } - return map[string]interface{}{ - key: d.nodeToValue(n.Value), - } - case *ast.MappingNode: - if d.useOrderedMap { - m := make(MapSlice, 0, len(n.Values)) - for _, value := range n.Values { - d.setToOrderedMapValue(value, &m) - } - return m - } - m := make(map[string]interface{}, len(n.Values)) - for _, value := range n.Values { - d.setToMapValue(value, m) - } - return m - case *ast.SequenceNode: - v := make([]interface{}, 0, len(n.Values)) - for _, value := range n.Values { - v = append(v, d.nodeToValue(value)) - } - return v - } - return nil -} - -func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { - switch n := node.(type) { - case *ast.MappingNode: - for idx, v := range n.Values { - value, err := d.resolveAlias(v) - if err != nil { - return nil, err - } - n.Values[idx] = value.(*ast.MappingValueNode) - } - case *ast.TagNode: - value, err := d.resolveAlias(n.Value) - if err != nil { - return nil, err - } - n.Value = value - case *ast.MappingKeyNode: - value, err := d.resolveAlias(n.Value) - if err != nil { - return nil, err - } - n.Value = value - case *ast.MappingValueNode: - if n.Key.Type() == ast.MergeKeyType && n.Value.Type() == ast.AliasType { - value, err := d.resolveAlias(n.Value) - if err != nil { - return nil, err - } - keyColumn := n.Key.GetToken().Position.Column - requiredColumn := keyColumn + 2 - value.AddColumn(requiredColumn) - n.Value = value - } else { - 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 - } - case *ast.SequenceNode: - for idx, v := range n.Values { - value, err := d.resolveAlias(v) - if err != nil { - return nil, err - } - n.Values[idx] = value - } - case *ast.AliasNode: - aliasName := n.Value.GetToken().Value - node := d.anchorNodeMap[aliasName] - if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) - } - return d.resolveAlias(node) - } - return node, nil -} - -func (d *Decoder) getMapNode(node ast.Node) (ast.MapNode, error) { - if _, ok := node.(*ast.NullNode); ok { - return nil, nil - } - if anchor, ok := node.(*ast.AnchorNode); ok { - mapNode, ok := anchor.Value.(ast.MapNode) - if ok { - return mapNode, nil - } - return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.MappingType, node.GetToken()) - } - if alias, ok := node.(*ast.AliasNode); ok { - aliasName := alias.Value.GetToken().Value - node := d.anchorNodeMap[aliasName] - if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) - } - mapNode, ok := node.(ast.MapNode) - if ok { - return mapNode, nil - } - return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) - } - mapNode, ok := node.(ast.MapNode) - if !ok { - return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) - } - return mapNode, nil -} - -func (d *Decoder) getArrayNode(node ast.Node) (ast.ArrayNode, error) { - if _, ok := node.(*ast.NullNode); ok { - return nil, nil - } - if anchor, ok := node.(*ast.AnchorNode); ok { - arrayNode, ok := anchor.Value.(ast.ArrayNode) - if ok { - return arrayNode, nil - } - - return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.SequenceType, node.GetToken()) - } - if alias, ok := node.(*ast.AliasNode); ok { - aliasName := alias.Value.GetToken().Value - node := d.anchorNodeMap[aliasName] - if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) - } - arrayNode, ok := node.(ast.ArrayNode) - if ok { - return arrayNode, nil - } - return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) - } - arrayNode, ok := node.(ast.ArrayNode) - if !ok { - return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) - } - return arrayNode, nil -} - -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 - } - } - return nil -} - -func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) { - if typ.Kind() != reflect.String { - if !v.Type().ConvertibleTo(typ) { - return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) - } - return v.Convert(typ), nil - } - // cast value to string - switch v.Type().Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return reflect.ValueOf(fmt.Sprint(v.Int())), nil - case reflect.Float32, reflect.Float64: - return reflect.ValueOf(fmt.Sprint(v.Float())), nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return reflect.ValueOf(fmt.Sprint(v.Uint())), nil - case reflect.Bool: - return reflect.ValueOf(fmt.Sprint(v.Bool())), nil - } - if !v.Type().ConvertibleTo(typ) { - return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) - } - return v.Convert(typ), nil -} - -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} -} - -func errTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *errors.TypeError { - return &errors.TypeError{DstType: dstType, SrcType: srcType, Token: token} -} - -type unknownFieldError struct { - err error -} - -func (e *unknownFieldError) Error() string { - return e.err.Error() -} - -func errUnknownField(msg string, tk *token.Token) *unknownFieldError { - return &unknownFieldError{err: errors.ErrSyntax(msg, tk)} -} - -func errUnexpectedNodeType(actual, expected ast.NodeType, tk *token.Token) error { - return errors.ErrSyntax(fmt.Sprintf("%s was used where %s is expected", actual.YAMLName(), expected.YAMLName()), tk) -} - -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)} -} - -func (d *Decoder) deleteStructKeys(structType reflect.Type, unknownFields map[string]ast.Node) error { - if structType.Kind() == reflect.Ptr { - structType = structType.Elem() - } - structFieldMap, err := structFieldMap(structType) - if err != nil { - return errors.Wrapf(err, "failed to create struct field map") - } - - for j := 0; j < structType.NumField(); j++ { - field := structType.Field(j) - if isIgnoredStructField(field) { - continue - } - - structField, exists := structFieldMap[field.Name] - if !exists { - continue - } - - if structField.IsInline { - d.deleteStructKeys(field.Type, unknownFields) - } else { - delete(unknownFields, structField.RenderName) - } - } - return nil -} - -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 -} - -func (d *Decoder) unmarshalableDocument(node ast.Node) ([]byte, error) { - var err error - node, err = d.resolveAlias(node) - if err != nil { - return nil, err - } - doc := node.String() - last := d.lastNode(node) - if last != nil && last.Type() == ast.LiteralType { - doc += "\n" - } - return []byte(doc), nil -} - -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 - } - if node.Type() == ast.AnchorType { - node = node.(*ast.AnchorNode).Value - } - switch n := node.(type) { - case *ast.StringNode: - return []byte(n.Value), true, nil - case *ast.LiteralNode: - return []byte(n.Value.GetToken().Value), true, nil - default: - scalar, ok := n.(ast.ScalarNode) - if ok { - return []byte(fmt.Sprint(scalar.GetValue())), true, nil - } - } - return nil, false, nil -} - -type jsonUnmarshaler interface { - UnmarshalJSON([]byte) error -} - -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 -} - -func (d *Decoder) canDecodeByUnmarshaler(dst reflect.Value) bool { - ptrValue := dst.Addr() - if d.existsTypeInCustomUnmarshalerMap(ptrValue.Type()) { - return true - } - iface := ptrValue.Interface() - switch iface.(type) { - case BytesUnmarshalerContext: - return true - case BytesUnmarshaler: - return true - case InterfaceUnmarshalerContext: - return true - case InterfaceUnmarshaler: - return true - case *time.Time: - return true - case *time.Duration: - return true - case encoding.TextUnmarshaler: - return true - case jsonUnmarshaler: - return d.useJSONUnmarshaler - } - return false -} - -func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, src ast.Node) error { - 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() - - if unmarshaler, ok := iface.(BytesUnmarshalerContext); ok { - b, err := d.unmarshalableDocument(src) - if err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") - } - if err := unmarshaler.UnmarshalYAML(ctx, b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") - } - return nil - } - - if unmarshaler, ok := iface.(BytesUnmarshaler); ok { - b, err := d.unmarshalableDocument(src) - if err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") - } - if err := unmarshaler.UnmarshalYAML(b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") - } - return nil - } - - 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 { - if err := unmarshaler.UnmarshalYAML(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 _, ok := iface.(*time.Time); ok { - return d.decodeTime(ctx, dst, src) - } - - if _, ok := iface.(*time.Duration); ok { - return d.decodeDuration(ctx, dst, src) - } - - if unmarshaler, isText := iface.(encoding.TextUnmarshaler); isText { - b, ok, err := d.unmarshalableText(src) - if err != nil { - return errors.Wrapf(err, "failed to UnmarshalText") - } - if ok { - if err := unmarshaler.UnmarshalText(b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalText") - } - return nil - } - } - - if d.useJSONUnmarshaler { - if unmarshaler, ok := iface.(jsonUnmarshaler); ok { - b, err := d.unmarshalableDocument(src) - if err != nil { - return errors.Wrapf(err, "failed to UnmarshalJSON") - } - jsonBytes, err := YAMLToJSON(b) - 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 - } - } - - return xerrors.Errorf("does not implemented Unmarshaler") -} - -var ( - astNodeType = reflect.TypeOf((*ast.Node)(nil)).Elem() -) - -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() - switch valueType.Kind() { - case reflect.Ptr: - if dst.IsNil() { - return nil - } - if src.Type() == ast.NullType { - // set nil value to pointer - dst.Set(reflect.Zero(valueType)) - return nil - } - v := d.createDecodableValue(dst.Type()) - if err := d.decodeValue(ctx, v, src); err != nil { - return errors.Wrapf(err, "failed to decode ptr value") - } - dst.Set(d.castToAssignableValue(v, dst.Type())) - case reflect.Interface: - if dst.Type() == astNodeType { - dst.Set(reflect.ValueOf(src)) - return nil - } - v := reflect.ValueOf(d.nodeToValue(src)) - if v.IsValid() { - dst.Set(v) - } - case reflect.Map: - return d.decodeMap(ctx, dst, src) - case reflect.Array: - return d.decodeArray(ctx, dst, src) - case reflect.Slice: - if mapSlice, ok := dst.Addr().Interface().(*MapSlice); ok { - return d.decodeMapSlice(ctx, mapSlice, src) - } - return d.decodeSlice(ctx, dst, src) - case reflect.Struct: - if mapItem, ok := dst.Addr().Interface().(*MapItem); ok { - return d.decodeMapItem(ctx, mapItem, src) - } - return d.decodeStruct(ctx, dst, src) - 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 - } - case uint64: - if vv <= math.MaxInt64 && !dst.OverflowInt(int64(vv)) { - dst.SetInt(int64(vv)) - return nil - } - case float64: - if vv <= math.MaxInt64 && !dst.OverflowInt(int64(vv)) { - dst.SetInt(int64(vv)) - return nil - } - default: - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) - } - return errOverflow(valueType, fmt.Sprint(v)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - v := d.nodeToValue(src) - switch vv := v.(type) { - case int64: - if 0 <= vv && !dst.OverflowUint(uint64(vv)) { - dst.SetUint(uint64(vv)) - return nil - } - case uint64: - if !dst.OverflowUint(vv) { - dst.SetUint(vv) - return nil - } - case float64: - if 0 <= vv && vv <= math.MaxUint64 && !dst.OverflowUint(uint64(vv)) { - dst.SetUint(uint64(vv)) - return nil - } - default: - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) - } - return errOverflow(valueType, fmt.Sprint(v)) - } - v := reflect.ValueOf(d.nodeToValue(src)) - if v.IsValid() { - convertedValue, err := d.convertValue(v, dst.Type(), src) - if err != nil { - return errors.Wrapf(err, "failed to convert value") - } - dst.Set(convertedValue) - } - return nil -} - -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 -} - -func (d *Decoder) createDecodedNewValue( - ctx context.Context, typ reflect.Type, defaultVal reflect.Value, node ast.Node, -) (reflect.Value, error) { - if node.Type() == ast.AliasType { - aliasName := node.(*ast.AliasNode).Value.GetToken().Value - newValue := d.anchorValueMap[aliasName] - if newValue.IsValid() { - return newValue, nil - } - } - if node.Type() == ast.NullType { - return reflect.Zero(typ), nil - } - newValue := d.createDecodableValue(typ) - for defaultVal.Kind() == reflect.Ptr { - defaultVal = defaultVal.Elem() - } - if defaultVal.IsValid() && defaultVal.Type().AssignableTo(newValue.Type()) { - newValue.Set(defaultVal) - } - if err := d.decodeValue(ctx, newValue, node); err != nil { - return newValue, errors.Wrapf(err, "failed to decode value") - } - return newValue, nil -} - -func (d *Decoder) keyToNodeMap(node ast.Node, ignoreMergeKey bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) { - mapNode, err := d.getMapNode(node) - if err != nil { - return nil, errors.Wrapf(err, "failed to get map node") - } - keyMap := map[string]struct{}{} - keyToNodeMap := map[string]ast.Node{} - if mapNode == nil { - return keyToNodeMap, nil - } - mapIter := mapNode.MapRange() - for mapIter.Next() { - keyNode := mapIter.Key() - if keyNode.Type() == ast.MergeKeyType { - if ignoreMergeKey { - continue - } - mergeMap, err := d.keyToNodeMap(mapIter.Value(), ignoreMergeKey, getKeyOrValueNode) - if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap by MergeKey node") - } - for k, v := range mergeMap { - if err := d.validateDuplicateKey(keyMap, k, v); err != nil { - return nil, errors.Wrapf(err, "invalid struct key") - } - keyToNodeMap[k] = v - } - } else { - key, ok := d.nodeToValue(keyNode).(string) - if !ok { - return nil, errors.Wrapf(err, "failed to decode map key") - } - if err := d.validateDuplicateKey(keyMap, key, keyNode); err != nil { - return nil, errors.Wrapf(err, "invalid struct key") - } - keyToNodeMap[key] = getKeyOrValueNode(mapIter) - } - } - return keyToNodeMap, nil -} - -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() }) - if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap") - } - return m, nil -} - -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() }) - if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap") - } - return m, nil -} - -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) - if isIgnoredStructField(field) { - continue - } - 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 -} - -// 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 -} - -func (d *Decoder) castToTime(src ast.Node) (time.Time, error) { - if src == nil { - return time.Time{}, nil - } - v := d.nodeToValue(src) - if t, ok := v.(time.Time); ok { - return t, nil - } - s, ok := v.(string) - if !ok { - return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v), src.GetToken()) - } - for _, format := range allowedTimestampFormats { - t, err := time.Parse(format, s) - if err != nil { - // invalid format - continue - } - return t, nil - } - return time.Time{}, nil -} - -func (d *Decoder) decodeTime(ctx context.Context, dst reflect.Value, src ast.Node) error { - t, err := d.castToTime(src) - if err != nil { - return errors.Wrapf(err, "failed to convert to time") - } - dst.Set(reflect.ValueOf(t)) - 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 { - return 0, errTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v), src.GetToken()) - } - 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 { - return errors.Wrapf(err, "failed to convert to duration") - } - dst.Set(reflect.ValueOf(t)) - return nil -} - -// 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 "" -} - -func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.Node) error { - if src == nil { - return nil - } - structType := dst.Type() - 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 - } - structFieldMap, err := structFieldMap(structType) - if err != nil { - return errors.Wrapf(err, "failed to create struct field map") - } - ignoreMergeKey := structFieldMap.hasMergeProperty() - keyToNodeMap, err := d.keyToValueNodeMap(src, ignoreMergeKey) - if err != nil { - return errors.Wrapf(err, "failed to get keyToValueNodeMap") - } - var unknownFields map[string]ast.Node - if d.disallowUnknownField { - unknownFields, err = d.keyToKeyNodeMap(src, ignoreMergeKey) - if err != nil { - return errors.Wrapf(err, "failed to get keyToKeyNodeMap") - } - } - - aliasName := d.getMergeAliasName(src) - var foundErr error - - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if isIgnoredStructField(field) { - continue - } - structField := structFieldMap[field.Name] - if structField.IsInline { - fieldValue := dst.FieldByName(field.Name) - if structField.IsAutoAlias { - if aliasName != "" { - newFieldValue := d.anchorValueMap[aliasName] - if newFieldValue.IsValid() { - fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) - } - } - continue - } - if !fieldValue.CanSet() { - return xerrors.Errorf("cannot set embedded type as unexported field %s.%s", field.PkgPath, field.Name) - } - if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { - // set nil value to pointer - fieldValue.Set(reflect.Zero(fieldValue.Type())) - continue - } - mapNode := ast.Mapping(nil, false) - for k, v := range keyToNodeMap { - key := &ast.StringNode{BaseNode: &ast.BaseNode{}, Value: k} - mapNode.Values = append(mapNode.Values, ast.MappingValue(nil, key, v)) - } - newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), fieldValue, mapNode) - if d.disallowUnknownField { - if err := d.deleteStructKeys(fieldValue.Type(), unknownFields); err != nil { - return errors.Wrapf(err, "cannot delete struct keys") - } - } - - if err != nil { - if foundErr != nil { - continue - } - var te *errors.TypeError - if xerrors.As(err, &te) { - if te.StructFieldName != nil { - fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.StructFieldName) - te.StructFieldName = &fieldName - } else { - fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) - te.StructFieldName = &fieldName - } - foundErr = te - continue - } else { - foundErr = err - } - continue - } - d.setDefaultValueIfConflicted(newFieldValue, structFieldMap) - fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) - continue - } - v, exists := keyToNodeMap[structField.RenderName] - if !exists { - continue - } - delete(unknownFields, structField.RenderName) - fieldValue := dst.FieldByName(field.Name) - if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { - // set nil value to pointer - fieldValue.Set(reflect.Zero(fieldValue.Type())) - continue - } - newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), fieldValue, v) - if err != nil { - if foundErr != nil { - continue - } - var te *errors.TypeError - if xerrors.As(err, &te) { - fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) - te.StructFieldName = &fieldName - foundErr = te - } else { - foundErr = err - } - continue - } - fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) - } - if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") - } - - // 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). - if len(unknownFields) != 0 && d.disallowUnknownField && src.GetToken() != nil { - for key, node := range unknownFields { - return errUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken()) - } - } - - if d.validator != nil { - if err := d.validator.Struct(dst.Interface()); err != nil { - 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() - structField, exists := structFieldMap[fieldName] - if !exists { - continue - } - node, exists := keyToNodeMap[structField.RenderName] - if exists { - // TODO: to make FieldError message cutomizable - return errors.ErrSyntax(fmt.Sprintf("%s", err), node.GetToken()) - } 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) - } - } - } - return err - } - } - return nil -} - -func (d *Decoder) decodeArray(ctx context.Context, dst reflect.Value, src ast.Node) error { - 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 - - var foundErr error - 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 { - dstValue, err := d.createDecodedNewValue(ctx, elemType, reflect.Value{}, v) - if err != nil { - if foundErr == nil { - foundErr = err - } - continue - } else { - arrayValue.Index(idx).Set(d.castToAssignableValue(dstValue, elemType)) - } - } - idx++ - } - dst.Set(arrayValue) - if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") - } - return nil -} - -func (d *Decoder) decodeSlice(ctx context.Context, dst reflect.Value, src ast.Node) error { - 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() - sliceType := dst.Type() - sliceValue := reflect.MakeSlice(sliceType, 0, iter.Len()) - elemType := sliceType.Elem() - - var foundErr error - for iter.Next() { - v := iter.Value() - if elemType.Kind() == reflect.Ptr && v.Type() == ast.NullType { - // set nil value to pointer - sliceValue = reflect.Append(sliceValue, reflect.Zero(elemType)) - continue - } - dstValue, err := d.createDecodedNewValue(ctx, elemType, reflect.Value{}, v) - if err != nil { - if foundErr == nil { - foundErr = err - } - continue - } - sliceValue = reflect.Append(sliceValue, d.castToAssignableValue(dstValue, elemType)) - } - dst.Set(sliceValue) - if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") - } - return nil -} - -func (d *Decoder) decodeMapItem(ctx context.Context, dst *MapItem, src ast.Node) error { - 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 { - if err := d.decodeMapItem(ctx, dst, value); err != nil { - 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 -} - -func (d *Decoder) validateDuplicateKey(keyMap map[string]struct{}, key interface{}, keyNode ast.Node) error { - 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 -} - -func (d *Decoder) decodeMapSlice(ctx context.Context, dst *MapSlice, src ast.Node) error { - 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() - keyMap := map[string]struct{}{} - for mapIter.Next() { - key := mapIter.Key() - value := mapIter.Value() - if key.Type() == ast.MergeKeyType { - var m MapSlice - if err := d.decodeMapSlice(ctx, &m, value); err != nil { - return errors.Wrapf(err, "failed to decode map with merge key") - } - for _, v := range m { - if err := d.validateDuplicateKey(keyMap, v.Key, value); err != nil { - return errors.Wrapf(err, "invalid map key") - } - mapSlice = append(mapSlice, v) - } - continue - } - k := d.nodeToValue(key) - if err := d.validateDuplicateKey(keyMap, k, key); err != nil { - return errors.Wrapf(err, "invalid map key") - } - mapSlice = append(mapSlice, MapItem{ - Key: k, - Value: d.nodeToValue(value), - }) - } - *dst = mapSlice - return nil -} - -func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node) error { - mapNode, err := d.getMapNode(src) - if err != nil { - return errors.Wrapf(err, "failed to get map node") - } - if mapNode == nil { - return nil - } - mapType := dst.Type() - mapValue := reflect.MakeMap(mapType) - keyType := mapValue.Type().Key() - valueType := mapValue.Type().Elem() - mapIter := mapNode.MapRange() - keyMap := map[string]struct{}{} - var foundErr error - for mapIter.Next() { - key := mapIter.Key() - value := mapIter.Value() - if key.Type() == ast.MergeKeyType { - if err := d.decodeMap(ctx, dst, value); err != nil { - return errors.Wrapf(err, "failed to decode map with merge key") - } - iter := dst.MapRange() - for iter.Next() { - if err := d.validateDuplicateKey(keyMap, iter.Key(), value); err != nil { - return errors.Wrapf(err, "invalid map key") - } - mapValue.SetMapIndex(iter.Key(), iter.Value()) - } - continue - } - k := reflect.ValueOf(d.nodeToValue(key)) - if k.IsValid() && k.Type().ConvertibleTo(keyType) { - k = k.Convert(keyType) - } - if k.IsValid() { - if err := d.validateDuplicateKey(keyMap, k.Interface(), key); err != nil { - return errors.Wrapf(err, "invalid map key") - } - } - if valueType.Kind() == reflect.Ptr && value.Type() == ast.NullType { - // set nil value to pointer - mapValue.SetMapIndex(k, reflect.Zero(valueType)) - continue - } - dstValue, err := d.createDecodedNewValue(ctx, valueType, reflect.Value{}, value) - if err != nil { - if foundErr == nil { - foundErr = err - } - } - if !k.IsValid() { - // expect nil key - mapValue.SetMapIndex(d.createDecodableValue(keyType), d.castToAssignableValue(dstValue, valueType)) - continue - } - mapValue.SetMapIndex(k, d.castToAssignableValue(dstValue, valueType)) - } - dst.Set(mapValue) - if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") - } - return nil -} - -func (d *Decoder) fileToReader(file string) (io.Reader, error) { - reader, err := os.Open(file) - if err != nil { - return nil, errors.Wrapf(err, "failed to open file") - } - 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) - if err != nil { - return nil, errors.Wrapf(err, "failed to get files by %s", pattern) - } - readers := []io.Reader{} - for _, match := range matches { - if !d.isYAMLFile(match) { - continue - } - reader, err := d.fileToReader(match) - if err != nil { - return nil, errors.Wrapf(err, "failed to get reader") - } - 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 { - return errors.Wrapf(err, "failed to get reader") - } - readers = append(readers, reader) - return nil - }); err != nil { - return nil, errors.Wrapf(err, "interrupt walk in %s", dir) - } - return readers, nil -} - -func (d *Decoder) resolveReference() error { - for _, opt := range d.opts { - if err := opt(d); err != nil { - return errors.Wrapf(err, "failed to exec option") - } - } - for _, file := range d.referenceFiles { - reader, err := d.fileToReader(file) - if err != nil { - return errors.Wrapf(err, "failed to get reader") - } - d.referenceReaders = append(d.referenceReaders, reader) - } - for _, dir := range d.referenceDirs { - if !d.isRecursiveDir { - readers, err := d.readersUnderDir(dir) - if err != nil { - return errors.Wrapf(err, "failed to get readers from under the %s", dir) - } - d.referenceReaders = append(d.referenceReaders, readers...) - } else { - readers, err := d.readersUnderDirRecursive(dir) - if err != nil { - return errors.Wrapf(err, "failed to get readers from under the %s", dir) - } - d.referenceReaders = append(d.referenceReaders, readers...) - } - } - for _, reader := range d.referenceReaders { - bytes, err := ioutil.ReadAll(reader) - if err != nil { - return errors.Wrapf(err, "failed to read buffer") - } - - // assign new anchor definition to anchorMap - if _, err := d.parse(bytes); err != nil { - return errors.Wrapf(err, "failed to decode") - } - } - d.isResolvedReference = true - return nil -} - -func (d *Decoder) parse(bytes []byte) (*ast.File, error) { - var parseMode parser.Mode - if d.toCommentMap != nil { - parseMode = parser.ParseComments - } - f, err := parser.ParseBytes(bytes, parseMode) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse yaml") - } - 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 -} - -func (d *Decoder) isInitialized() bool { - return d.parsedFile != nil -} - -func (d *Decoder) decodeInit() error { - if !d.isResolvedReference { - if err := d.resolveReference(); err != nil { - return errors.Wrapf(err, "failed to resolve reference") - } - } - var buf bytes.Buffer - if _, err := io.Copy(&buf, d.reader); err != nil { - return errors.Wrapf(err, "failed to copy from reader") - } - file, err := d.parse(buf.Bytes()) - if err != nil { - return errors.Wrapf(err, "failed to decode") - } - d.parsedFile = file - return nil -} - -func (d *Decoder) decode(ctx context.Context, v reflect.Value) error { - if len(d.parsedFile.Docs) <= d.streamIndex { - return io.EOF - } - body := d.parsedFile.Docs[d.streamIndex].Body - if body == nil { - return nil - } - if err := d.decodeValue(ctx, v.Elem(), body); err != nil { - return errors.Wrapf(err, "failed to decode value") - } - 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 { - 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 { - rv := reflect.ValueOf(v) - if rv.Type().Kind() != reflect.Ptr { - return errors.ErrDecodeRequiredPointerType - } - if d.isInitialized() { - if err := d.decode(ctx, rv); err != nil { - if err == io.EOF { - return err - } - return errors.Wrapf(err, "failed to decode") - } - return nil - } - if err := d.decodeInit(); err != nil { - return errors.Wrapf(err, "failed to decodeInit") - } - if err := d.decode(ctx, rv); err != nil { - if err == io.EOF { - return err - } - return errors.Wrapf(err, "failed to decode") - } - return nil -} - -// 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") - } - } - // resolve references to the anchor on the same file - d.nodeToValue(node) - if err := d.decodeValue(ctx, rv.Elem(), node); err != nil { - return errors.Wrapf(err, "failed to decode value") - } - return nil -} |