github.com/m4gshm/gollections@v0.0.10/break/loop/convert.go (about)

     1  package loop
     2  
     3  import (
     4  	"github.com/m4gshm/gollections/break/c"
     5  )
     6  
     7  // ConvFiltIter iterator implementation that retrieves an element by the 'next' function, converts by the 'converter' and addition checks by the 'filter'.
     8  // If the filter returns true then the converted element is returned as next.
     9  type ConvFiltIter[From, To any] struct {
    10  	next       func() (From, bool, error)
    11  	converter  func(From) (To, error)
    12  	filterFrom func(From) (bool, error)
    13  	filterTo   func(To) (bool, error)
    14  }
    15  
    16  var (
    17  	_ c.Iterator[any] = (*ConvFiltIter[any, any])(nil)
    18  	_ c.Iterator[any] = ConvFiltIter[any, any]{}
    19  )
    20  
    21  var _ c.IterFor[any, ConvFiltIter[any, any]] = ConvFiltIter[any, any]{}
    22  
    23  // For takes elements retrieved by the iterator. Can be interrupt by returning ErrBreak
    24  func (c ConvFiltIter[From, To]) For(walker func(element To) error) error {
    25  	return For(c.Next, walker)
    26  }
    27  
    28  // Next returns the next element.
    29  // The ok result indicates whether the element was returned by the iterator.
    30  // If ok == false, then the iteration must be completed.
    31  func (c ConvFiltIter[From, To]) Next() (t To, ok bool, err error) {
    32  	next, filterFrom, filterTo := c.next, c.filterFrom, c.filterTo
    33  	if next == nil || filterFrom == nil || filterTo == nil {
    34  		return t, false, nil
    35  	}
    36  	for {
    37  		if f, ok, err := nextFiltered(next, filterFrom); err != nil || !ok {
    38  			return t, false, err
    39  		} else if cf, err := c.converter(f); err != nil {
    40  			return t, false, err
    41  		} else if ok, err := filterTo(cf); err != nil || !ok {
    42  			return t, false, err
    43  		} else {
    44  			return cf, true, nil
    45  		}
    46  	}
    47  }
    48  
    49  // Start is used with for loop construct like 'for i, val, ok, err := i.Start(); ok || err != nil ; val, ok, err = i.Next() { if err != nil { return err }}'
    50  func (c ConvFiltIter[From, To]) Start() (ConvFiltIter[From, To], To, bool, error) {
    51  	return startIt[To](c)
    52  }
    53  
    54  // ConvertIter iterator implementation that retrieves an element by the 'next' function and converts by the 'converter'
    55  type ConvertIter[From, To any] struct {
    56  	next      func() (From, bool, error)
    57  	converter func(From) (To, error)
    58  }
    59  
    60  var (
    61  	_ c.Iterator[any] = (*ConvertIter[any, any])(nil)
    62  	_ c.Iterator[any] = ConvertIter[any, any]{}
    63  )
    64  
    65  var _ c.IterFor[any, ConvertIter[any, any]] = ConvertIter[any, any]{}
    66  
    67  // For takes elements retrieved by the iterator. Can be interrupt by returning ErrBreak
    68  func (c ConvertIter[From, To]) For(walker func(element To) error) error {
    69  	return For(c.Next, walker)
    70  }
    71  
    72  // Next returns the next element.
    73  // The ok result indicates whether the element was returned by the iterator.
    74  // If ok == false, then the iteration must be completed.
    75  func (c ConvertIter[From, To]) Next() (t To, ok bool, err error) {
    76  	if next := c.next; next == nil {
    77  		return t, false, nil
    78  	} else if v, ok, err := next(); err != nil || !ok {
    79  		return t, false, err
    80  	} else {
    81  		vc, err := c.converter(v)
    82  		return vc, err == nil, err
    83  	}
    84  }
    85  
    86  // Start is used with for loop construct like 'for i, val, ok, err := i.Start(); ok || err != nil ; val, ok, err = i.Next() { if err != nil { return err }}'
    87  func (c ConvertIter[From, To]) Start() (ConvertIter[From, To], To, bool, error) {
    88  	return startIt[To](c)
    89  }
    90  
    91  // ConvertCheckIter converts and filters elements at the same time
    92  type ConvertCheckIter[From, To any] struct {
    93  	next      func() (From, bool, error)
    94  	converter func(From) (To, bool, error)
    95  }
    96  
    97  var (
    98  	_ c.Iterator[any] = (*ConvertCheckIter[any, any])(nil)
    99  	_ c.Iterator[any] = ConvertCheckIter[any, any]{}
   100  )
   101  
   102  var _ c.IterFor[any, ConvertCheckIter[any, any]] = ConvertCheckIter[any, any]{}
   103  
   104  // For takes elements retrieved by the iterator. Can be interrupt by returning ErrBreak
   105  func (c ConvertCheckIter[From, To]) For(walker func(element To) error) error {
   106  	return For(c.Next, walker)
   107  }
   108  
   109  // Next returns the next element.
   110  // The ok result indicates whether the element was returned by the iterator.
   111  // If ok == false, then the iteration must be completed.
   112  func (c ConvertCheckIter[From, To]) Next() (t To, ok bool, err error) {
   113  	next, converter := c.next, c.converter
   114  	if next == nil || converter == nil {
   115  		return t, false, nil
   116  	}
   117  	for {
   118  		if e, ok, err := next(); err != nil || !ok {
   119  			return t, false, err
   120  		} else if t, ok, err := converter(e); err != nil || ok {
   121  			return t, ok, err
   122  		}
   123  	}
   124  }
   125  
   126  // Start is used with for loop construct like 'for i, val, ok, err := i.Start(); ok || err != nil ; val, ok, err = i.Next() { if err != nil { return err }}'
   127  func (c ConvertCheckIter[From, To]) Start() (ConvertCheckIter[From, To], To, bool, error) {
   128  	return startIt[To](c)
   129  }