github.com/ledgerwatch/erigon-lib@v1.0.0/kv/iter/iter_interface.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package iter 18 19 // Iterators - composable high-level abstraction to iterate over. It's more high-level than kv.Cursor and provides less controll, less features, but enough to build an app. 20 // 21 // for s.HasNext() { 22 // k, v, err := s.Next() 23 // if err != nil { 24 // return err 25 // } 26 // } 27 // Invariants: 28 // 1. HasNext() is Idempotent 29 // 2. K, V are valid at-least 2 .Next() calls! It allows zero-copy composition of iterators. Example: iter.Union 30 // - 1 value used by User and 1 value used internally by iter.Union 31 // 3. No `Close` method: all streams produced by TemporalTx will be closed inside `tx.Rollback()` (by casting to `kv.Closer`) 32 // 4. automatically checks cancelation of `ctx` passed to `db.Begin(ctx)`, can skip this 33 // check in loops on stream. Dual has very limited API - user has no way to 34 // terminate it - but user can specify more strict conditions when creating stream (then server knows better when to stop) 35 36 // Dual - return 2 items - usually called Key and Value (or `k` and `v`) 37 // Example: 38 // 39 // for s.HasNext() { 40 // k, v, err := s.Next() 41 // if err != nil { 42 // return err 43 // } 44 // } 45 type Dual[K, V any] interface { 46 Next() (K, V, error) 47 HasNext() bool 48 } 49 50 // Unary - return 1 item. Example: 51 // 52 // for s.HasNext() { 53 // v, err := s.Next() 54 // if err != nil { 55 // return err 56 // } 57 // } 58 type Unary[V any] interface { 59 Next() (V, error) 60 //NextBatch() ([]V, error) 61 HasNext() bool 62 } 63 64 // KV - return 2 items of type []byte - usually called Key and Value (or `k` and `v`). Example: 65 // 66 // for s.HasNext() { 67 // k, v, err := s.Next() 68 // if err != nil { 69 // return err 70 // } 71 // } 72 73 // often used shortcuts 74 type ( 75 U64 Unary[uint64] 76 KV Dual[[]byte, []byte] 77 ) 78 79 func ToU64Arr(s U64) ([]uint64, error) { return ToArr[uint64](s) } 80 func ToKVArray(s KV) ([][]byte, [][]byte, error) { return ToDualArray[[]byte, []byte](s) } 81 82 func ToArrU64Must(s U64) []uint64 { 83 arr, err := ToArr[uint64](s) 84 if err != nil { 85 panic(err) 86 } 87 return arr 88 } 89 func ToArrKVMust(s KV) ([][]byte, [][]byte) { 90 keys, values, err := ToDualArray[[]byte, []byte](s) 91 if err != nil { 92 panic(err) 93 } 94 return keys, values 95 } 96 97 func CountU64(s U64) (int, error) { return Count[uint64](s) } 98 func CountKV(s KV) (int, error) { return CountDual[[]byte, []byte](s) } 99 100 func TransformKV(it KV, transform func(k, v []byte) ([]byte, []byte, error)) *TransformDualIter[[]byte, []byte] { 101 return TransformDual[[]byte, []byte](it, transform) 102 } 103 104 // internal types 105 type ( 106 NextPageUnary[T any] func(pageToken string) (arr []T, nextPageToken string, err error) 107 NextPageDual[K, V any] func(pageToken string) (keys []K, values []V, nextPageToken string, err error) 108 ) 109 110 func PaginateKV(f NextPageDual[[]byte, []byte]) *PaginatedDual[[]byte, []byte] { 111 return PaginateDual[[]byte, []byte](f) 112 } 113 func PaginateU64(f NextPageUnary[uint64]) *Paginated[uint64] { 114 return Paginate[uint64](f) 115 }