github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/yaml/path.go (about)

     1  package yaml
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"strconv"
     8  
     9  	"github.com/bingoohuang/gg/pkg/yaml/ast"
    10  	"github.com/bingoohuang/gg/pkg/yaml/internal/errors"
    11  	"github.com/bingoohuang/gg/pkg/yaml/parser"
    12  	"github.com/bingoohuang/gg/pkg/yaml/printer"
    13  )
    14  
    15  // PathString create Path from string
    16  //
    17  // YAMLPath rule
    18  // $     : the root object/element
    19  // .     : child operator
    20  // ..    : recursive descent
    21  // [num] : object/element of array by number
    22  // [*]   : all objects/elements for array.
    23  func PathString(s string) (*Path, error) {
    24  	buf := []rune(s)
    25  	length := len(buf)
    26  	cursor := 0
    27  	builder := &PathBuilder{}
    28  	for cursor < length {
    29  		c := buf[cursor]
    30  		switch c {
    31  		case '$':
    32  			builder = builder.Root()
    33  			cursor++
    34  		case '.':
    35  			b, c, err := parsePathDot(builder, buf, cursor)
    36  			if err != nil {
    37  				return nil, errors.Wrapf(err, "failed to parse path of dot")
    38  			}
    39  			builder = b
    40  			cursor = c
    41  		case '[':
    42  			b, c, err := parsePathIndex(builder, buf, cursor)
    43  			if err != nil {
    44  				return nil, errors.Wrapf(err, "failed to parse path of index")
    45  			}
    46  			builder = b
    47  			cursor = c
    48  		default:
    49  			return nil, errors.Wrapf(ErrInvalidPathString, "invalid path at %d", cursor)
    50  		}
    51  	}
    52  	return builder.Build(), nil
    53  }
    54  
    55  func parsePathRecursive(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, int, error) {
    56  	length := len(buf)
    57  	cursor += 2 // skip .. characters
    58  	start := cursor
    59  	for ; cursor < length; cursor++ {
    60  		c := buf[cursor]
    61  		switch c {
    62  		case '$':
    63  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '..' character")
    64  		case '*':
    65  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '..' character")
    66  		case '.', '[':
    67  			goto end
    68  		case ']':
    69  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '..' character")
    70  		}
    71  	}
    72  end:
    73  	if start == cursor {
    74  		return nil, 0, errors.Wrapf(ErrInvalidPathString, "not found recursive selector")
    75  	}
    76  	return b.Recursive(string(buf[start:cursor])), cursor, nil
    77  }
    78  
    79  func parsePathDot(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, int, error) {
    80  	length := len(buf)
    81  	if cursor+1 < length && buf[cursor+1] == '.' {
    82  		b, c, err := parsePathRecursive(b, buf, cursor)
    83  		if err != nil {
    84  			return nil, 0, errors.Wrapf(err, "failed to parse path of recursive")
    85  		}
    86  		return b, c, nil
    87  	}
    88  	cursor++ // skip . character
    89  	start := cursor
    90  	for ; cursor < length; cursor++ {
    91  		c := buf[cursor]
    92  		switch c {
    93  		case '$':
    94  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '.' character")
    95  		case '*':
    96  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '.' character")
    97  		case '.', '[':
    98  			goto end
    99  		case ']':
   100  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '.' character")
   101  		}
   102  	}
   103  end:
   104  	if start == cursor {
   105  		return nil, 0, errors.Wrapf(ErrInvalidPathString, "not found child selector")
   106  	}
   107  	return b.Child(string(buf[start:cursor])), cursor, nil
   108  }
   109  
   110  func parsePathIndex(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, int, error) {
   111  	length := len(buf)
   112  	cursor++ // skip '[' character
   113  	if length <= cursor {
   114  		return nil, 0, errors.Wrapf(ErrInvalidPathString, "unexpected end of YAML Path")
   115  	}
   116  	c := buf[cursor]
   117  	switch c {
   118  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*':
   119  		start := cursor
   120  		cursor++
   121  		for ; cursor < length; cursor++ {
   122  			c := buf[cursor]
   123  			switch c {
   124  			case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   125  				continue
   126  			}
   127  			break
   128  		}
   129  		if buf[cursor] != ']' {
   130  			return nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", string(buf[cursor]), cursor)
   131  		}
   132  		numOrAll := string(buf[start:cursor])
   133  		if numOrAll == "*" {
   134  			return b.IndexAll(), cursor + 1, nil
   135  		}
   136  		num, err := strconv.ParseInt(numOrAll, 10, 64)
   137  		if err != nil {
   138  			return nil, 0, errors.Wrapf(err, "failed to parse number")
   139  		}
   140  		return b.Index(uint(num)), cursor + 1, nil
   141  	}
   142  	return nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", c, cursor)
   143  }
   144  
   145  // Path represent YAMLPath ( like a JSONPath ).
   146  type Path struct {
   147  	node pathNode
   148  }
   149  
   150  // String path to text.
   151  func (p *Path) String() string {
   152  	return p.node.String()
   153  }
   154  
   155  // Read decode from r and set extracted value by YAMLPath to v.
   156  func (p *Path) Read(r io.Reader, v interface{}) error {
   157  	node, err := p.ReadNode(r)
   158  	if err != nil {
   159  		return errors.Wrapf(err, "failed to read node")
   160  	}
   161  	if err := Unmarshal([]byte(node.String()), v); err != nil {
   162  		return errors.Wrapf(err, "failed to unmarshal")
   163  	}
   164  	return nil
   165  }
   166  
   167  // ReadNode create AST from r and extract node by YAMLPath.
   168  func (p *Path) ReadNode(r io.Reader) (ast.Node, error) {
   169  	if p.node == nil {
   170  		return nil, ErrInvalidPath
   171  	}
   172  	var buf bytes.Buffer
   173  	if _, err := io.Copy(&buf, r); err != nil {
   174  		return nil, errors.Wrapf(err, "failed to copy from reader")
   175  	}
   176  	f, err := parser.ParseBytes(buf.Bytes(), 0)
   177  	if err != nil {
   178  		return nil, errors.Wrapf(err, "failed to parse yaml")
   179  	}
   180  	node, err := p.FilterFile(f)
   181  	if err != nil {
   182  		return nil, errors.Wrapf(err, "failed to filter from ast.File")
   183  	}
   184  	return node, nil
   185  }
   186  
   187  // Filter filter from target by YAMLPath and set it to v.
   188  func (p *Path) Filter(target, v interface{}) error {
   189  	b, err := Marshal(target)
   190  	if err != nil {
   191  		return errors.Wrapf(err, "failed to marshal target value")
   192  	}
   193  	if err := p.Read(bytes.NewBuffer(b), v); err != nil {
   194  		return errors.Wrapf(err, "failed to read")
   195  	}
   196  	return nil
   197  }
   198  
   199  // FilterFile filter from ast.File by YAMLPath.
   200  func (p *Path) FilterFile(f *ast.File) (ast.Node, error) {
   201  	for _, doc := range f.Docs {
   202  		node, err := p.FilterNode(doc.Body)
   203  		if err != nil {
   204  			return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node)
   205  		}
   206  		if node != nil {
   207  			return node, nil
   208  		}
   209  	}
   210  	return nil, errors.Wrapf(ErrNotFoundNode, "failed to find path ( %s )", p.node)
   211  }
   212  
   213  // FilterNode filter from node by YAMLPath.
   214  func (p *Path) FilterNode(node ast.Node) (ast.Node, error) {
   215  	n, err := p.node.filter(node)
   216  	if err != nil {
   217  		return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node)
   218  	}
   219  	return n, nil
   220  }
   221  
   222  // MergeFromReader merge YAML text into ast.File.
   223  func (p *Path) MergeFromReader(dst *ast.File, src io.Reader) error {
   224  	var buf bytes.Buffer
   225  	if _, err := io.Copy(&buf, src); err != nil {
   226  		return errors.Wrapf(err, "failed to copy from reader")
   227  	}
   228  	file, err := parser.ParseBytes(buf.Bytes(), 0)
   229  	if err != nil {
   230  		return errors.Wrapf(err, "failed to parse")
   231  	}
   232  	if err := p.MergeFromFile(dst, file); err != nil {
   233  		return errors.Wrapf(err, "failed to merge file")
   234  	}
   235  	return nil
   236  }
   237  
   238  // MergeFromFile merge ast.File into ast.File.
   239  func (p *Path) MergeFromFile(dst *ast.File, src *ast.File) error {
   240  	base, err := p.FilterFile(dst)
   241  	if err != nil {
   242  		return errors.Wrapf(err, "failed to filter file")
   243  	}
   244  	for _, doc := range src.Docs {
   245  		if err := ast.Merge(base, doc); err != nil {
   246  			return errors.Wrapf(err, "failed to merge")
   247  		}
   248  	}
   249  	return nil
   250  }
   251  
   252  // MergeFromNode merge ast.Node into ast.File.
   253  func (p *Path) MergeFromNode(dst *ast.File, src ast.Node) error {
   254  	base, err := p.FilterFile(dst)
   255  	if err != nil {
   256  		return errors.Wrapf(err, "failed to filter file")
   257  	}
   258  	if err := ast.Merge(base, src); err != nil {
   259  		return errors.Wrapf(err, "failed to merge")
   260  	}
   261  	return nil
   262  }
   263  
   264  // ReplaceWithReader replace ast.File with io.Reader.
   265  func (p *Path) ReplaceWithReader(dst *ast.File, src io.Reader) error {
   266  	var buf bytes.Buffer
   267  	if _, err := io.Copy(&buf, src); err != nil {
   268  		return errors.Wrapf(err, "failed to copy from reader")
   269  	}
   270  	file, err := parser.ParseBytes(buf.Bytes(), 0)
   271  	if err != nil {
   272  		return errors.Wrapf(err, "failed to parse")
   273  	}
   274  	if err := p.ReplaceWithFile(dst, file); err != nil {
   275  		return errors.Wrapf(err, "failed to replace file")
   276  	}
   277  	return nil
   278  }
   279  
   280  // ReplaceWithFile replace ast.File with ast.File.
   281  func (p *Path) ReplaceWithFile(dst *ast.File, src *ast.File) error {
   282  	for _, doc := range src.Docs {
   283  		if err := p.ReplaceWithNode(dst, doc); err != nil {
   284  			return errors.Wrapf(err, "failed to replace file by path ( %s )", p.node)
   285  		}
   286  	}
   287  	return nil
   288  }
   289  
   290  // ReplaceNode replace ast.File with ast.Node.
   291  func (p *Path) ReplaceWithNode(dst *ast.File, node ast.Node) error {
   292  	for _, doc := range dst.Docs {
   293  		if node.Type() == ast.DocumentType {
   294  			node = node.(*ast.DocumentNode).Body
   295  		}
   296  		if err := p.node.replace(doc.Body, node); err != nil {
   297  			return errors.Wrapf(err, "failed to replace node by path ( %s )", p.node)
   298  		}
   299  	}
   300  	return nil
   301  }
   302  
   303  // AnnotateSource add annotation to passed source ( see section 5.1 in README.md ).
   304  func (p *Path) AnnotateSource(source []byte, colored bool) ([]byte, error) {
   305  	file, err := parser.ParseBytes([]byte(source), 0)
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  	node, err := p.FilterFile(file)
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  	var pp printer.Printer
   314  	return []byte(pp.PrintErrorToken(node.GetToken(), colored)), nil
   315  }
   316  
   317  // PathBuilder represent builder for YAMLPath.
   318  type PathBuilder struct {
   319  	root *rootNode
   320  	node pathNode
   321  }
   322  
   323  // Root add '$' to current path.
   324  func (b *PathBuilder) Root() *PathBuilder {
   325  	root := newRootNode()
   326  	return &PathBuilder{root: root, node: root}
   327  }
   328  
   329  // IndexAll add '[*]' to current path.
   330  func (b *PathBuilder) IndexAll() *PathBuilder {
   331  	b.node = b.node.chain(newIndexAllNode())
   332  	return b
   333  }
   334  
   335  // Recursive add '..selector' to current path.
   336  func (b *PathBuilder) Recursive(selector string) *PathBuilder {
   337  	b.node = b.node.chain(newRecursiveNode(selector))
   338  	return b
   339  }
   340  
   341  // Child add '.name' to current path.
   342  func (b *PathBuilder) Child(name string) *PathBuilder {
   343  	b.node = b.node.chain(newSelectorNode(name))
   344  	return b
   345  }
   346  
   347  // Index add '[idx]' to current path.
   348  func (b *PathBuilder) Index(idx uint) *PathBuilder {
   349  	b.node = b.node.chain(newIndexNode(idx))
   350  	return b
   351  }
   352  
   353  // Build build YAMLPath.
   354  func (b *PathBuilder) Build() *Path {
   355  	return &Path{node: b.root}
   356  }
   357  
   358  type pathNode interface {
   359  	fmt.Stringer
   360  	chain(pathNode) pathNode
   361  	filter(ast.Node) (ast.Node, error)
   362  	replace(ast.Node, ast.Node) error
   363  }
   364  
   365  type basePathNode struct {
   366  	child pathNode
   367  }
   368  
   369  func (n *basePathNode) chain(node pathNode) pathNode {
   370  	n.child = node
   371  	return node
   372  }
   373  
   374  type rootNode struct {
   375  	*basePathNode
   376  }
   377  
   378  func newRootNode() *rootNode {
   379  	return &rootNode{basePathNode: &basePathNode{}}
   380  }
   381  
   382  func (n *rootNode) String() string {
   383  	s := "$"
   384  	if n.child != nil {
   385  		s += n.child.String()
   386  	}
   387  	return s
   388  }
   389  
   390  func (n *rootNode) filter(node ast.Node) (ast.Node, error) {
   391  	if n.child == nil {
   392  		return nil, nil
   393  	}
   394  	filtered, err := n.child.filter(node)
   395  	if err != nil {
   396  		return nil, errors.Wrapf(err, "failed to filter")
   397  	}
   398  	return filtered, nil
   399  }
   400  
   401  func (n *rootNode) replace(node ast.Node, target ast.Node) error {
   402  	if n.child == nil {
   403  		return nil
   404  	}
   405  	if err := n.child.replace(node, target); err != nil {
   406  		return errors.Wrapf(err, "failed to replace")
   407  	}
   408  	return nil
   409  }
   410  
   411  type selectorNode struct {
   412  	*basePathNode
   413  	selector string
   414  }
   415  
   416  func newSelectorNode(selector string) *selectorNode {
   417  	return &selectorNode{
   418  		basePathNode: &basePathNode{},
   419  		selector:     selector,
   420  	}
   421  }
   422  
   423  func (n *selectorNode) filter(node ast.Node) (ast.Node, error) {
   424  	switch node.Type() {
   425  	case ast.MappingType:
   426  		for _, value := range node.(*ast.MappingNode).Values {
   427  			key := value.Key.GetToken().Value
   428  			if key == n.selector {
   429  				if n.child == nil {
   430  					return value.Value, nil
   431  				}
   432  				filtered, err := n.child.filter(value.Value)
   433  				if err != nil {
   434  					return nil, errors.Wrapf(err, "failed to filter")
   435  				}
   436  				return filtered, nil
   437  			}
   438  		}
   439  	case ast.MappingValueType:
   440  		value := node.(*ast.MappingValueNode)
   441  		key := value.Key.GetToken().Value
   442  		if key == n.selector {
   443  			if n.child == nil {
   444  				return value.Value, nil
   445  			}
   446  			filtered, err := n.child.filter(value.Value)
   447  			if err != nil {
   448  				return nil, errors.Wrapf(err, "failed to filter")
   449  			}
   450  			return filtered, nil
   451  		}
   452  	default:
   453  		return nil, errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type())
   454  	}
   455  	return nil, nil
   456  }
   457  
   458  func (n *selectorNode) replaceMapValue(value *ast.MappingValueNode, target ast.Node) error {
   459  	key := value.Key.GetToken().Value
   460  	if key != n.selector {
   461  		return nil
   462  	}
   463  	if n.child == nil {
   464  		if err := value.Replace(target); err != nil {
   465  			return errors.Wrapf(err, "failed to replace")
   466  		}
   467  	} else {
   468  		if err := n.child.replace(value.Value, target); err != nil {
   469  			return errors.Wrapf(err, "failed to replace")
   470  		}
   471  	}
   472  	return nil
   473  }
   474  
   475  func (n *selectorNode) replace(node ast.Node, target ast.Node) error {
   476  	switch node.Type() {
   477  	case ast.MappingType:
   478  		for _, value := range node.(*ast.MappingNode).Values {
   479  			if err := n.replaceMapValue(value, target); err != nil {
   480  				return errors.Wrapf(err, "failed to replace map value")
   481  			}
   482  		}
   483  	case ast.MappingValueType:
   484  		value := node.(*ast.MappingValueNode)
   485  		if err := n.replaceMapValue(value, target); err != nil {
   486  			return errors.Wrapf(err, "failed to replace map value")
   487  		}
   488  	default:
   489  		return errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type())
   490  	}
   491  	return nil
   492  }
   493  
   494  func (n *selectorNode) String() string {
   495  	s := fmt.Sprintf(".%s", n.selector)
   496  	if n.child != nil {
   497  		s += n.child.String()
   498  	}
   499  	return s
   500  }
   501  
   502  type indexNode struct {
   503  	*basePathNode
   504  	selector uint
   505  }
   506  
   507  func newIndexNode(selector uint) *indexNode {
   508  	return &indexNode{
   509  		basePathNode: &basePathNode{},
   510  		selector:     selector,
   511  	}
   512  }
   513  
   514  func (n *indexNode) filter(node ast.Node) (ast.Node, error) {
   515  	if node.Type() != ast.SequenceType {
   516  		return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
   517  	}
   518  	sequence := node.(*ast.SequenceNode)
   519  	if n.selector >= uint(len(sequence.Values)) {
   520  		return nil, errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values)
   521  	}
   522  	value := sequence.Values[n.selector]
   523  	if n.child == nil {
   524  		return value, nil
   525  	}
   526  	filtered, err := n.child.filter(value)
   527  	if err != nil {
   528  		return nil, errors.Wrapf(err, "failed to filter")
   529  	}
   530  	return filtered, nil
   531  }
   532  
   533  func (n *indexNode) replace(node ast.Node, target ast.Node) error {
   534  	if node.Type() != ast.SequenceType {
   535  		return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
   536  	}
   537  	sequence := node.(*ast.SequenceNode)
   538  	if n.selector >= uint(len(sequence.Values)) {
   539  		return errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values)
   540  	}
   541  	if n.child == nil {
   542  		if err := sequence.Replace(int(n.selector), target); err != nil {
   543  			return errors.Wrapf(err, "failed to replace")
   544  		}
   545  		return nil
   546  	}
   547  	if err := n.child.replace(sequence.Values[n.selector], target); err != nil {
   548  		return errors.Wrapf(err, "failed to replace")
   549  	}
   550  	return nil
   551  }
   552  
   553  func (n *indexNode) String() string {
   554  	s := fmt.Sprintf("[%d]", n.selector)
   555  	if n.child != nil {
   556  		s += n.child.String()
   557  	}
   558  	return s
   559  }
   560  
   561  type indexAllNode struct {
   562  	*basePathNode
   563  }
   564  
   565  func newIndexAllNode() *indexAllNode {
   566  	return &indexAllNode{
   567  		basePathNode: &basePathNode{},
   568  	}
   569  }
   570  
   571  func (n *indexAllNode) String() string {
   572  	s := "[*]"
   573  	if n.child != nil {
   574  		s += n.child.String()
   575  	}
   576  	return s
   577  }
   578  
   579  func (n *indexAllNode) filter(node ast.Node) (ast.Node, error) {
   580  	if node.Type() != ast.SequenceType {
   581  		return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
   582  	}
   583  	sequence := node.(*ast.SequenceNode)
   584  	if n.child == nil {
   585  		return sequence, nil
   586  	}
   587  	out := *sequence
   588  	out.Values = []ast.Node{}
   589  	for _, value := range sequence.Values {
   590  		filtered, err := n.child.filter(value)
   591  		if err != nil {
   592  			return nil, errors.Wrapf(err, "failed to filter")
   593  		}
   594  		out.Values = append(out.Values, filtered)
   595  	}
   596  	return &out, nil
   597  }
   598  
   599  func (n *indexAllNode) replace(node ast.Node, target ast.Node) error {
   600  	if node.Type() != ast.SequenceType {
   601  		return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type())
   602  	}
   603  	sequence := node.(*ast.SequenceNode)
   604  	if n.child == nil {
   605  		for idx := range sequence.Values {
   606  			if err := sequence.Replace(idx, target); err != nil {
   607  				return errors.Wrapf(err, "failed to replace")
   608  			}
   609  		}
   610  		return nil
   611  	}
   612  	for _, value := range sequence.Values {
   613  		if err := n.child.replace(value, target); err != nil {
   614  			return errors.Wrapf(err, "failed to replace")
   615  		}
   616  	}
   617  	return nil
   618  }
   619  
   620  type recursiveNode struct {
   621  	*basePathNode
   622  	selector string
   623  }
   624  
   625  func newRecursiveNode(selector string) *recursiveNode {
   626  	return &recursiveNode{
   627  		basePathNode: &basePathNode{},
   628  		selector:     selector,
   629  	}
   630  }
   631  
   632  func (n *recursiveNode) String() string {
   633  	s := fmt.Sprintf("..%s", n.selector)
   634  	if n.child != nil {
   635  		s += n.child.String()
   636  	}
   637  	return s
   638  }
   639  
   640  func (n *recursiveNode) filterNode(node ast.Node) (*ast.SequenceNode, error) {
   641  	sequence := &ast.SequenceNode{BaseNode: &ast.BaseNode{}}
   642  	switch typedNode := node.(type) {
   643  	case *ast.MappingNode:
   644  		for _, value := range typedNode.Values {
   645  			seq, err := n.filterNode(value)
   646  			if err != nil {
   647  				return nil, errors.Wrapf(err, "failed to filter")
   648  			}
   649  			sequence.Values = append(sequence.Values, seq.Values...)
   650  		}
   651  	case *ast.MappingValueNode:
   652  		key := typedNode.Key.GetToken().Value
   653  		if n.selector == key {
   654  			sequence.Values = append(sequence.Values, typedNode.Value)
   655  		}
   656  		seq, err := n.filterNode(typedNode.Value)
   657  		if err != nil {
   658  			return nil, errors.Wrapf(err, "failed to filter")
   659  		}
   660  		sequence.Values = append(sequence.Values, seq.Values...)
   661  	case *ast.SequenceNode:
   662  		for _, value := range typedNode.Values {
   663  			seq, err := n.filterNode(value)
   664  			if err != nil {
   665  				return nil, errors.Wrapf(err, "failed to filter")
   666  			}
   667  			sequence.Values = append(sequence.Values, seq.Values...)
   668  		}
   669  	}
   670  	return sequence, nil
   671  }
   672  
   673  func (n *recursiveNode) filter(node ast.Node) (ast.Node, error) {
   674  	sequence, err := n.filterNode(node)
   675  	if err != nil {
   676  		return nil, errors.Wrapf(err, "failed to filter")
   677  	}
   678  	sequence.Start = node.GetToken()
   679  	return sequence, nil
   680  }
   681  
   682  func (n *recursiveNode) replaceNode(node ast.Node, target ast.Node) error {
   683  	switch typedNode := node.(type) {
   684  	case *ast.MappingNode:
   685  		for _, value := range typedNode.Values {
   686  			if err := n.replaceNode(value, target); err != nil {
   687  				return errors.Wrapf(err, "failed to replace")
   688  			}
   689  		}
   690  	case *ast.MappingValueNode:
   691  		key := typedNode.Key.GetToken().Value
   692  		if n.selector == key {
   693  			if err := typedNode.Replace(target); err != nil {
   694  				return errors.Wrapf(err, "failed to replace")
   695  			}
   696  		}
   697  		if err := n.replaceNode(typedNode.Value, target); err != nil {
   698  			return errors.Wrapf(err, "failed to replace")
   699  		}
   700  	case *ast.SequenceNode:
   701  		for _, value := range typedNode.Values {
   702  			if err := n.replaceNode(value, target); err != nil {
   703  				return errors.Wrapf(err, "failed to replace")
   704  			}
   705  		}
   706  	}
   707  	return nil
   708  }
   709  
   710  func (n *recursiveNode) replace(node ast.Node, target ast.Node) error {
   711  	if err := n.replaceNode(node, target); err != nil {
   712  		return errors.Wrapf(err, "failed to replace")
   713  	}
   714  	return nil
   715  }