-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiterator.go
152 lines (131 loc) · 3.92 KB
/
iterator.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package biter
import (
"bytes"
"github.com/dgraph-io/badger/v3"
)
// Iterator adds an implementable target for variations of different Iterator(s)
// for simplification of functional code, that you can then implement this reduced
// interface such that primarily methods Rewind and Valid and Next are overloaded.
// usage:
// for iterator.Rewind(); iterator.Valid(); iterator.Next() {
// iterator.Item()
// ...
// }
// this is a general snippet of code that using this interface may have changed implementation
// only Rewind and Valid are changes
type Iterator interface {
Rewind()
Valid() bool
Next()
Item() *badger.Item
}
//badgerPrefixIterator seek's to the prefix and ends at the end of the prefix
type badgerPrefixIterator struct {
*badger.Iterator
prefix []byte
}
func (b *badgerPrefixIterator) Rewind() {
b.Seek(b.prefix)
}
func (b *badgerPrefixIterator) Valid() bool {
return b.ValidForPrefix(b.prefix)
}
//badgerFromIterator seeks to from, then keeps going as usual
type badgerFromIterator struct {
*badger.Iterator
from []byte
}
func (b *badgerFromIterator) Valid() bool {
return b.Iterator.Valid()
}
func (b *badgerFromIterator) Rewind() {
b.Seek(b.from)
}
//badgerToIterator starts at the top, and keeps going until to is less than the current key
type badgerToIterator struct {
*badger.Iterator
to []byte
}
func (b *badgerToIterator) Valid() bool {
return b.Iterator.Valid() && keyLtEq(b.Item().Key(), b.to)
}
//badgerFromToIterator seeks to from, and stops at to
type badgerFromToIterator struct {
*badger.Iterator
from, to []byte
}
func (b *badgerFromToIterator) Valid() bool {
return b.Iterator.Valid() && keyLtEq(b.Item().Key(), b.to)
}
func (b *badgerFromToIterator) Rewind() {
b.Seek(b.from)
}
//badgerPrefixFromIterator is like a badgerPrefixIterator,
//but it rewinds to from in stead
type badgerPrefixFromIterator struct {
*badgerPrefixIterator
from []byte
}
func (b *badgerPrefixFromIterator) Rewind() {
b.Seek(b.from)
}
//badgerPrefixToIterator does not exist as the method set
//is completely similar to that of badgerFromToIterator
func keyLtEq(key, upperBound []byte) bool {
return 1 > bytes.Compare(key, upperBound)
}
// KeyRangeIterator returns an Iterator interface implementation, that wraps the badger.Iterator
// in order to simplify iterating with from-to and/or prefix.
func KeyRangeIterator(it *badger.Iterator, prefix, from, to []byte) Iterator {
lPref, lFrom, lTo := len(prefix), len(from), len(to)
switch {
case lPref+lFrom+lTo == 0:
return it
case lPref != 0 && lFrom+lTo == 0:
return &badgerPrefixIterator{it, prefix}
case lTo != 0 && lPref+lFrom == 0:
return &badgerToIterator{it, to}
case lFrom != 0 && lPref+lTo == 0:
return &badgerFromIterator{it, from}
case lFrom != 0 && lTo != 0 && lPref == 0:
return &badgerFromToIterator{it, from, to}
case lFrom == 0:
lastInPrefix := lastInPrefix(prefix, to)
if keyLtEq(lastInPrefix, to) {
return &badgerPrefixIterator{it, prefix}
}
return &badgerFromToIterator{it, prefix, to}
case lTo == 0:
if bytes.Compare(prefix, from) >= 0 {
return &badgerPrefixIterator{it, prefix}
}
return &badgerPrefixFromIterator{&badgerPrefixIterator{it, prefix}, from}
default: // all is set
return iteratorOfAll(it, prefix, from, to)
}
}
func lastInPrefix(prefix, to []byte) []byte {
lastValueInPrefix := prefix
if len(to)-len(prefix) > 0 {
padding := make([]byte, len(to)-len(prefix))
for i := range padding {
padding[i] = uint8(255)
}
lastValueInPrefix = append(lastValueInPrefix, padding...)
}
return lastValueInPrefix
}
func iteratorOfAll(it *badger.Iterator, prefix, from, to []byte) Iterator {
f, t := from, to
if bytes.Compare(prefix, from) >= 0 {
f = prefix
}
lastInPrefix := lastInPrefix(prefix, to)
if keyLtEq(lastInPrefix, to) {
if bytes.Equal(f, prefix) {
return &badgerPrefixIterator{it, prefix}
}
return &badgerPrefixFromIterator{&badgerPrefixIterator{it, prefix}, f}
}
return &badgerFromToIterator{it, f, t}
}