/
index.go
80 lines (67 loc) · 1.73 KB
/
index.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
package fsm
import (
"encoding/binary"
"fmt"
"reflect"
)
// IntFieldIndex is used to extract a int field from an object using
// reflection and builds an index on that field.
type IntFieldIndex struct {
Field string
}
func (u *IntFieldIndex) FromObject(obj interface{}) (bool, []byte, error) {
v := reflect.ValueOf(obj)
v = reflect.Indirect(v) // Dereference the pointer if any
fv := v.FieldByName(u.Field)
if !fv.IsValid() {
return false, nil,
fmt.Errorf("field '%s' for %#v is invalid", u.Field, obj)
}
// Check the type
k := fv.Kind()
size, ok := IsIntType(k)
if !ok {
return false, nil, fmt.Errorf("field %q is of type %v; want a int", u.Field, k)
}
// Get the value and encode it
val := fv.Int()
buf := make([]byte, size)
binary.PutVarint(buf, val)
return true, buf, nil
}
func (u *IntFieldIndex) FromArgs(args ...interface{}) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
v := reflect.ValueOf(args[0])
if !v.IsValid() {
return nil, fmt.Errorf("%#v is invalid", args[0])
}
k := v.Kind()
size, ok := IsIntType(k)
if !ok {
return nil, fmt.Errorf("arg is of type %v; want a int", k)
}
val := v.Int()
buf := make([]byte, size)
binary.PutVarint(buf, val)
return buf, nil
}
// IsIntType returns whether the passed type is a type of int and the number
// of bytes needed to encode the type.
func IsIntType(k reflect.Kind) (size int, okay bool) {
switch k {
case reflect.Int:
return binary.MaxVarintLen64, true
case reflect.Int8:
return 2, true
case reflect.Int16:
return binary.MaxVarintLen16, true
case reflect.Int32:
return binary.MaxVarintLen32, true
case reflect.Int64:
return binary.MaxVarintLen64, true
default:
return 0, false
}
}