github.com/anacrolix/torrent@v1.61.0/internal/indexed/funcs.go (about)

     1  package indexed
     2  
     3  import (
     4  	"fmt"
     5  	"iter"
     6  
     7  	g "github.com/anacrolix/generics"
     8  	"github.com/anacrolix/torrent/internal/amortize"
     9  	"github.com/google/go-cmp/cmp"
    10  )
    11  
    12  // Iters from a point, assuming that where can only be true consecutively from that point and
    13  // nowhere else.
    14  func IterClusteredWhere[R any](t relation[R], gte R, where func(r R) bool) Iter[R] {
    15  	return func(yield func(R) bool) {
    16  		first := true
    17  		// TODO: This function is allocating..
    18  		checkFirst := func(r g.Option[R]) {
    19  			if !first {
    20  				return
    21  			}
    22  			checkWhereGotFirst(t, r, where)
    23  			first = false
    24  		}
    25  		for r := range t.IterFrom(gte) {
    26  			if !where(r) {
    27  				break
    28  			}
    29  			checkFirst(g.Some(r))
    30  			if !yield(r) {
    31  				// Mustn't do first check after yielding, as the table could have changed.
    32  				return
    33  			}
    34  		}
    35  		checkFirst(g.None[R]())
    36  	}
    37  }
    38  
    39  func checkWhereGotFirst[R any](me relation[R], first g.Option[R], where func(r R) bool) {
    40  	if !amortize.Try() {
    41  		return
    42  	}
    43  	var slowRet g.Option[R]
    44  	for r := range me.Iter {
    45  		if where(r) {
    46  			slowRet.Set(r)
    47  			break
    48  		}
    49  	}
    50  	if first.Ok != slowRet.Ok || first.Ok && me.GetCmp()(first.Value, slowRet.Value) != 0 {
    51  		fmt.Printf("%#v\n", first.Value)
    52  		fmt.Printf("%#v\n", slowRet.Value)
    53  		fmt.Printf("diff: %s\n", cmp.Diff(first.Value, slowRet.Value))
    54  		panic("iterating where got different first value than caller")
    55  	}
    56  }
    57  
    58  func IterRange[R any](me relation[R], gte, lt R) iter.Seq[R] {
    59  	return func(yield func(R) bool) {
    60  		for r := range me.IterFrom(gte) {
    61  			if me.GetCmp()(r, lt) >= 0 {
    62  				break
    63  			}
    64  			if !yield(r) {
    65  				break
    66  			}
    67  		}
    68  	}
    69  }
    70  
    71  func FirstInRange[R any](me relation[R], gte, lt R) (ret g.Option[R]) {
    72  	ret = me.GetGte(gte)
    73  	if ret.Ok && me.GetCmp()(ret.Value, lt) >= 0 {
    74  		ret.SetNone()
    75  	}
    76  	return
    77  }