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 }