pkg/math/segments.go (36 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
package math
import "fmt"
// Segments represents a range of segments.
type Segments struct {
offset int64
step int
size int64
}
// Segment represents a single segment.
type Segment struct {
Index int64
Offset int64
Count int
}
// NewSegments creates a new Segments object.
func NewSegments(offset int64, step int, count int64, size int64) (Segments, error) {
if (step & (step - 1)) > 0 {
return Segments{}, fmt.Errorf("step must be power of 2, got %d", step)
}
return Segments{offset, step, Min64(offset+count, size)}, nil
}
// AlignDown will align down the x by align. For example:
// AlignDown(1, 2) = 0
// AlignDown(29, 14) = 28
func AlignDown(x int64, align int64) int64 {
return x / align * align
}
// All provides a channel of all segments.
func (r Segments) All() chan Segment {
ch := make(chan Segment)
go func() {
for i := AlignDown(r.offset, int64(r.step)); i < r.size; i += int64(r.step) {
absOffset := Max64(i, r.offset)
seg := Segment{Index: i, Offset: absOffset - i}
seg.Count = int(Min64(i+int64(r.step), r.size) - absOffset)
if seg.Count > 0 {
ch <- seg
}
}
close(ch)
}()
return ch
}