-
Notifications
You must be signed in to change notification settings - Fork 2
/
object.go
131 lines (114 loc) · 2.81 KB
/
object.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package gtly
import (
"fmt"
"reflect"
"unsafe"
)
//Object represents dynamic object
type Object struct {
proto *Proto
setAt []bool
addr unsafe.Pointer
value reflect.Value
}
//Set sets a value from a map of a slice (slice index has to match field index)
func (o *Object) Set(val interface{}) error {
switch actual := val.(type) {
case map[string]interface{}:
for k, v := range actual {
o.proto.Mutator(k).SetValue(o, v)
}
return nil
case []interface{}:
for k, v := range actual {
o.proto.MutatorAt(k).SetValue(o, v)
}
return nil
}
return fmt.Errorf("unsupported type: %T", val)
}
//Proto returns object proto
func (o *Object) Proto() *Proto {
return o.proto
}
//Addr returns struct unsafe pointer
func (o *Object) Addr() unsafe.Pointer {
return o.addr
}
//Interface returns a struct value
func (o *Object) Interface() interface{} {
return o.proto.xType.Interface(o.addr)
}
//SetValue sets fieldValues
func (o *Object) SetValue(fieldName string, value interface{}) {
field := o.proto.Field(fieldName)
o.proto.mutators[field.Index].SetValue(o, value)
}
//SetValueAt sets field's value
func (o *Object) SetValueAt(fieldIndex int, value interface{}) {
o.proto.mutators[fieldIndex].SetValue(o, value)
}
//Value get value for supplied filed name
func (o *Object) Value(fieldName string) interface{} {
field := o.proto.Field(fieldName)
if field.Index >= len(o.setAt) || !o.setAt[field.Index] {
return nil
}
return o.proto.accessors[field.Index].Value(o)
}
//ValueAt get value for supplied filed Index
func (o *Object) ValueAt(fieldIndex int) (interface{}, bool) {
if fieldIndex >= len(o.setAt) || !o.setAt[fieldIndex] {
return nil, false
}
return o.proto.accessors[fieldIndex].Value(o), true
}
//SetAt returns true if value was set at given index
func (o *Object) SetAt(index int) bool {
if index >= len(o.setAt) {
return false
}
return o.setAt[index]
}
func (o *Object) markFieldSet(index int) {
o.setAt[index] = true
}
//IsNil returns true if object is nil
func (o *Object) IsNil() bool {
for _, v := range o.setAt {
if v == true {
return false
}
}
return true
}
//AsMap return map
func (o *Object) AsMap() map[string]interface{} {
result := map[string]interface{}{}
fields := o.proto.Fields()
for i := range o.proto.accessors {
field := &fields[i]
if !o.SetAt(field.Index) || field.hidden {
continue
}
outputName := o.FieldOutputName(field)
if outputName == "" {
continue
}
value := o.proto.accessors[i].Value(o)
result[outputName] = value
}
return result
}
//FieldOutputName returns Field output name
func (o *Object) FieldOutputName(field *Field) string {
outputName := field.Name
if field.outputName != "" {
outputName = field.outputName
}
return outputName
}
//Field returns Field by name
func (o *Object) Field(name string) *Field {
return o.proto.Field(name)
}