github.com/haraldrudell/parl@v0.4.176/iters/simple.go (about)

     1  /*
     2  © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package iters
     7  
     8  import (
     9  	"github.com/haraldrudell/parl/internal/cyclebreaker"
    10  )
    11  
    12  // Converter traverses another iterator and returns converted values
    13  type Simple[K any, V any] struct {
    14  	// keyIterator provides the key values converterFunction uses to
    15  	// return values
    16  	keyIterator     Iterator[K]
    17  	simpleConverter func(key K) (value V)
    18  	// BaseIterator implements Cancel and the DelegateAction[T] function required by
    19  	// Delegator[T]
    20  	//	- receives invokeConverterFunction function
    21  	//	- provides delegateAction function
    22  	BaseIterator[V]
    23  }
    24  
    25  // NewConverterIterator returns a converting iterator.
    26  //   - converterFunction receives cancel and can return error
    27  //   - ConverterIterator is thread-safe and re-entrant.
    28  //   - stores self-referencing pointers
    29  func NewSimpleConverterIterator[K any, V any](
    30  	keyIterator Iterator[K],
    31  	simpleConverter SimpleConverter[K, V],
    32  	asyncCancel ...func(),
    33  ) (iterator Iterator[V]) {
    34  	if simpleConverter == nil {
    35  		panic(cyclebreaker.NilError("simpleConverter"))
    36  	} else if keyIterator == nil {
    37  		panic(cyclebreaker.NilError("keyIterator"))
    38  	}
    39  
    40  	c := Simple[K, V]{
    41  		keyIterator:     keyIterator,
    42  		simpleConverter: simpleConverter,
    43  	}
    44  	c.BaseIterator = *NewBaseIterator(c.iteratorAction, asyncCancel...)
    45  
    46  	return &c
    47  }
    48  
    49  // Init implements the right-hand side of a short variable declaration in
    50  // the init statement for a Go “for” clause
    51  //
    52  // Usage:
    53  //
    54  //		for i, iterator := NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); {
    55  //	   // i is pointer to slice element
    56  func (i *Simple[K, T]) Init() (iterationVariable T, iterator Iterator[T]) {
    57  	iterator = i
    58  	return
    59  }
    60  
    61  // iteratorAction invokes converterFunction recovering a possible panic
    62  //   - if cancelState == notCanceled, a new value is requested.
    63  //     Otherwise, iteration cancel is requested
    64  //   - if err is nil, value is valid and isPanic false.
    65  //     Otherwise, err is non-nil and isPanic may be set.
    66  //     value is zero-value
    67  func (i *Simple[K, T]) iteratorAction(isCancel bool) (value T, err error) {
    68  	if isCancel {
    69  		return
    70  	}
    71  	// get next key from keyIterator
    72  	var key K
    73  	var hasKey bool
    74  	if key, hasKey = i.keyIterator.Next(); !hasKey {
    75  		err = cyclebreaker.ErrEndCallbacks
    76  		return
    77  	}
    78  	value = i.simpleConverter(key)
    79  
    80  	return
    81  }