github.com/ledgerwatch/erigon-lib@v1.0.0/kv/iter/iter.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  import (
    20  	"bytes"
    21  
    22  	"github.com/ledgerwatch/erigon-lib/kv/order"
    23  	"golang.org/x/exp/constraints"
    24  	"golang.org/x/exp/slices"
    25  )
    26  
    27  type Closer interface {
    28  	Close()
    29  }
    30  
    31  var (
    32  	EmptyU64 = &EmptyUnary[uint64]{}
    33  	EmptyKV  = &EmptyDual[[]byte, []byte]{}
    34  )
    35  
    36  type (
    37  	EmptyUnary[T any]   struct{}
    38  	EmptyDual[K, V any] struct{}
    39  )
    40  
    41  func (EmptyUnary[T]) HasNext() bool                 { return false }
    42  func (EmptyUnary[T]) Next() (v T, err error)        { return v, err }
    43  func (EmptyDual[K, V]) HasNext() bool               { return false }
    44  func (EmptyDual[K, V]) Next() (k K, v V, err error) { return k, v, err }
    45  
    46  type ArrStream[V any] struct {
    47  	arr []V
    48  	i   int
    49  }
    50  
    51  func ReverseArray[V any](arr []V) *ArrStream[V] {
    52  	arr = slices.Clone(arr)
    53  	for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 {
    54  		arr[i], arr[j] = arr[j], arr[i]
    55  	}
    56  	return Array(arr)
    57  }
    58  func Array[V any](arr []V) *ArrStream[V] { return &ArrStream[V]{arr: arr} }
    59  func (it *ArrStream[V]) HasNext() bool   { return it.i < len(it.arr) }
    60  func (it *ArrStream[V]) Close()          {}
    61  func (it *ArrStream[V]) Next() (V, error) {
    62  	v := it.arr[it.i]
    63  	it.i++
    64  	return v, nil
    65  }
    66  func (it *ArrStream[V]) NextBatch() ([]V, error) {
    67  	v := it.arr[it.i:]
    68  	it.i = len(it.arr)
    69  	return v, nil
    70  }
    71  
    72  func Range[T constraints.Integer](from, to T) *RangeIter[T] {
    73  	if from == to {
    74  		to++
    75  	}
    76  	return &RangeIter[T]{i: from, to: to}
    77  }
    78  
    79  type RangeIter[T constraints.Integer] struct {
    80  	i, to T
    81  }
    82  
    83  func (it *RangeIter[T]) HasNext() bool { return it.i < it.to }
    84  func (it *RangeIter[T]) Close()        {}
    85  func (it *RangeIter[T]) Next() (T, error) {
    86  	v := it.i
    87  	it.i++
    88  	return v, nil
    89  }
    90  
    91  // UnionKVIter - merge 2 kv.Pairs streams to 1 in lexicographically order
    92  // 1-st stream has higher priority - when 2 streams return same key
    93  type UnionKVIter struct {
    94  	x, y               KV
    95  	xHasNext, yHasNext bool
    96  	xNextK, xNextV     []byte
    97  	yNextK, yNextV     []byte
    98  	limit              int
    99  	err                error
   100  }
   101  
   102  func UnionKV(x, y KV, limit int) KV {
   103  	if x == nil && y == nil {
   104  		return EmptyKV
   105  	}
   106  	if x == nil {
   107  		return y
   108  	}
   109  	if y == nil {
   110  		return x
   111  	}
   112  	m := &UnionKVIter{x: x, y: y, limit: limit}
   113  	m.advanceX()
   114  	m.advanceY()
   115  	return m
   116  }
   117  func (m *UnionKVIter) HasNext() bool {
   118  	return m.err != nil || (m.limit != 0 && m.xHasNext) || (m.limit != 0 && m.yHasNext)
   119  }
   120  func (m *UnionKVIter) advanceX() {
   121  	if m.err != nil {
   122  		return
   123  	}
   124  	m.xHasNext = m.x.HasNext()
   125  	if m.xHasNext {
   126  		m.xNextK, m.xNextV, m.err = m.x.Next()
   127  	}
   128  }
   129  func (m *UnionKVIter) advanceY() {
   130  	if m.err != nil {
   131  		return
   132  	}
   133  	m.yHasNext = m.y.HasNext()
   134  	if m.yHasNext {
   135  		m.yNextK, m.yNextV, m.err = m.y.Next()
   136  	}
   137  }
   138  func (m *UnionKVIter) Next() ([]byte, []byte, error) {
   139  	if m.err != nil {
   140  		return nil, nil, m.err
   141  	}
   142  	m.limit--
   143  	if m.xHasNext && m.yHasNext {
   144  		cmp := bytes.Compare(m.xNextK, m.yNextK)
   145  		if cmp < 0 {
   146  			k, v, err := m.xNextK, m.xNextV, m.err
   147  			m.advanceX()
   148  			return k, v, err
   149  		} else if cmp == 0 {
   150  			k, v, err := m.xNextK, m.xNextV, m.err
   151  			m.advanceX()
   152  			m.advanceY()
   153  			return k, v, err
   154  		}
   155  		k, v, err := m.yNextK, m.yNextV, m.err
   156  		m.advanceY()
   157  		return k, v, err
   158  	}
   159  	if m.xHasNext {
   160  		k, v, err := m.xNextK, m.xNextV, m.err
   161  		m.advanceX()
   162  		return k, v, err
   163  	}
   164  	k, v, err := m.yNextK, m.yNextV, m.err
   165  	m.advanceY()
   166  	return k, v, err
   167  }
   168  
   169  // func (m *UnionKVIter) ToArray() (keys, values [][]byte, err error) { return ToKVArray(m) }
   170  func (m *UnionKVIter) Close() {
   171  	if x, ok := m.x.(Closer); ok {
   172  		x.Close()
   173  	}
   174  	if y, ok := m.y.(Closer); ok {
   175  		y.Close()
   176  	}
   177  }
   178  
   179  // UnionUnary
   180  type UnionUnary[T constraints.Ordered] struct {
   181  	x, y           Unary[T]
   182  	asc            bool
   183  	xHas, yHas     bool
   184  	xNextK, yNextK T
   185  	err            error
   186  	limit          int
   187  }
   188  
   189  func Union[T constraints.Ordered](x, y Unary[T], asc order.By, limit int) Unary[T] {
   190  	if x == nil && y == nil {
   191  		return &EmptyUnary[T]{}
   192  	}
   193  	if x == nil {
   194  		return y
   195  	}
   196  	if y == nil {
   197  		return x
   198  	}
   199  	if !x.HasNext() {
   200  		return y
   201  	}
   202  	if !y.HasNext() {
   203  		return x
   204  	}
   205  	m := &UnionUnary[T]{x: x, y: y, asc: bool(asc), limit: limit}
   206  	m.advanceX()
   207  	m.advanceY()
   208  	return m
   209  }
   210  
   211  func (m *UnionUnary[T]) HasNext() bool {
   212  	return m.err != nil || (m.limit != 0 && m.xHas) || (m.limit != 0 && m.yHas)
   213  }
   214  func (m *UnionUnary[T]) advanceX() {
   215  	if m.err != nil {
   216  		return
   217  	}
   218  	m.xHas = m.x.HasNext()
   219  	if m.xHas {
   220  		m.xNextK, m.err = m.x.Next()
   221  	}
   222  }
   223  func (m *UnionUnary[T]) advanceY() {
   224  	if m.err != nil {
   225  		return
   226  	}
   227  	m.yHas = m.y.HasNext()
   228  	if m.yHas {
   229  		m.yNextK, m.err = m.y.Next()
   230  	}
   231  }
   232  
   233  func (m *UnionUnary[T]) less() bool {
   234  	return (m.asc && m.xNextK < m.yNextK) || (!m.asc && m.xNextK > m.yNextK)
   235  }
   236  
   237  func (m *UnionUnary[T]) Next() (res T, err error) {
   238  	if m.err != nil {
   239  		return res, m.err
   240  	}
   241  	m.limit--
   242  	if m.xHas && m.yHas {
   243  		if m.less() {
   244  			k, err := m.xNextK, m.err
   245  			m.advanceX()
   246  			return k, err
   247  		} else if m.xNextK == m.yNextK {
   248  			k, err := m.xNextK, m.err
   249  			m.advanceX()
   250  			m.advanceY()
   251  			return k, err
   252  		}
   253  		k, err := m.yNextK, m.err
   254  		m.advanceY()
   255  		return k, err
   256  	}
   257  	if m.xHas {
   258  		k, err := m.xNextK, m.err
   259  		m.advanceX()
   260  		return k, err
   261  	}
   262  	k, err := m.yNextK, m.err
   263  	m.advanceY()
   264  	return k, err
   265  }
   266  func (m *UnionUnary[T]) Close() {
   267  	if x, ok := m.x.(Closer); ok {
   268  		x.Close()
   269  	}
   270  	if y, ok := m.y.(Closer); ok {
   271  		y.Close()
   272  	}
   273  }
   274  
   275  // IntersectIter
   276  type IntersectIter[T constraints.Ordered] struct {
   277  	x, y               Unary[T]
   278  	xHasNext, yHasNext bool
   279  	xNextK, yNextK     T
   280  	limit              int
   281  	err                error
   282  }
   283  
   284  func Intersect[T constraints.Ordered](x, y Unary[T], limit int) Unary[T] {
   285  	if x == nil || y == nil || !x.HasNext() || !y.HasNext() {
   286  		return &EmptyUnary[T]{}
   287  	}
   288  	m := &IntersectIter[T]{x: x, y: y, limit: limit}
   289  	m.advance()
   290  	return m
   291  }
   292  func (m *IntersectIter[T]) HasNext() bool {
   293  	return m.err != nil || (m.limit != 0 && m.xHasNext && m.yHasNext)
   294  }
   295  func (m *IntersectIter[T]) advance() {
   296  	m.advanceX()
   297  	m.advanceY()
   298  	for m.xHasNext && m.yHasNext {
   299  		if m.err != nil {
   300  			break
   301  		}
   302  		if m.xNextK < m.yNextK {
   303  			m.advanceX()
   304  			continue
   305  		} else if m.xNextK == m.yNextK {
   306  			return
   307  		} else {
   308  			m.advanceY()
   309  			continue
   310  		}
   311  	}
   312  	m.xHasNext = false
   313  }
   314  
   315  func (m *IntersectIter[T]) advanceX() {
   316  	if m.err != nil {
   317  		return
   318  	}
   319  	m.xHasNext = m.x.HasNext()
   320  	if m.xHasNext {
   321  		m.xNextK, m.err = m.x.Next()
   322  	}
   323  }
   324  func (m *IntersectIter[T]) advanceY() {
   325  	if m.err != nil {
   326  		return
   327  	}
   328  	m.yHasNext = m.y.HasNext()
   329  	if m.yHasNext {
   330  		m.yNextK, m.err = m.y.Next()
   331  	}
   332  }
   333  func (m *IntersectIter[T]) Next() (T, error) {
   334  	if m.err != nil {
   335  		return m.xNextK, m.err
   336  	}
   337  	m.limit--
   338  	k, err := m.xNextK, m.err
   339  	m.advance()
   340  	return k, err
   341  }
   342  func (m *IntersectIter[T]) Close() {
   343  	if x, ok := m.x.(Closer); ok {
   344  		x.Close()
   345  	}
   346  	if y, ok := m.y.(Closer); ok {
   347  		y.Close()
   348  	}
   349  }
   350  
   351  // TransformDualIter - analog `map` (in terms of map-filter-reduce pattern)
   352  type TransformDualIter[K, V any] struct {
   353  	it        Dual[K, V]
   354  	transform func(K, V) (K, V, error)
   355  }
   356  
   357  func TransformDual[K, V any](it Dual[K, V], transform func(K, V) (K, V, error)) *TransformDualIter[K, V] {
   358  	return &TransformDualIter[K, V]{it: it, transform: transform}
   359  }
   360  func (m *TransformDualIter[K, V]) HasNext() bool { return m.it.HasNext() }
   361  func (m *TransformDualIter[K, V]) Next() (K, V, error) {
   362  	k, v, err := m.it.Next()
   363  	if err != nil {
   364  		return k, v, err
   365  	}
   366  	return m.transform(k, v)
   367  }
   368  func (m *TransformDualIter[K, v]) Close() {
   369  	if x, ok := m.it.(Closer); ok {
   370  		x.Close()
   371  	}
   372  }
   373  
   374  type TransformKV2U64Iter[K, V []byte] struct {
   375  	it        KV
   376  	transform func(K, V) (uint64, error)
   377  }
   378  
   379  func TransformKV2U64[K, V []byte](it KV, transform func(K, V) (uint64, error)) *TransformKV2U64Iter[K, V] {
   380  	return &TransformKV2U64Iter[K, V]{it: it, transform: transform}
   381  }
   382  func (m *TransformKV2U64Iter[K, V]) HasNext() bool { return m.it.HasNext() }
   383  func (m *TransformKV2U64Iter[K, V]) Next() (uint64, error) {
   384  	k, v, err := m.it.Next()
   385  	if err != nil {
   386  		return 0, err
   387  	}
   388  	return m.transform(k, v)
   389  }
   390  func (m *TransformKV2U64Iter[K, v]) Close() {
   391  	if x, ok := m.it.(Closer); ok {
   392  		x.Close()
   393  	}
   394  }
   395  
   396  // FilterDualIter - analog `map` (in terms of map-filter-reduce pattern)
   397  // please avoid reading from Disk/DB more elements and then filter them. Better
   398  // push-down filter conditions to lower-level iterator to reduce disk reads amount.
   399  type FilterDualIter[K, V any] struct {
   400  	it      Dual[K, V]
   401  	filter  func(K, V) bool
   402  	hasNext bool
   403  	err     error
   404  	nextK   K
   405  	nextV   V
   406  }
   407  
   408  func FilterKV(it KV, filter func(k, v []byte) bool) *FilterDualIter[[]byte, []byte] {
   409  	return FilterDual[[]byte, []byte](it, filter)
   410  }
   411  func FilterDual[K, V any](it Dual[K, V], filter func(K, V) bool) *FilterDualIter[K, V] {
   412  	i := &FilterDualIter[K, V]{it: it, filter: filter}
   413  	i.advance()
   414  	return i
   415  }
   416  func (m *FilterDualIter[K, V]) advance() {
   417  	if m.err != nil {
   418  		return
   419  	}
   420  	m.hasNext = false
   421  	for m.it.HasNext() {
   422  		// create new variables, to avoid leaking outside of loop
   423  		key, val, err := m.it.Next()
   424  		if err != nil {
   425  			m.err = err
   426  			return
   427  		}
   428  		if m.filter(key, val) {
   429  			m.hasNext = true
   430  			m.nextK, m.nextV = key, val
   431  			break
   432  		}
   433  	}
   434  }
   435  func (m *FilterDualIter[K, V]) HasNext() bool { return m.err != nil || m.hasNext }
   436  func (m *FilterDualIter[K, V]) Next() (k K, v V, err error) {
   437  	k, v, err = m.nextK, m.nextV, m.err
   438  	m.advance()
   439  	return k, v, err
   440  }
   441  func (m *FilterDualIter[K, v]) Close() {
   442  	if x, ok := m.it.(Closer); ok {
   443  		x.Close()
   444  	}
   445  }
   446  
   447  // FilterUnaryIter - analog `map` (in terms of map-filter-reduce pattern)
   448  // please avoid reading from Disk/DB more elements and then filter them. Better
   449  // push-down filter conditions to lower-level iterator to reduce disk reads amount.
   450  type FilterUnaryIter[T any] struct {
   451  	it      Unary[T]
   452  	filter  func(T) bool
   453  	hasNext bool
   454  	err     error
   455  	nextK   T
   456  }
   457  
   458  func FilterU64(it U64, filter func(k uint64) bool) *FilterUnaryIter[uint64] {
   459  	return FilterUnary[uint64](it, filter)
   460  }
   461  func FilterUnary[T any](it Unary[T], filter func(T) bool) *FilterUnaryIter[T] {
   462  	i := &FilterUnaryIter[T]{it: it, filter: filter}
   463  	i.advance()
   464  	return i
   465  }
   466  func (m *FilterUnaryIter[T]) advance() {
   467  	if m.err != nil {
   468  		return
   469  	}
   470  	m.hasNext = false
   471  	for m.it.HasNext() {
   472  		// create new variables, to avoid leaking outside of loop
   473  		key, err := m.it.Next()
   474  		if err != nil {
   475  			m.err = err
   476  			return
   477  		}
   478  		if m.filter(key) {
   479  			m.hasNext, m.nextK = true, key
   480  			break
   481  		}
   482  	}
   483  }
   484  func (m *FilterUnaryIter[T]) HasNext() bool { return m.err != nil || m.hasNext }
   485  func (m *FilterUnaryIter[T]) Next() (k T, err error) {
   486  	k, err = m.nextK, m.err
   487  	m.advance()
   488  	return k, err
   489  }
   490  func (m *FilterUnaryIter[T]) Close() {
   491  	if x, ok := m.it.(Closer); ok {
   492  		x.Close()
   493  	}
   494  }
   495  
   496  // PaginatedIter - for remote-list pagination
   497  //
   498  //	Rationale: If an API does not support pagination from the start, supporting it later is troublesome because adding pagination breaks the API's behavior. Clients that are unaware that the API now uses pagination could incorrectly assume that they received a complete result, when in fact they only received the first page.
   499  //
   500  // To support pagination (returning list results in pages) in a List method, the API shall:
   501  //   - The client uses this field to request a specific page of the list results.
   502  //   - define an int32 field page_size in the List method's request message. Clients use this field to specify the maximum number of results to be returned by the server. The server may further constrain the maximum number of results returned in a single page. If the page_size is 0, the server will decide the number of results to be returned.
   503  //   - define a string field next_page_token in the List method's response message. This field represents the pagination token to retrieve the next page of results. If the value is "", it means no further results for the request.
   504  //
   505  // see: https://cloud.google.com/apis/design/design_patterns
   506  type Paginated[T any] struct {
   507  	arr           []T
   508  	i             int
   509  	err           error
   510  	nextPage      NextPageUnary[T]
   511  	nextPageToken string
   512  	initialized   bool
   513  }
   514  
   515  func Paginate[T any](f NextPageUnary[T]) *Paginated[T] { return &Paginated[T]{nextPage: f} }
   516  func (it *Paginated[T]) HasNext() bool {
   517  	if it.err != nil || it.i < len(it.arr) {
   518  		return true
   519  	}
   520  	if it.initialized && it.nextPageToken == "" {
   521  		return false
   522  	}
   523  	it.initialized = true
   524  	it.i = 0
   525  	it.arr, it.nextPageToken, it.err = it.nextPage(it.nextPageToken)
   526  	return it.err != nil || it.i < len(it.arr)
   527  }
   528  func (it *Paginated[T]) Close() {}
   529  func (it *Paginated[T]) Next() (v T, err error) {
   530  	if it.err != nil {
   531  		return v, it.err
   532  	}
   533  	v = it.arr[it.i]
   534  	it.i++
   535  	return v, nil
   536  }
   537  
   538  type PaginatedDual[K, V any] struct {
   539  	keys          []K
   540  	values        []V
   541  	i             int
   542  	err           error
   543  	nextPage      NextPageDual[K, V]
   544  	nextPageToken string
   545  	initialized   bool
   546  }
   547  
   548  func PaginateDual[K, V any](f NextPageDual[K, V]) *PaginatedDual[K, V] {
   549  	return &PaginatedDual[K, V]{nextPage: f}
   550  }
   551  func (it *PaginatedDual[K, V]) HasNext() bool {
   552  	if it.err != nil || it.i < len(it.keys) {
   553  		return true
   554  	}
   555  	if it.initialized && it.nextPageToken == "" {
   556  		return false
   557  	}
   558  	it.initialized = true
   559  	it.i = 0
   560  	it.keys, it.values, it.nextPageToken, it.err = it.nextPage(it.nextPageToken)
   561  	return it.err != nil || it.i < len(it.keys)
   562  }
   563  func (it *PaginatedDual[K, V]) Close() {}
   564  func (it *PaginatedDual[K, V]) Next() (k K, v V, err error) {
   565  	if it.err != nil {
   566  		return k, v, it.err
   567  	}
   568  	k, v = it.keys[it.i], it.values[it.i]
   569  	it.i++
   570  	return k, v, nil
   571  }