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