git.gammaspectra.live/P2Pool/go-json@v0.99.0/internal/decoder/path.go (about)

     1  package decoder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strconv"
     7  
     8  	"git.gammaspectra.live/P2Pool/go-json/internal/errors"
     9  	"git.gammaspectra.live/P2Pool/go-json/internal/runtime"
    10  )
    11  
    12  type PathString string
    13  
    14  func (s PathString) Build() (*Path, error) {
    15  	builder := new(PathBuilder)
    16  	return builder.Build([]rune(s))
    17  }
    18  
    19  type PathBuilder struct {
    20  	root                    PathNode
    21  	node                    PathNode
    22  	singleQuotePathSelector bool
    23  	doubleQuotePathSelector bool
    24  }
    25  
    26  func (b *PathBuilder) Build(buf []rune) (*Path, error) {
    27  	node, err := b.build(buf)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	return &Path{
    32  		node:                    node,
    33  		RootSelectorOnly:        node == nil,
    34  		SingleQuotePathSelector: b.singleQuotePathSelector,
    35  		DoubleQuotePathSelector: b.doubleQuotePathSelector,
    36  	}, nil
    37  }
    38  
    39  func (b *PathBuilder) build(buf []rune) (PathNode, error) {
    40  	if len(buf) == 0 {
    41  		return nil, errors.ErrEmptyPath()
    42  	}
    43  	if buf[0] != '$' {
    44  		return nil, errors.ErrInvalidPath("JSON Path must start with a $ character")
    45  	}
    46  	if len(buf) == 1 {
    47  		return nil, nil
    48  	}
    49  	buf = buf[1:]
    50  	offset, err := b.buildNext(buf)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	if len(buf) > offset {
    55  		return nil, errors.ErrInvalidPath("remain invalid path %q", buf[offset:])
    56  	}
    57  	return b.root, nil
    58  }
    59  
    60  func (b *PathBuilder) buildNextCharIfExists(buf []rune, cursor int) (int, error) {
    61  	if len(buf) > cursor {
    62  		offset, err := b.buildNext(buf[cursor:])
    63  		if err != nil {
    64  			return 0, err
    65  		}
    66  		return cursor + 1 + offset, nil
    67  	}
    68  	return cursor, nil
    69  }
    70  
    71  func (b *PathBuilder) buildNext(buf []rune) (int, error) {
    72  	switch buf[0] {
    73  	case '.':
    74  		if len(buf) == 1 {
    75  			return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
    76  		}
    77  		offset, err := b.buildSelector(buf[1:])
    78  		if err != nil {
    79  			return 0, err
    80  		}
    81  		return offset + 1, nil
    82  	case '[':
    83  		if len(buf) == 1 {
    84  			return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
    85  		}
    86  		offset, err := b.buildIndex(buf[1:])
    87  		if err != nil {
    88  			return 0, err
    89  		}
    90  		return offset + 1, nil
    91  	default:
    92  		return 0, errors.ErrInvalidPath("expect dot or left bracket character. but found %c character", buf[0])
    93  	}
    94  }
    95  
    96  func (b *PathBuilder) buildSelector(buf []rune) (int, error) {
    97  	switch buf[0] {
    98  	case '.':
    99  		if len(buf) == 1 {
   100  			return 0, errors.ErrInvalidPath("JSON Path ends with double dot character")
   101  		}
   102  		offset, err := b.buildPathRecursive(buf[1:])
   103  		if err != nil {
   104  			return 0, err
   105  		}
   106  		return 1 + offset, nil
   107  	case '[', ']', '$', '*':
   108  		return 0, errors.ErrInvalidPath("found invalid path character %c after dot", buf[0])
   109  	}
   110  	for cursor := 0; cursor < len(buf); cursor++ {
   111  		switch buf[cursor] {
   112  		case '$', '*', ']':
   113  			return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
   114  		case '.':
   115  			if cursor+1 >= len(buf) {
   116  				return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
   117  			}
   118  			selector := buf[:cursor]
   119  			b.addSelectorNode(string(selector))
   120  			offset, err := b.buildSelector(buf[cursor+1:])
   121  			if err != nil {
   122  				return 0, err
   123  			}
   124  			return cursor + 1 + offset, nil
   125  		case '[':
   126  			if cursor+1 >= len(buf) {
   127  				return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
   128  			}
   129  			selector := buf[:cursor]
   130  			b.addSelectorNode(string(selector))
   131  			offset, err := b.buildIndex(buf[cursor+1:])
   132  			if err != nil {
   133  				return 0, err
   134  			}
   135  			return cursor + 1 + offset, nil
   136  		case '"':
   137  			if cursor+1 >= len(buf) {
   138  				return 0, errors.ErrInvalidPath("JSON Path ends with double quote character")
   139  			}
   140  			offset, err := b.buildQuoteSelector(buf[cursor+1:], DoubleQuotePathSelector)
   141  			if err != nil {
   142  				return 0, err
   143  			}
   144  			return cursor + 1 + offset, nil
   145  		}
   146  	}
   147  	b.addSelectorNode(string(buf))
   148  	return len(buf), nil
   149  }
   150  
   151  func (b *PathBuilder) buildQuoteSelector(buf []rune, sel QuotePathSelector) (int, error) {
   152  	switch buf[0] {
   153  	case '[', ']', '$', '.', '*', '\'', '"':
   154  		return 0, errors.ErrInvalidPath("found invalid path character %c after quote", buf[0])
   155  	}
   156  	for cursor := 0; cursor < len(buf); cursor++ {
   157  		switch buf[cursor] {
   158  		case '\'':
   159  			if sel != SingleQuotePathSelector {
   160  				return 0, errors.ErrInvalidPath("found double quote character in field selector with single quote context")
   161  			}
   162  			if len(buf) <= cursor+1 {
   163  				return 0, errors.ErrInvalidPath("JSON Path ends with single quote character in field selector context")
   164  			}
   165  			if buf[cursor+1] != ']' {
   166  				return 0, errors.ErrInvalidPath("expect right bracket for field selector with single quote but found %c", buf[cursor+1])
   167  			}
   168  			selector := buf[:cursor]
   169  			b.addSelectorNode(string(selector))
   170  			b.singleQuotePathSelector = true
   171  			return b.buildNextCharIfExists(buf, cursor+2)
   172  		case '"':
   173  			if sel != DoubleQuotePathSelector {
   174  				return 0, errors.ErrInvalidPath("found single quote character in field selector with double quote context")
   175  			}
   176  			selector := buf[:cursor]
   177  			b.addSelectorNode(string(selector))
   178  			b.doubleQuotePathSelector = true
   179  			return b.buildNextCharIfExists(buf, cursor+1)
   180  		}
   181  	}
   182  	return 0, errors.ErrInvalidPath("couldn't find quote character in selector quote path context")
   183  }
   184  
   185  func (b *PathBuilder) buildPathRecursive(buf []rune) (int, error) {
   186  	switch buf[0] {
   187  	case '.', '[', ']', '$', '*':
   188  		return 0, errors.ErrInvalidPath("found invalid path character %c after double dot", buf[0])
   189  	}
   190  	for cursor := 0; cursor < len(buf); cursor++ {
   191  		switch buf[cursor] {
   192  		case '$', '*', ']':
   193  			return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
   194  		case '.':
   195  			if cursor+1 >= len(buf) {
   196  				return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
   197  			}
   198  			selector := buf[:cursor]
   199  			b.addRecursiveNode(string(selector))
   200  			offset, err := b.buildSelector(buf[cursor+1:])
   201  			if err != nil {
   202  				return 0, err
   203  			}
   204  			return cursor + 1 + offset, nil
   205  		case '[':
   206  			if cursor+1 >= len(buf) {
   207  				return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
   208  			}
   209  			selector := buf[:cursor]
   210  			b.addRecursiveNode(string(selector))
   211  			offset, err := b.buildIndex(buf[cursor+1:])
   212  			if err != nil {
   213  				return 0, err
   214  			}
   215  			return cursor + 1 + offset, nil
   216  		}
   217  	}
   218  	b.addRecursiveNode(string(buf))
   219  	return len(buf), nil
   220  }
   221  
   222  func (b *PathBuilder) buildIndex(buf []rune) (int, error) {
   223  	switch buf[0] {
   224  	case '.', '[', ']', '$':
   225  		return 0, errors.ErrInvalidPath("found invalid path character %c after left bracket", buf[0])
   226  	case '\'':
   227  		if len(buf) == 1 {
   228  			return 0, errors.ErrInvalidPath("JSON Path ends with single quote character")
   229  		}
   230  		offset, err := b.buildQuoteSelector(buf[1:], SingleQuotePathSelector)
   231  		if err != nil {
   232  			return 0, err
   233  		}
   234  		return 1 + offset, nil
   235  	case '*':
   236  		if len(buf) == 1 {
   237  			return 0, errors.ErrInvalidPath("JSON Path ends with star character")
   238  		}
   239  		if buf[1] != ']' {
   240  			return 0, errors.ErrInvalidPath("expect right bracket character for index all path but found %c character", buf[1])
   241  		}
   242  		b.addIndexAllNode()
   243  		offset := len("*]")
   244  		if len(buf) > 2 {
   245  			buildOffset, err := b.buildNext(buf[2:])
   246  			if err != nil {
   247  				return 0, err
   248  			}
   249  			return offset + buildOffset, nil
   250  		}
   251  		return offset, nil
   252  	}
   253  
   254  	for cursor := 0; cursor < len(buf); cursor++ {
   255  		switch buf[cursor] {
   256  		case ']':
   257  			index, err := strconv.ParseInt(string(buf[:cursor]), 10, 64)
   258  			if err != nil {
   259  				return 0, errors.ErrInvalidPath("%q is unexpected index path", buf[:cursor])
   260  			}
   261  			b.addIndexNode(int(index))
   262  			return b.buildNextCharIfExists(buf, cursor+1)
   263  		}
   264  	}
   265  	return 0, errors.ErrInvalidPath("couldn't find right bracket character in index path context")
   266  }
   267  
   268  func (b *PathBuilder) addIndexAllNode() {
   269  	node := newPathIndexAllNode()
   270  	if b.root == nil {
   271  		b.root = node
   272  		b.node = node
   273  	} else {
   274  		b.node = b.node.chain(node)
   275  	}
   276  }
   277  
   278  func (b *PathBuilder) addRecursiveNode(selector string) {
   279  	node := newPathRecursiveNode(selector)
   280  	if b.root == nil {
   281  		b.root = node
   282  		b.node = node
   283  	} else {
   284  		b.node = b.node.chain(node)
   285  	}
   286  }
   287  
   288  func (b *PathBuilder) addSelectorNode(name string) {
   289  	node := newPathSelectorNode(name)
   290  	if b.root == nil {
   291  		b.root = node
   292  		b.node = node
   293  	} else {
   294  		b.node = b.node.chain(node)
   295  	}
   296  }
   297  
   298  func (b *PathBuilder) addIndexNode(idx int) {
   299  	node := newPathIndexNode(idx)
   300  	if b.root == nil {
   301  		b.root = node
   302  		b.node = node
   303  	} else {
   304  		b.node = b.node.chain(node)
   305  	}
   306  }
   307  
   308  type QuotePathSelector int
   309  
   310  const (
   311  	SingleQuotePathSelector QuotePathSelector = 1
   312  	DoubleQuotePathSelector QuotePathSelector = 2
   313  )
   314  
   315  type Path struct {
   316  	node                    PathNode
   317  	RootSelectorOnly        bool
   318  	SingleQuotePathSelector bool
   319  	DoubleQuotePathSelector bool
   320  }
   321  
   322  func (p *Path) Field(sel string) (PathNode, bool, error) {
   323  	if p.node == nil {
   324  		return nil, false, nil
   325  	}
   326  	return p.node.Field(sel)
   327  }
   328  
   329  func (p *Path) Get(src, dst reflect.Value) error {
   330  	if p.node == nil {
   331  		return nil
   332  	}
   333  	return p.node.Get(src, dst)
   334  }
   335  
   336  func (p *Path) String() string {
   337  	if p.node == nil {
   338  		return "$"
   339  	}
   340  	return p.node.String()
   341  }
   342  
   343  type PathNode interface {
   344  	fmt.Stringer
   345  	Index(idx int) (PathNode, bool, error)
   346  	Field(fieldName string) (PathNode, bool, error)
   347  	Get(src, dst reflect.Value) error
   348  	chain(PathNode) PathNode
   349  	target() bool
   350  	single() bool
   351  }
   352  
   353  type BasePathNode struct {
   354  	child PathNode
   355  }
   356  
   357  func (n *BasePathNode) chain(node PathNode) PathNode {
   358  	n.child = node
   359  	return node
   360  }
   361  
   362  func (n *BasePathNode) target() bool {
   363  	return n.child == nil
   364  }
   365  
   366  func (n *BasePathNode) single() bool {
   367  	return true
   368  }
   369  
   370  type PathSelectorNode struct {
   371  	*BasePathNode
   372  	selector string
   373  }
   374  
   375  func newPathSelectorNode(selector string) *PathSelectorNode {
   376  	return &PathSelectorNode{
   377  		BasePathNode: &BasePathNode{},
   378  		selector:     selector,
   379  	}
   380  }
   381  
   382  func (n *PathSelectorNode) Index(idx int) (PathNode, bool, error) {
   383  	return nil, false, &errors.PathError{}
   384  }
   385  
   386  func (n *PathSelectorNode) Field(fieldName string) (PathNode, bool, error) {
   387  	if n.selector == fieldName {
   388  		return n.child, true, nil
   389  	}
   390  	return nil, false, nil
   391  }
   392  
   393  func (n *PathSelectorNode) Get(src, dst reflect.Value) error {
   394  	switch src.Type().Kind() {
   395  	case reflect.Map:
   396  		iter := src.MapRange()
   397  		for iter.Next() {
   398  			key, ok := iter.Key().Interface().(string)
   399  			if !ok {
   400  				return fmt.Errorf("invalid map key type %T", src.Type().Key())
   401  			}
   402  			child, found, err := n.Field(key)
   403  			if err != nil {
   404  				return err
   405  			}
   406  			if found {
   407  				if child != nil {
   408  					return child.Get(iter.Value(), dst)
   409  				}
   410  				return AssignValue(iter.Value(), dst)
   411  			}
   412  		}
   413  	case reflect.Struct:
   414  		typ := src.Type()
   415  		for i := 0; i < typ.Len(); i++ {
   416  			tag := runtime.StructTagFromField(typ.Field(i))
   417  			child, found, err := n.Field(tag.Key)
   418  			if err != nil {
   419  				return err
   420  			}
   421  			if found {
   422  				if child != nil {
   423  					return child.Get(src.Field(i), dst)
   424  				}
   425  				return AssignValue(src.Field(i), dst)
   426  			}
   427  		}
   428  	case reflect.Ptr:
   429  		return n.Get(src.Elem(), dst)
   430  	case reflect.Interface:
   431  		return n.Get(reflect.ValueOf(src.Interface()), dst)
   432  	case reflect.Float64, reflect.String, reflect.Bool:
   433  		return AssignValue(src, dst)
   434  	}
   435  	return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
   436  }
   437  
   438  func (n *PathSelectorNode) String() string {
   439  	s := fmt.Sprintf(".%s", n.selector)
   440  	if n.child != nil {
   441  		s += n.child.String()
   442  	}
   443  	return s
   444  }
   445  
   446  type PathIndexNode struct {
   447  	*BasePathNode
   448  	selector int
   449  }
   450  
   451  func newPathIndexNode(selector int) *PathIndexNode {
   452  	return &PathIndexNode{
   453  		BasePathNode: &BasePathNode{},
   454  		selector:     selector,
   455  	}
   456  }
   457  
   458  func (n *PathIndexNode) Index(idx int) (PathNode, bool, error) {
   459  	if n.selector == idx {
   460  		return n.child, true, nil
   461  	}
   462  	return nil, false, nil
   463  }
   464  
   465  func (n *PathIndexNode) Field(fieldName string) (PathNode, bool, error) {
   466  	return nil, false, &errors.PathError{}
   467  }
   468  
   469  func (n *PathIndexNode) Get(src, dst reflect.Value) error {
   470  	switch src.Type().Kind() {
   471  	case reflect.Array, reflect.Slice:
   472  		if src.Len() > n.selector {
   473  			if n.child != nil {
   474  				return n.child.Get(src.Index(n.selector), dst)
   475  			}
   476  			return AssignValue(src.Index(n.selector), dst)
   477  		}
   478  	case reflect.Ptr:
   479  		return n.Get(src.Elem(), dst)
   480  	case reflect.Interface:
   481  		return n.Get(reflect.ValueOf(src.Interface()), dst)
   482  	}
   483  	return fmt.Errorf("failed to get [%d] value from %s", n.selector, src.Type())
   484  }
   485  
   486  func (n *PathIndexNode) String() string {
   487  	s := fmt.Sprintf("[%d]", n.selector)
   488  	if n.child != nil {
   489  		s += n.child.String()
   490  	}
   491  	return s
   492  }
   493  
   494  type PathIndexAllNode struct {
   495  	*BasePathNode
   496  }
   497  
   498  func newPathIndexAllNode() *PathIndexAllNode {
   499  	return &PathIndexAllNode{
   500  		BasePathNode: &BasePathNode{},
   501  	}
   502  }
   503  
   504  func (n *PathIndexAllNode) Index(idx int) (PathNode, bool, error) {
   505  	return n.child, true, nil
   506  }
   507  
   508  func (n *PathIndexAllNode) Field(fieldName string) (PathNode, bool, error) {
   509  	return nil, false, &errors.PathError{}
   510  }
   511  
   512  func (n *PathIndexAllNode) Get(src, dst reflect.Value) error {
   513  	switch src.Type().Kind() {
   514  	case reflect.Array, reflect.Slice:
   515  		var arr []interface{}
   516  		for i := 0; i < src.Len(); i++ {
   517  			var v interface{}
   518  			rv := reflect.ValueOf(&v)
   519  			if n.child != nil {
   520  				if err := n.child.Get(src.Index(i), rv); err != nil {
   521  					return err
   522  				}
   523  			} else {
   524  				if err := AssignValue(src.Index(i), rv); err != nil {
   525  					return err
   526  				}
   527  			}
   528  			arr = append(arr, v)
   529  		}
   530  		if err := AssignValue(reflect.ValueOf(arr), dst); err != nil {
   531  			return err
   532  		}
   533  		return nil
   534  	case reflect.Ptr:
   535  		return n.Get(src.Elem(), dst)
   536  	case reflect.Interface:
   537  		return n.Get(reflect.ValueOf(src.Interface()), dst)
   538  	}
   539  	return fmt.Errorf("failed to get all value from %s", src.Type())
   540  }
   541  
   542  func (n *PathIndexAllNode) String() string {
   543  	s := "[*]"
   544  	if n.child != nil {
   545  		s += n.child.String()
   546  	}
   547  	return s
   548  }
   549  
   550  type PathRecursiveNode struct {
   551  	*BasePathNode
   552  	selector string
   553  }
   554  
   555  func newPathRecursiveNode(selector string) *PathRecursiveNode {
   556  	node := newPathSelectorNode(selector)
   557  	return &PathRecursiveNode{
   558  		BasePathNode: &BasePathNode{
   559  			child: node,
   560  		},
   561  		selector: selector,
   562  	}
   563  }
   564  
   565  func (n *PathRecursiveNode) Field(fieldName string) (PathNode, bool, error) {
   566  	if n.selector == fieldName {
   567  		return n.child, true, nil
   568  	}
   569  	return nil, false, nil
   570  }
   571  
   572  func (n *PathRecursiveNode) Index(_ int) (PathNode, bool, error) {
   573  	return n, true, nil
   574  }
   575  
   576  func valueToSliceValue(v interface{}) []interface{} {
   577  	rv := reflect.ValueOf(v)
   578  	ret := []interface{}{}
   579  	if rv.Type().Kind() == reflect.Slice || rv.Type().Kind() == reflect.Array {
   580  		for i := 0; i < rv.Len(); i++ {
   581  			ret = append(ret, rv.Index(i).Interface())
   582  		}
   583  		return ret
   584  	}
   585  	return []interface{}{v}
   586  }
   587  
   588  func (n *PathRecursiveNode) Get(src, dst reflect.Value) error {
   589  	if n.child == nil {
   590  		return fmt.Errorf("failed to get by recursive path ..%s", n.selector)
   591  	}
   592  	var arr []interface{}
   593  	switch src.Type().Kind() {
   594  	case reflect.Map:
   595  		iter := src.MapRange()
   596  		for iter.Next() {
   597  			key, ok := iter.Key().Interface().(string)
   598  			if !ok {
   599  				return fmt.Errorf("invalid map key type %T", src.Type().Key())
   600  			}
   601  			child, found, err := n.Field(key)
   602  			if err != nil {
   603  				return err
   604  			}
   605  			if found {
   606  				var v interface{}
   607  				rv := reflect.ValueOf(&v)
   608  				_ = child.Get(iter.Value(), rv)
   609  				arr = append(arr, valueToSliceValue(v)...)
   610  			} else {
   611  				var v interface{}
   612  				rv := reflect.ValueOf(&v)
   613  				_ = n.Get(iter.Value(), rv)
   614  				if v != nil {
   615  					arr = append(arr, valueToSliceValue(v)...)
   616  				}
   617  			}
   618  		}
   619  		_ = AssignValue(reflect.ValueOf(arr), dst)
   620  		return nil
   621  	case reflect.Struct:
   622  		typ := src.Type()
   623  		for i := 0; i < typ.Len(); i++ {
   624  			tag := runtime.StructTagFromField(typ.Field(i))
   625  			child, found, err := n.Field(tag.Key)
   626  			if err != nil {
   627  				return err
   628  			}
   629  			if found {
   630  				var v interface{}
   631  				rv := reflect.ValueOf(&v)
   632  				_ = child.Get(src.Field(i), rv)
   633  				arr = append(arr, valueToSliceValue(v)...)
   634  			} else {
   635  				var v interface{}
   636  				rv := reflect.ValueOf(&v)
   637  				_ = n.Get(src.Field(i), rv)
   638  				if v != nil {
   639  					arr = append(arr, valueToSliceValue(v)...)
   640  				}
   641  			}
   642  		}
   643  		_ = AssignValue(reflect.ValueOf(arr), dst)
   644  		return nil
   645  	case reflect.Array, reflect.Slice:
   646  		for i := 0; i < src.Len(); i++ {
   647  			var v interface{}
   648  			rv := reflect.ValueOf(&v)
   649  			_ = n.Get(src.Index(i), rv)
   650  			if v != nil {
   651  				arr = append(arr, valueToSliceValue(v)...)
   652  			}
   653  		}
   654  		_ = AssignValue(reflect.ValueOf(arr), dst)
   655  		return nil
   656  	case reflect.Ptr:
   657  		return n.Get(src.Elem(), dst)
   658  	case reflect.Interface:
   659  		return n.Get(reflect.ValueOf(src.Interface()), dst)
   660  	}
   661  	return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
   662  }
   663  
   664  func (n *PathRecursiveNode) String() string {
   665  	s := fmt.Sprintf("..%s", n.selector)
   666  	if n.child != nil {
   667  		s += n.child.String()
   668  	}
   669  	return s
   670  }