-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreflection.go
132 lines (109 loc) · 3.29 KB
/
reflection.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
132
package main
import (
"fmt"
"math/big"
"reflect"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/iancoleman/orderedmap"
"github.com/ipfs/go-cid"
)
// Special data types
var addressType = reflect.TypeOf((*address.Address)(nil)).Elem()
var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
var bitFieldType = reflect.TypeOf((*bitfield.BitField)(nil)).Elem()
var cidType = reflect.TypeOf((*cid.Cid)(nil)).Elem()
func GetDataType(t reflect.Type) DataType {
var dataType DataType
dataType.Name = t.Name()
// Handle special types
switch t.String() {
case addressType.String():
dataType.Type = TypeString
return dataType
case bigIntType.String():
dataType.Name = "FilecoinNumber"
dataType.Type = TypeString
return dataType
case bitFieldType.String():
containsType := DataType{Name: "Bit", Type: TypeNumber}
dataType.Type = TypeArray
dataType.Contains = &containsType
return dataType
case cidType.String():
dataType.Type = TypeObject
dataType.Children = orderedmap.New()
dataType.Children.SetEscapeHTML(false)
dataType.Children.Set("/", DataType{Name: "CidString", Type: TypeString})
return dataType
}
// Handle base types
switch t.Kind() {
case reflect.Ptr:
return GetDataType(t.Elem())
case reflect.Bool:
dataType.Type = TypeBool
return dataType
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
dataType.Type = TypeNumber
return dataType
case reflect.String:
dataType.Type = TypeString
return dataType
case reflect.Chan:
containsType := GetDataType(t.Elem())
dataType.Type = TypeChan
dataType.ChanDir = t.ChanDir().String()
dataType.Contains = &containsType
return dataType
case reflect.Map:
keyType := GetDataType(t.Key())
containsType := GetDataType(t.Elem())
dataType.Type = TypeMap
dataType.Key = &keyType
dataType.Contains = &containsType
return dataType
case reflect.Array, reflect.Slice:
containsType := GetDataType(t.Elem())
// Treat uint8 arrays as bytes
if containsType.Name == "uint8" {
dataType.Type = TypeBytes
return dataType
}
dataType.Type = TypeArray
dataType.Contains = &containsType
return dataType
case reflect.Struct:
dataType.Type = TypeObject
dataType.Children = orderedmap.New()
dataType.Children.SetEscapeHTML(false)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
dataType.Children.Set(f.Name, GetDataType(f.Type))
}
return dataType
case reflect.Func:
dataType.Type = TypeFunction
dataType.IsVariadic = t.IsVariadic()
for i := 0; i < t.NumIn(); i++ {
dataType.Params = append(dataType.Params, GetDataType(t.In(i)))
}
for i := 0; i < t.NumOut(); i++ {
dataType.Returns = append(dataType.Returns, GetDataType(t.Out(i)))
}
return dataType
case reflect.Interface:
dataType.Type = TypeInterface
dataType.Methods = orderedmap.New()
dataType.Methods.SetEscapeHTML(false)
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
dataType.Methods.Set(m.Name, GetDataType(m.Type))
}
return dataType
}
// Unhandled type
panic(fmt.Sprintf("Unhandled type with string: %s, name: %s, kind: %s", t.String(), t.Name(), t.Kind().String()))
}