github.com/m4gshm/gollections@v0.0.13-0.20240331203319-a34a86e58a24/collection/mutable/slice_iter.go (about) 1 package mutable 2 3 import ( 4 "github.com/m4gshm/gollections/c" 5 "github.com/m4gshm/gollections/loop" 6 "github.com/m4gshm/gollections/slice" 7 ) 8 9 // NewHead instantiates Iter starting at the first element of a slice. 10 func NewHead[TS ~[]T, T any](elements *TS, del func(int) bool) *SliceIter[T] { 11 if elements == nil { 12 return nil 13 } 14 return &SliceIter[T]{elements: slice.UpcastRef(elements), current: slice.IterNoStarted, del: del} 15 } 16 17 // NewTail instantiates Iter starting at the last element of a slice. 18 func NewTail[TS ~[]T, T any](elements *TS, del func(int) bool) *SliceIter[T] { 19 if elements == nil { 20 return nil 21 } 22 return &SliceIter[T]{elements: slice.UpcastRef(elements), current: len(*elements), del: del} 23 } 24 25 // SliceIter is the Iterator implementation for mutable containers. 26 type SliceIter[T any] struct { 27 elements *[]T 28 current, step int 29 del func(index int) bool 30 } 31 32 var ( 33 _ c.Iterator[any] = (*SliceIter[any])(nil) 34 _ c.PrevIterator[any] = (*SliceIter[any])(nil) 35 _ c.DelIterator[any] = (*SliceIter[any])(nil) 36 ) 37 38 // All is used to iterate through the collection using `for ... range`. Supported since go 1.22 with GOEXPERIMENT=rangefunc enabled. 39 func (i *SliceIter[T]) All(consumer func(element T) bool) { 40 loop.All(i.Next, consumer) 41 } 42 43 // For takes elements retrieved by the iterator. Can be interrupt by returning Break 44 func (i *SliceIter[T]) For(consumer func(element T) error) error { 45 return loop.For(i.Next, consumer) 46 } 47 48 // ForEach FlatIter all elements retrieved by the iterator 49 func (i *SliceIter[T]) ForEach(consumer func(element T)) { 50 loop.ForEach(i.Next, consumer) 51 } 52 53 // HasNext checks the next element existing 54 func (i *SliceIter[T]) HasNext() bool { 55 if i == nil || i.elements == nil { 56 return false 57 } 58 return slice.HasNext(*i.elements, i.current) 59 } 60 61 // HasPrev checks the previous element existing 62 func (i *SliceIter[T]) HasPrev() bool { 63 if i == nil || i.elements == nil { 64 return false 65 } 66 return slice.HasPrev(*i.elements, i.current) 67 } 68 69 // GetNext returns the next element 70 func (i *SliceIter[T]) GetNext() (t T) { 71 if i != nil { 72 t, _ = i.Next() 73 } 74 return 75 } 76 77 // GetPrev returns the previous element 78 func (i *SliceIter[T]) GetPrev() (t T) { 79 if i != nil { 80 t, _ = i.Prev() 81 } 82 return 83 } 84 85 // Next returns the next element. 86 // The ok result indicates whether the element was returned by the iterator. 87 // If ok == false, then the iteration must be completed. 88 func (i *SliceIter[T]) Next() (T, bool) { 89 if i.HasNext() { 90 i.current++ 91 i.step = 1 92 return slice.Get(*i.elements, i.current), true 93 } 94 var no T 95 return no, false 96 } 97 98 // Prev returns the previous element. 99 // The ok result indicates whether the element was returned by the iterator. 100 // If ok == false, then the iteration must be completed. 101 func (i *SliceIter[T]) Prev() (T, bool) { 102 if i.HasPrev() { 103 i.current-- 104 i.step = 0 105 return slice.Get(*i.elements, i.current), true 106 } 107 var no T 108 return no, false 109 } 110 111 // Get returns the current element. 112 // The ok result indicates whether the element was returned by the iterator. 113 // If ok == false, then the iteration must be completed. 114 func (i *SliceIter[T]) Get() (t T, ok bool) { 115 if i == nil || i.elements == nil { 116 return t, ok 117 } 118 current := i.current 119 elements := *i.elements 120 if slice.IsValidIndex(len(elements), current) { 121 return elements[current], true 122 } 123 return t, ok 124 } 125 126 // Size returns the iterator capacity 127 func (i *SliceIter[T]) Size() int { 128 if i == nil || i.elements == nil { 129 return 0 130 } 131 return len(*i.elements) 132 } 133 134 // Delete deletes the current element 135 func (i *SliceIter[T]) Delete() { 136 if i == nil { 137 return 138 } else if deleted := i.del(i.current); deleted { 139 i.current -= i.step 140 } 141 } 142 143 // DeleteNext deletes the next element if it exists 144 func (i *SliceIter[T]) DeleteNext() bool { 145 if i == nil { 146 return false 147 } 148 return i.del(i.current + 1) 149 } 150 151 // DeletePrev deletes the previos element if it exists 152 func (i *SliceIter[T]) DeletePrev() bool { 153 if i == nil { 154 return false 155 } else if deleted := i.del(i.current - 1); deleted { 156 i.current-- 157 return true 158 } 159 return false 160 }