-
Notifications
You must be signed in to change notification settings - Fork 2
/
describe.go
127 lines (111 loc) · 2.4 KB
/
describe.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
package zcl
import (
"log"
"reflect"
)
type ValueDescription struct {
Index int
Name string
Type TypeID
List bool
ListType *ValueDescription
EnumValues []Option
BitmapValues []Option
Default Val
}
type CommandDescription struct {
Name string
ClusterID *ClusterID
Required bool
MnfCode *uint16
List bool
Arguments []ValueDescription
}
func DescribeAttr(attr Argument) (desc ValueDescription) {
ft := reflect.TypeOf(attr)
desc.Name = ft.Elem().Name()
if ea, ok := attr.(EnumArg); ok {
desc.EnumValues = ea.SingleOptions()
} else if ea, ok := attr.(BitmapArg); ok {
desc.BitmapValues = ea.MultiOptions()
}
desc.Type = attr.TypeID()
desc.List = ft.Kind() == reflect.Slice
return
}
func DescribeArgs(cmd interface{}) (v []ValueDescription) {
rv := reflect.ValueOf(cmd)
rf := reflect.TypeOf(cmd)
if rf.Kind() == reflect.Ptr {
rf = rf.Elem()
rv = rv.Elem()
}
if rf.Kind() != reflect.Struct {
return
}
for i := 0; i < rf.NumField(); i++ {
f := rf.Field(i)
fv := rv.Field(i)
//ft := f.Type
if !fv.CanInterface() {
continue
}
fd := ValueDescription{}
if attr, ok := fv.Interface().(Argument); ok {
fd = DescribeAttr(attr)
} else if attr, ok := fv.Addr().Interface().(Argument); ok {
fd = DescribeAttr(attr)
} else {
log.Printf("Unable to describe argument %s of %s: %s %#v", f.Name, rf.Name(), fv.Type(), fv)
}
fd.Index = i
fd.Name = f.Name
v = append(v, fd)
}
return
}
func DescribeGeneral(cmd General) (desc CommandDescription) {
rv := reflect.ValueOf(cmd)
rf := reflect.TypeOf(cmd)
if rf.Kind() == reflect.Ptr {
rf = rf.Elem()
rv = rv.Elem()
}
desc.Name = rf.Name()
switch rf.Kind() {
case reflect.Slice:
//t := rf.Elem()
desc.List = true
desc.Arguments = []ValueDescription{{
Index: -1,
Name: rf.Name(),
}}
case reflect.Struct:
desc.Arguments = DescribeArgs(cmd)
}
return
}
func DescribeCommand(cmd Command) (desc CommandDescription) {
desc = DescribeGeneral(cmd)
c := cmd.Cluster()
desc.ClusterID = &c
m := cmd.MnfCode()
if m > 0 {
desc.MnfCode = &m
}
desc.Required = cmd.Required()
return
}
func DescribeZdoCommand(cmd ZdoCommand) (desc CommandDescription) {
rf := reflect.TypeOf(cmd)
if rf.Kind() == reflect.Ptr {
rf = rf.Elem()
}
c := cmd.Cluster()
desc = CommandDescription{
Name: rf.Name(),
Arguments: DescribeArgs(cmd),
ClusterID: &c,
}
return
}