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  }