github.com/anacrolix/torrent@v1.61.0/segments/segments.go (about)

     1  package segments
     2  
     3  import (
     4  	"iter"
     5  )
     6  
     7  type Int = int64
     8  
     9  type Length = Int
    10  
    11  type Extent struct {
    12  	Start, Length Int
    13  }
    14  
    15  func (e Extent) End() Int {
    16  	return e.Start + e.Length
    17  }
    18  
    19  type (
    20  	Callback              = func(segmentIndex int, segmentBounds Extent) bool
    21  	LengthIter            = iter.Seq[Length]
    22  	ConsecutiveExtentIter = iter.Seq[Extent]
    23  )
    24  
    25  // TODO: Does this handle discontiguous extents?
    26  func scanConsecutive(haystack ConsecutiveExtentIter, needle Extent) iter.Seq[Extent] {
    27  	return func(yield func(Extent) bool) {
    28  		// Extents have been found in the haystack, and we're waiting for the needle to end. This is
    29  		// kind of for backwards compatibility for some tests that expect to have zero-length extents.
    30  		startedNeedle := false
    31  		next, stop := iter.Pull(haystack)
    32  		defer stop()
    33  		for needle.Length != 0 {
    34  			l, ok := next()
    35  			if !ok {
    36  				return
    37  			}
    38  
    39  			e1 := Extent{
    40  				Start: max(needle.Start-l.Start, 0),
    41  			}
    42  			e1.Length = max(min(l.Length, needle.End()-l.Start)-e1.Start, 0)
    43  			needle.Start = max(0, needle.Start-l.End())
    44  			needle.Length -= e1.Length + l.Start
    45  			if e1.Length > 0 || (startedNeedle && needle.Length != 0) {
    46  				if !yield(e1) {
    47  					return
    48  				}
    49  				startedNeedle = true
    50  			}
    51  		}
    52  	}
    53  }
    54  
    55  type Locater func(Extent, Callback) bool