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 }