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 }