github.com/haraldrudell/parl@v0.4.176/iters/simple-func.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  // Function traverses a function generating values
    13  type SimpleFunc[T any] struct {
    14  	// IteratorFunction is a function that can be used with function iterator
    15  	//   - if isCancel true, it means this is the last invocation of IteratorFunction and
    16  	//     IteratorFunction should release any resources.
    17  	//     Any returned value is not used
    18  	//   - IteratorFunction signals end of values by returning parl.ErrEndCallbacks.
    19  	//     if hasValue true, the accompanying value is used
    20  	//   - if IteratorFunction returns error, it will not be invoked again.
    21  	//     Any returned value is not used
    22  	//   - IteratorFunction must be thread-safe
    23  	//   - IteratorFunction is invoked by at most one thread at a time
    24  	iteratorFunction SimpleIteratorFunc[T]
    25  	// BaseIterator implements the DelegateAction[T] function required by
    26  	// Delegator[T] and Cancel
    27  	//	- provides its delegateAction method to Delegator
    28  	*BaseIterator[T]
    29  }
    30  
    31  // NewFunctionIterator returns an [Iterator] iterating over a function
    32  //   - thread-safe
    33  func NewSimpleFunctionIterator[T any](
    34  	iteratorFunction SimpleIteratorFunc[T],
    35  	asyncCancel ...func(),
    36  ) (iterator Iterator[T]) {
    37  	if iteratorFunction == nil {
    38  		panic(cyclebreaker.NilError("iteratorFunction"))
    39  	}
    40  	f := &SimpleFunc[T]{iteratorFunction: iteratorFunction}
    41  	f.BaseIterator = NewBaseIterator[T](f.iteratorAction, asyncCancel...)
    42  	return f
    43  }
    44  
    45  // Init implements the right-hand side of a short variable declaration in
    46  // the init statement for a Go “for” clause
    47  //
    48  // Usage:
    49  //
    50  //		for i, iterator := NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); {
    51  //	   // i is pointer to slice element
    52  func (i *SimpleFunc[T]) Init() (iterationVariable T, iterator Iterator[T]) {
    53  	iterator = i
    54  	return
    55  }
    56  
    57  // baseIteratorRequest invokes fn recovering a possible panic
    58  //   - if cancelState == notCanceled, a new value is requested.
    59  //     Otherwise, iteration cancel is requested
    60  //   - if err is nil, value is valid and isPanic false.
    61  //     Otherwise, err is non-nil and isPanic may be set.
    62  //     value is zero-value
    63  //   - thread-safe but invocations must be serialized
    64  func (i *SimpleFunc[T]) iteratorAction(isCancel bool) (value T, err error) {
    65  	if isCancel {
    66  		return
    67  	}
    68  	// func() (value T, hasValue bool)
    69  	var hasValue bool
    70  	if value, hasValue = i.iteratorFunction(); !hasValue {
    71  		err = cyclebreaker.ErrEndCallbacks
    72  	}
    73  
    74  	return
    75  }