-
Notifications
You must be signed in to change notification settings - Fork 0
/
reflect.go
79 lines (68 loc) · 1.63 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
package table
import (
"bytes"
"reflect"
"github.com/Deepchain-foundation/lachesis-base/kvdb"
)
// MigrateTables sets target fields to database tables.
func MigrateTables(s interface{}, db kvdb.Store) {
value := reflect.ValueOf(s).Elem()
var keys uniqKeys
defer keys.Check()
for i := 0; i < value.NumField(); i++ {
if prefix := value.Type().Field(i).Tag.Get("table"); prefix != "" && prefix != "-" {
field := value.Field(i)
var val reflect.Value
if db != nil {
keys.Add(prefix)
table := New(db, []byte(prefix))
val = reflect.ValueOf(table)
} else {
val = reflect.Zero(field.Type())
}
field.Set(val)
}
}
}
// MigrateCaches sets target fields to get() result.
func MigrateCaches(c interface{}, get func() interface{}) {
value := reflect.ValueOf(c).Elem()
for i := 0; i < value.NumField(); i++ {
if prefix := value.Type().Field(i).Tag.Get("cache"); prefix != "" {
field := value.Field(i)
var cache interface{}
if get != nil {
cache = get()
}
var val reflect.Value
if cache != nil {
val = reflect.ValueOf(cache)
} else {
val = reflect.Zero(field.Type())
}
field.Set(val)
}
}
}
type uniqKeys struct {
len int
keys [][]byte
}
func (u *uniqKeys) Add(s string) {
key := []byte(s)
if len(u.keys) == 0 || u.len > len(key) {
u.len = len(key)
}
u.keys = append(u.keys, key)
}
func (u *uniqKeys) Check() {
for i := 0; i < len(u.keys); i++ {
for j := i + 1; j < len(u.keys); j++ {
a := u.keys[i][:u.len]
b := u.keys[j][:u.len]
if bytes.Equal(a, b) {
panic("prefixes '" + string(u.keys[i]) + "' and '" + string(u.keys[j]) + "' are the same")
}
}
}
}