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 }