/
reflect.go
124 lines (98 loc) · 2.51 KB
/
reflect.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
package statedb
import (
"errors"
"fmt"
"reflect"
)
type Mutable interface {
Mutable() interface{}
}
type KeyStr interface {
Key() string
}
type KeyInt interface {
Key() int
}
type Typer interface {
Type() string
}
func ReflectKeyTypeM(v interface{}) (*KeyType, error) {
if v == nil {
return nil, errors.New("Keytype: <nil> does not have keytype")
}
typ := ReflectTypeM(v)
key, err := ReflectKeyM(v)
if err != nil {
return nil, err
}
return &KeyType{*key, typ}, nil
}
// If no Type method is defined, use reflect to determine type
func ReflectTypeM(v interface{}) string {
// call Type if object supports it
if m, ok := v.(Typer); ok {
return m.Type()
}
// or reflect the type instead
return ReflectType(v)
}
func ReflectKeyM(v interface{}) (*Key, error) {
if m, ok := v.(KeyInt); ok {
return NewIntKey(m.Key())
}
if m, ok := v.(KeyStr); ok {
return NewStringKey(m.Key())
}
k, err := ReflectKey(v)
if err != nil {
return nil, err
}
return k, nil
}
// Return the unique type if for any object
func ReflectType(i interface{}) string {
if i == nil {
return ""
}
return reflectType(reflect.ValueOf(i))
}
// Return the unique type if for any object
func reflectType(val reflect.Value) string {
return Indirect(val).Type().String()
}
// Use reflect to generate the key from the "ID" field in a struct
func ReflectKey(i interface{}) (*Key, error) {
if i == nil {
return nil, errors.New("Key: <nil> has no key")
}
val := Indirect(reflect.ValueOf(i))
return reflectKey(val)
}
// Search for a field named 'ID' in the provided struct
// - The 'ID' field must be of type Int | String, any other type
// results in an error
func reflectKey(val reflect.Value) (*Key, error) {
if val.Kind() == reflect.Ptr && val.IsNil() {
return nil, fmt.Errorf("Key: <nil> pointer of type %s", val.String())
}
if val.Kind() == reflect.Ptr {
val = Indirect(val)
}
// TODO: for static-only states (meaning no mutability)
// this might be too limiting.
if val.Kind() != reflect.Struct {
return nil, errors.New("Key: only structs can have a Key")
}
id_field := val.FieldByName("ID")
if !id_field.IsValid() {
return nil, fmt.Errorf("%s does not have field with name = 'ID'", val.Type().String())
}
switch id_field.Kind() {
case reflect.String:
return NewStringKey(id_field.String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return NewIntKey(int(id_field.Int()))
default:
return nil, fmt.Errorf("Field 'ID' is of invalid type: %v\n", id_field.Kind())
}
}