-
Notifications
You must be signed in to change notification settings - Fork 1
/
offset.go
126 lines (112 loc) · 2.48 KB
/
offset.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
package nflex
import (
"strconv"
"github.com/pkg/errors"
)
type offset struct {
offsets []int
source Source
debugID int
}
// WithOffset returns a modified source that offsets slice lookups
// such that it requires a larger key to do the lookup.
func WithOffset(source Source, offsets ...int) Source {
if source == nil {
return nil
}
return offset{
offsets: offsets,
source: source,
debugID: debugID(),
}
}
func (o offset) transform(keys []string) ([]string, error) {
n := make([]string, len(keys))
for i, key := range keys {
if o.offsets[i] == 0 {
n[i] = key
continue
}
k, err := strconv.Atoi(key)
if err != nil {
return nil, errors.Wrap(err, "expecting integer key")
}
n[i] = strconv.Itoa(k - o.offsets[i])
}
return n, nil
}
func (o offset) Exists(keys ...string) bool {
tk, err := o.transform(keys)
if err != nil {
return false
}
return o.source.Exists(tk...)
}
func (o offset) GetBool(keys ...string) (bool, error) {
tk, err := o.transform(keys)
if err != nil {
return false, err
}
return o.source.GetBool(tk...)
}
func (o offset) GetInt(keys ...string) (int64, error) {
tk, err := o.transform(keys)
if err != nil {
return 0, err
}
return o.source.GetInt(tk...)
}
func (o offset) GetFloat(keys ...string) (float64, error) {
tk, err := o.transform(keys)
if err != nil {
return 0, err
}
return o.source.GetFloat(tk...)
}
func (o offset) GetString(keys ...string) (string, error) {
tk, err := o.transform(keys)
if err != nil {
return "", err
}
return o.source.GetString(tk...)
}
func (o offset) Recurse(keys ...string) Source {
tk, err := o.transform(keys)
if err != nil {
debug("nflex/offset Recurse(", keys, ")", id(o), "-> nil")
return nil
}
r := o.source.Recurse(tk...)
if len(o.offsets) <= len(keys) {
debug("nflex/offset Recurse(", keys, ")", id(o), "-> no offset")
return r
}
n := WithOffset(r, o.offsets[len(keys):]...)
debug("nflex/offset Recurse(", keys, ")", id(o), "->", id(n))
return n
}
func (o offset) Keys(keys ...string) ([]string, error) {
tk, err := o.transform(keys)
if err != nil {
return nil, err
}
return o.source.Keys(tk...)
}
func (o offset) Len(keys ...string) (int, error) {
tk, err := o.transform(keys)
if err != nil {
return 0, err
}
length, err := o.source.Len(tk...)
if len(o.offsets) <= len(keys) {
return length, err
}
return length, err
}
func (o offset) Type(keys ...string) NodeType {
tk, err := o.transform(keys)
if err != nil {
return Undefined
}
return o.source.Type(tk...)
}