-
Notifications
You must be signed in to change notification settings - Fork 16
/
renamer.go
75 lines (65 loc) · 2.01 KB
/
renamer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package codec
import (
"fmt"
"reflect"
"unicode"
"github.com/smartcontractkit/chainlink-common/pkg/types"
)
func NewRenamer(fields map[string]string) Modifier {
m := &renamer{
modifierBase: modifierBase[string]{
fields: fields,
onToOffChainType: map[reflect.Type]reflect.Type{},
offToOnChainType: map[reflect.Type]reflect.Type{},
},
}
m.modifyFieldForInput = func(pkgPath string, field *reflect.StructField, _, newName string) error {
field.Name = newName
if unicode.IsLower(rune(field.Name[0])) {
field.PkgPath = pkgPath
}
return nil
}
return m
}
type renamer struct {
modifierBase[string]
}
func (r *renamer) TransformToOffChain(onChainValue any, _ string) (any, error) {
rOutput, err := renameTransform(r.onToOffChainType, reflect.ValueOf(onChainValue))
if err != nil {
return nil, err
}
return rOutput.Interface(), nil
}
func (r *renamer) TransformToOnChain(offChainValue any, _ string) (any, error) {
rOutput, err := renameTransform(r.offToOnChainType, reflect.ValueOf(offChainValue))
if err != nil {
return nil, err
}
return rOutput.Interface(), nil
}
func renameTransform(typeMap map[reflect.Type]reflect.Type, rInput reflect.Value) (reflect.Value, error) {
toType, ok := typeMap[rInput.Type()]
if !ok {
return reflect.Value{}, fmt.Errorf("%w: cannot rename unknown type %v", types.ErrInvalidType, toType)
}
if toType == rInput.Type() {
return rInput, nil
}
switch rInput.Kind() {
case reflect.Pointer:
return reflect.NewAt(toType.Elem(), rInput.UnsafePointer()), nil
case reflect.Struct, reflect.Slice, reflect.Array:
return transformNonPointer(toType, rInput)
default:
return reflect.Value{}, fmt.Errorf("%w: cannot rename kind %v", types.ErrInvalidType, rInput.Kind())
}
}
func transformNonPointer(toType reflect.Type, rInput reflect.Value) (reflect.Value, error) {
// make sure the input is addressable
ptr := reflect.New(rInput.Type())
reflect.Indirect(ptr).Set(rInput)
changed := reflect.NewAt(toType, ptr.UnsafePointer()).Elem()
return changed, nil
}