forked from redis/rueidis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema.go
91 lines (78 loc) · 1.7 KB
/
schema.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
package om
import (
"fmt"
"reflect"
"strings"
)
const ignoreField = "-"
type schema struct {
key *field
ver *field
fields map[string]*field
}
type field struct {
typ reflect.Type
name string
idx int
isKey bool
isVer bool
}
func newSchema(t reflect.Type) schema {
if t.Kind() != reflect.Struct {
panic(fmt.Sprintf("schema %q should be a struct", t))
}
s := schema{fields: make(map[string]*field, t.NumField())}
for i := 0; i < t.NumField(); i++ {
sf := t.Field(i)
if !sf.IsExported() {
continue
}
f := parse(sf)
if f.name == ignoreField {
continue
}
f.idx = i
s.fields[f.name] = &f
if f.isKey {
if sf.Type.Kind() != reflect.String {
panic(fmt.Sprintf("field with tag `redis:\",key\"` in schema %q should be a string", t))
}
s.key = &f
}
if f.isVer {
if sf.Type.Kind() != reflect.Int64 {
panic(fmt.Sprintf("field with tag `redis:\",ver\"` in schema %q should be a int64", t))
}
s.ver = &f
}
}
if s.key == nil {
panic(fmt.Sprintf("schema %q should have one field with `redis:\",key\"` tag", t))
}
if s.ver == nil {
panic(fmt.Sprintf("schema %q should have one field with `redis:\",ver\"` tag", t))
}
return s
}
func parse(f reflect.StructField) (field field) {
v, _ := f.Tag.Lookup("json")
vs := strings.SplitN(v, ",", 1)
if vs[0] == "" {
field.name = f.Name
} else {
field.name = vs[0]
}
v, _ = f.Tag.Lookup("redis")
field.isKey = strings.Contains(v, ",key")
field.isVer = strings.Contains(v, ",ver")
field.typ = f.Type
return field
}
func key(prefix, id string) (key string) {
sb := strings.Builder{}
sb.Grow(len(prefix) + len(id) + 1)
sb.WriteString(prefix)
sb.WriteString(":")
sb.WriteString(id)
return sb.String()
}