-
Notifications
You must be signed in to change notification settings - Fork 11
/
clientargs.go
131 lines (100 loc) · 3.22 KB
/
clientargs.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 clientargs
import (
"reflect"
"strings"
"qlova.org/seed/client"
"qlova.org/seed/use/js"
)
//PassGoValues can be embedded inside of a clientside-arguments struct to enable the passthrough of Go arguments.
//these arguments must be decoded with this type's methods after being parsed.
type PassGoValues struct {
arguments client.Object
ints int
}
func (p PassGoValues) getPassGoValues() PassGoValues {
return p
}
//Is returns a client reference to 'true' if the given popup field is equal to the provided value.
func (p PassGoValues) Is(field interface{}, value interface{}) client.Bool {
var T = reflect.TypeOf(field)
var V = reflect.ValueOf(field)
switch T.Kind() {
case reflect.Int:
return p.arguments.GetObject().Value.Get("types").Get("int").Index(int(V.Int()) - 1).Equals(js.ValueOf(value))
}
return client.NewBool(false)
}
func valueAs(v js.AnyValue, T reflect.Type) reflect.Value {
var TypeName = strings.TrimPrefix(T.Name(), "Any")
if strings.Contains(TypeName, ".") {
TypeName = strings.Split(TypeName, ".")[1]
}
if method, ok := T.MethodByName("Get" + TypeName); ok {
Type := method.Type.Out(0)
var result = reflect.New(Type).Elem()
result.FieldByName("Value").Set(reflect.ValueOf(v.GetValue()))
return result
}
return reflect.Zero(T)
}
//Parse parses the arguments of a clientside-arguments struct and returns the converted client-side arguments struct as an interface and the client representation of it.
func Parse(structure interface{}, arguments client.Object) (interface{}, client.Object) {
type passingGoValues interface {
getPassGoValues() PassGoValues
}
getter, passing := structure.(passingGoValues)
var pgv PassGoValues
if passing {
pgv = getter.getPassGoValues()
pgv.arguments = arguments
}
var T = reflect.TypeOf(structure)
var V = reflect.ValueOf(structure)
var object = make(map[string]js.AnyValue, T.NumField())
var TypeTable = js.NewObject{}
if object["types"] == nil {
object["types"] = TypeTable
}
var Converted = reflect.New(T).Elem()
for i := 0; i < T.NumField(); i++ {
var Field = T.Field(i)
var FieldValue = V.Field(i)
if Field.Type.Implements(reflect.TypeOf((*js.AnyValue)(nil)).Elem()) {
var key = Field.Name
if intf := FieldValue.Interface(); intf != nil {
object[key] = intf.(js.AnyValue)
} else {
object[key] = js.Null()
}
var value = arguments.GetObject().Get(client.NewString(key))
Converted.Field(i).Set(valueAs(value, Field.Type))
} else if passing {
if _, ok := FieldValue.Interface().(passingGoValues); ok {
val := FieldValue
cval := Converted.Field(i)
for {
if val.Type() == reflect.TypeOf(PassGoValues{}) {
cval.Set(reflect.ValueOf(pgv))
break
}
val = val.Field(0)
cval = cval.Field(0)
}
continue
}
switch Field.Type.Kind() {
case reflect.Int:
pgv.ints++
if TypeTable["int"] == nil {
TypeTable["int"] = js.NewArray{}
}
ints := TypeTable["int"].(js.NewArray)
TypeTable["int"] = append(ints, js.NewNumber(float64(FieldValue.Int())))
Converted.Field(i).SetInt(int64(pgv.ints))
default:
panic("clientargs.Parse: unsupported type: " + Field.Type.String())
}
}
}
return Converted.Interface(), js.NewObject(object)
}