(node, data any, decodedToken string, nameProvider NameProvider)
| 542 | } |
| 543 | |
| 544 | func setSingleImpl(node, data any, decodedToken string, nameProvider NameProvider) (any, error) { |
| 545 | // check for nil to prevent panic when calling rValue.Type() |
| 546 | if isNil(node) { |
| 547 | return node, fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) |
| 548 | } |
| 549 | |
| 550 | if ns, ok := node.(JSONSetable); ok { |
| 551 | return node, ns.JSONSet(decodedToken, data) |
| 552 | } |
| 553 | |
| 554 | rValue := reflect.Indirect(reflect.ValueOf(node)) |
| 555 | |
| 556 | switch rValue.Kind() { |
| 557 | case reflect.Struct: |
| 558 | nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) |
| 559 | if !ok { |
| 560 | return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) |
| 561 | } |
| 562 | |
| 563 | fld := rValue.FieldByName(nm) |
| 564 | if !fld.CanSet() { |
| 565 | return node, fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer) |
| 566 | } |
| 567 | |
| 568 | value := reflect.ValueOf(data) |
| 569 | valueType := value.Type() |
| 570 | assignedType := fld.Type() |
| 571 | |
| 572 | if !valueType.AssignableTo(assignedType) { |
| 573 | return node, fmt.Errorf("can't set value with type %T to field %s with type %v: %w", data, nm, assignedType, ErrPointer) |
| 574 | } |
| 575 | |
| 576 | fld.Set(value) |
| 577 | |
| 578 | return node, nil |
| 579 | |
| 580 | case reflect.Map: |
| 581 | kv := reflect.ValueOf(decodedToken) |
| 582 | rValue.SetMapIndex(kv, reflect.ValueOf(data)) |
| 583 | |
| 584 | return node, nil |
| 585 | |
| 586 | case reflect.Slice: |
| 587 | if decodedToken == dashToken { |
| 588 | // RFC 6901 §4 / RFC 6902 append semantics: terminal "-" appends the value to the slice. |
| 589 | // |
| 590 | // We rebind in place when the slice is reachable via an addressable ancestor; otherwise we |
| 591 | // return the new slice header for the parent (or the public Set) to rebind. |
| 592 | value := reflect.ValueOf(data) |
| 593 | elemType := rValue.Type().Elem() |
| 594 | if !value.Type().AssignableTo(elemType) { |
| 595 | return node, fmt.Errorf("can't append value of type %T to slice of %v: %w", data, elemType, ErrPointer) |
| 596 | } |
| 597 | newSlice := reflect.Append(rValue, value) |
| 598 | if rValue.CanSet() { |
| 599 | rValue.Set(newSlice) |
| 600 | return node, nil |
| 601 | } |
searching dependent graphs…