-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathutils.go
114 lines (103 loc) · 2.84 KB
/
utils.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package splitwise
import (
"fmt"
"reflect"
)
func NewErrFailConversion(value interface{}) error {
return fmt.Errorf("can't convert value %v", value)
}
func buildStructValues(structFields []reflect.StructField, values []interface{}) (interface{}, error) {
typ := reflect.StructOf(structFields)
instance := reflect.New(typ).Elem()
for i := 0; i < instance.NumField(); i++ {
varType := instance.Type().Field(i).Type
switch varType.Kind() {
case reflect.Int:
v, ok := (values[i]).(int)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetInt(int64(v))
case reflect.Int32:
v, ok := (values[i]).(int32)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetInt(int64(v))
case reflect.Int64:
v, ok := (values[i]).(int64)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetInt(v)
case reflect.Uint:
v, ok := (values[i]).(uint)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetUint(uint64(v))
case reflect.Uint32:
v, ok := (values[i]).(uint32)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetUint(uint64(v))
case reflect.Uint64:
v, ok := (values[i]).(uint64)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetUint(v)
case reflect.Float32:
v, ok := (values[i]).(float32)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetFloat(float64(v))
case reflect.Float64:
v, ok := (values[i]).(float64)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetFloat(v)
case reflect.Bool:
v, ok := (values[i]).(bool)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetBool(v)
case reflect.String:
v, ok := (values[i]).(string)
if !ok {
return nil, NewErrFailConversion(values[i])
}
instance.Field(i).SetString(v)
default:
return nil, fmt.Errorf("unexpected type %s", varType.Kind())
}
}
return instance.Addr().Interface(), nil
}
func mergeStructFields(inputs ...interface{}) ([]reflect.StructField, []interface{}) {
var fields []reflect.StructField
var finalValues []interface{}
for _, input := range inputs {
values := reflect.Indirect(reflect.ValueOf(input))
types := values.Type()
for i := 0; i < values.NumField(); i++ {
val := values.Field(i)
typ := types.Field(i)
fields = append(fields, reflect.StructField{
Name: typ.Name,
Type: reflect.TypeOf(val.Interface()),
Tag: reflect.StructTag(string(typ.Tag)),
})
finalValues = append(finalValues, val.Interface())
}
}
return fields, finalValues
}
func MergeStructs(inputs ...interface{}) (interface{}, error) {
fields, values := mergeStructFields(inputs...)
return buildStructValues(fields, values)
}