-
Notifications
You must be signed in to change notification settings - Fork 9
/
iter.go
235 lines (200 loc) · 6.43 KB
/
iter.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package collections
import (
"fmt"
store "cosmossdk.io/store"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
)
// Order defines the key order.
type Order uint8
const (
// OrderAscending instructs the Iterator to provide keys from the smallest to the greatest.
OrderAscending Order = 0
// OrderDescending instructs the Iterator to provide keys from the greatest to the smallest.
OrderDescending Order = 1
)
// BoundInclusive creates a Bound of the provided key K
// which is inclusive. Meaning, if it is used as Ranger.RangeValues start,
// the provided key will be included if it exists in the Iterator range.
func BoundInclusive[K any](key K) *Bound[K] {
return &Bound[K]{
value: key,
inclusive: true,
}
}
// BoundExclusive creates a Bound of the provided key K
// which is exclusive. Meaning, if it is used as Ranger.RangeValues start,
// the provided key will be excluded if it exists in the Iterator range.
func BoundExclusive[K any](key K) *Bound[K] {
return &Bound[K]{
value: key,
inclusive: false,
}
}
// Bound defines key bounds for Start and Ends of iterator ranges.
type Bound[K any] struct {
value K
inclusive bool
}
// Ranger defines a generic interface that provides a range of keys.
type Ranger[K any] interface {
// RangeValues is defined by Ranger implementers.
// It provides instructions to generate an Iterator instance.
// If prefix is not nil, then the Iterator will return only the keys which start
// with the given prefix.
// If start is not nil, then the Iterator will return only keys which are greater than the provided start
// or greater equal depending on the bound is inclusive or exclusive.
// If end is not nil, then the Iterator will return only keys which are smaller than the provided end
// or smaller equal depending on the bound is inclusive or exclusive.
RangeValues() (prefix *K, start *Bound[K], end *Bound[K], order Order)
}
// Range is a Ranger implementer.
type Range[K any] struct {
prefix *K
start *Bound[K]
end *Bound[K]
order Order
}
// Prefix sets a fixed prefix for the key range.
func (r Range[K]) Prefix(key K) Range[K] {
r.prefix = &key
return r
}
// StartInclusive makes the range contain only keys which are bigger or equal to the provided start K.
func (r Range[K]) StartInclusive(start K) Range[K] {
r.start = BoundInclusive(start)
return r
}
// StartExclusive makes the range contain only keys which are bigger to the provided start K.
func (r Range[K]) StartExclusive(start K) Range[K] {
r.start = BoundExclusive(start)
return r
}
// EndInclusive makes the range contain only keys which are smaller or equal to the provided end K.
func (r Range[K]) EndInclusive(end K) Range[K] {
r.end = BoundInclusive(end)
return r
}
// EndExclusive makes the range contain only keys which are smaller to the provided end K.
func (r Range[K]) EndExclusive(end K) Range[K] {
r.end = BoundExclusive(end)
return r
}
func (r Range[K]) Descending() Range[K] {
r.order = OrderDescending
return r
}
func (r Range[K]) RangeValues() (prefix *K, start *Bound[K], end *Bound[K], order Order) {
return r.prefix, r.start, r.end, r.order
}
// iteratorFromRange generates an Iterator instance, with the proper prefixing and ranging.
func iteratorFromRange[K, V any](s store.KVStore, r Ranger[K], kc KeyEncoder[K], vc ValueEncoder[V]) Iterator[K, V] {
pfx, start, end, order := r.RangeValues()
var prefixBytes []byte
if pfx != nil {
prefixBytes = kc.Encode(*pfx)
s = prefix.NewStore(s, prefixBytes)
}
var startBytes []byte // default is nil
if start != nil {
startBytes = kc.Encode(start.value)
// iterators are inclusive at start by default
// so if we want to make the iteration exclusive
// we extend by one byte.
if !start.inclusive {
startBytes = extendOneByte(startBytes)
}
}
var endBytes []byte // default is nil
if end != nil {
endBytes = kc.Encode(end.value)
// iterators are exclusive at end by default
// so if we want to make the iteration
// inclusive we need to extend by one byte.
if end.inclusive {
endBytes = extendOneByte(endBytes)
}
}
var iter storetypes.Iterator
switch order {
case OrderAscending:
iter = s.Iterator(startBytes, endBytes)
case OrderDescending:
iter = s.ReverseIterator(startBytes, endBytes)
default:
panic(fmt.Errorf("unrecognized Order: %v", order))
}
return Iterator[K, V]{
kc: kc,
vc: vc,
iter: iter,
prefixBytes: prefixBytes,
}
}
// Iterator defines a generic wrapper around an storetypes.Iterator.
// This iterator provides automatic key and value encoding,
// it assumes all the keys and values contained within the storetypes.Iterator
// range are the same.
type Iterator[K, V any] struct {
kc KeyEncoder[K]
vc ValueEncoder[V]
iter storetypes.Iterator
prefixBytes []byte
}
// Value returns the current iterator value bytes decoded.
func (i Iterator[K, V]) Value() V {
return i.vc.Decode(i.iter.Value())
}
// Key returns the current storetypes.Iterator decoded key.
func (i Iterator[K, V]) Key() K {
rawKey := append(i.prefixBytes, i.iter.Key()...)
read, c := i.kc.Decode(rawKey)
if read != len(rawKey) {
panic(fmt.Sprintf("key decoder didn't fully consume the key: %T %x %d", i.kc, rawKey, read))
}
return c
}
// Values fully consumes the iterator and returns all the decoded values contained within the range.
func (i Iterator[K, V]) Values() []V {
defer i.Close()
var values []V
for ; i.iter.Valid(); i.iter.Next() {
values = append(values, i.Value())
}
return values
}
// Keys fully consumes the iterator and returns all the decoded keys contained within the range.
func (i Iterator[K, V]) Keys() []K {
defer i.Close()
var keys []K
for ; i.iter.Valid(); i.iter.Next() {
keys = append(keys, i.Key())
}
return keys
}
// KeyValue returns the current key and value decoded.
func (i Iterator[K, V]) KeyValue() KeyValue[K, V] {
return KeyValue[K, V]{
Key: i.Key(),
Value: i.Value(),
}
}
// KeyValues fully consumes the iterator and returns the list of key and values within the iterator range.
func (i Iterator[K, V]) KeyValues() []KeyValue[K, V] {
defer i.Close()
var kvs []KeyValue[K, V]
for ; i.iter.Valid(); i.iter.Next() {
kvs = append(kvs, i.KeyValue())
}
return kvs
}
func (i Iterator[K, V]) Close() { _ = i.iter.Close() }
func (i Iterator[K, V]) Next() { i.iter.Next() }
func (i Iterator[K, V]) Valid() bool { return i.iter.Valid() }
type KeyValue[K, V any] struct {
Key K
Value V
}
func extendOneByte(b []byte) []byte {
return append(b, 0)
}