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  }