"vscode:/vscode.git/clone" did not exist on "d8b217c5e891ebe4174354e25d67fa17b9864b9e"
chunks.go 2.02 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package chunks

import (
	"fmt"
	"iter"
	"strconv"
	"strings"
)

type Chunk struct {
	Start, End int64
}

func New(start, end int64) Chunk {
	return Chunk{start, end}
}

// ParseRange parses a string in the form "unit=range" where unit is a string
// and range is a string in the form "start-end". It returns the unit and the
// range as a Chunk.
func ParseRange(s string) (unit string, _ Chunk, _ error) {
	unit, r, _ := strings.Cut(s, "=")
	if r == "" {
		return unit, Chunk{}, nil
	}
	c, err := Parse(r)
	if err != nil {
		return "", Chunk{}, err
	}
	return unit, c, err
}

// Parse parses a string in the form "start-end" and returns the Chunk.
34
35
36
37
38
39
func Parse[S ~string | ~[]byte](s S) (Chunk, error) {
	startPart, endPart, found := strings.Cut(string(s), "-")
	if !found {
		return Chunk{}, fmt.Errorf("chunks: invalid range %q: missing '-'", s)
	}
	start, err := strconv.ParseInt(startPart, 10, 64)
40
	if err != nil {
41
		return Chunk{}, fmt.Errorf("chunks: invalid start to %q: %v", s, err)
42
	}
43
	end, err := strconv.ParseInt(endPart, 10, 64)
44
	if err != nil {
45
		return Chunk{}, fmt.Errorf("chunks: invalid end to %q: %v", s, err)
46
47
	}
	if start > end {
48
		return Chunk{}, fmt.Errorf("chunks: invalid range %q: start > end", s)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	}
	return Chunk{start, end}, nil
}

// Of returns a sequence of contiguous Chunks of size chunkSize that cover
// the range [0, size), in order.
func Of(size, chunkSize int64) iter.Seq[Chunk] {
	return func(yield func(Chunk) bool) {
		for start := int64(0); start < size; start += chunkSize {
			end := min(start+chunkSize-1, size-1)
			if !yield(Chunk{start, end}) {
				break
			}
		}
	}
}

// Count returns the number of Chunks of size chunkSize needed to cover the
// range [0, size).
func Count(size, chunkSize int64) int64 {
	return (size + chunkSize - 1) / chunkSize
}

// Size returns end minus start plus one.
func (c Chunk) Size() int64 {
	return c.End - c.Start + 1
}

// String returns the string representation of the Chunk in the form
// "{start}-{end}".
func (c Chunk) String() string {
	return fmt.Sprintf("%d-%d", c.Start, c.End)
}