github.com/ethereum/go-ethereum@v1.16.1/common/range.go (about)

     1  // Copyright 2025 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package common
    18  
    19  import (
    20  	"iter"
    21  )
    22  
    23  // Range represents a range of integers.
    24  type Range[T uint32 | uint64] struct {
    25  	first, afterLast T
    26  }
    27  
    28  // NewRange creates a new range based of first element and number of elements.
    29  func NewRange[T uint32 | uint64](first, count T) Range[T] {
    30  	return Range[T]{first, first + count}
    31  }
    32  
    33  // First returns the first element of the range.
    34  func (r Range[T]) First() T {
    35  	return r.first
    36  }
    37  
    38  // Last returns the last element of the range. This panics for empty ranges.
    39  func (r Range[T]) Last() T {
    40  	if r.first == r.afterLast {
    41  		panic("last item of zero length range is not allowed")
    42  	}
    43  	return r.afterLast - 1
    44  }
    45  
    46  // AfterLast returns the first element after the range. This allows obtaining
    47  // information about the end part of zero length ranges.
    48  func (r Range[T]) AfterLast() T {
    49  	return r.afterLast
    50  }
    51  
    52  // Count returns the number of elements in the range.
    53  func (r Range[T]) Count() T {
    54  	return r.afterLast - r.first
    55  }
    56  
    57  // IsEmpty returns true if the range is empty.
    58  func (r Range[T]) IsEmpty() bool {
    59  	return r.first == r.afterLast
    60  }
    61  
    62  // Includes returns true if the given element is inside the range.
    63  func (r Range[T]) Includes(v T) bool {
    64  	return v >= r.first && v < r.afterLast
    65  }
    66  
    67  // SetFirst updates the first element of the list.
    68  func (r *Range[T]) SetFirst(v T) {
    69  	r.first = v
    70  	if r.afterLast < r.first {
    71  		r.afterLast = r.first
    72  	}
    73  }
    74  
    75  // SetAfterLast updates the end of the range by specifying the first element
    76  // after the range. This allows setting zero length ranges.
    77  func (r *Range[T]) SetAfterLast(v T) {
    78  	r.afterLast = v
    79  	if r.afterLast < r.first {
    80  		r.first = r.afterLast
    81  	}
    82  }
    83  
    84  // SetLast updates last element of the range.
    85  func (r *Range[T]) SetLast(v T) {
    86  	r.SetAfterLast(v + 1)
    87  }
    88  
    89  // Intersection returns the intersection of two ranges.
    90  func (r Range[T]) Intersection(q Range[T]) Range[T] {
    91  	i := Range[T]{first: max(r.first, q.first), afterLast: min(r.afterLast, q.afterLast)}
    92  	if i.first > i.afterLast {
    93  		return Range[T]{}
    94  	}
    95  	return i
    96  }
    97  
    98  // Union returns the union of two ranges. Panics for gapped ranges.
    99  func (r Range[T]) Union(q Range[T]) Range[T] {
   100  	if max(r.first, q.first) > min(r.afterLast, q.afterLast) {
   101  		panic("cannot create union; gap between ranges")
   102  	}
   103  	return Range[T]{first: min(r.first, q.first), afterLast: max(r.afterLast, q.afterLast)}
   104  }
   105  
   106  // Iter iterates all integers in the range.
   107  func (r Range[T]) Iter() iter.Seq[T] {
   108  	return func(yield func(T) bool) {
   109  		for i := r.first; i < r.afterLast; i++ {
   110  			if !yield(i) {
   111  				break
   112  			}
   113  		}
   114  	}
   115  }