gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

path.go (16453B)


      1 package decoder
      2 
      3 import (
      4 	"fmt"
      5 	"reflect"
      6 	"strconv"
      7 
      8 	"github.com/goccy/go-json/internal/errors"
      9 	"github.com/goccy/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 }