chunks.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package chunks
  2. import (
  3. "fmt"
  4. "iter"
  5. "strconv"
  6. "strings"
  7. )
  8. type Chunk struct {
  9. Start, End int64
  10. }
  11. func New(start, end int64) Chunk {
  12. return Chunk{start, end}
  13. }
  14. // ParseRange parses a string in the form "unit=range" where unit is a string
  15. // and range is a string in the form "start-end". It returns the unit and the
  16. // range as a Chunk.
  17. func ParseRange(s string) (unit string, _ Chunk, _ error) {
  18. unit, r, _ := strings.Cut(s, "=")
  19. if r == "" {
  20. return unit, Chunk{}, nil
  21. }
  22. c, err := Parse(r)
  23. if err != nil {
  24. return "", Chunk{}, err
  25. }
  26. return unit, c, err
  27. }
  28. // Parse parses a string in the form "start-end" and returns the Chunk.
  29. func Parse(s string) (Chunk, error) {
  30. startStr, endStr, _ := strings.Cut(s, "-")
  31. start, err := strconv.ParseInt(startStr, 10, 64)
  32. if err != nil {
  33. return Chunk{}, fmt.Errorf("invalid start: %v", err)
  34. }
  35. end, err := strconv.ParseInt(endStr, 10, 64)
  36. if err != nil {
  37. return Chunk{}, fmt.Errorf("invalid end: %v", err)
  38. }
  39. if start > end {
  40. return Chunk{}, fmt.Errorf("invalid range %d-%d: start > end", start, end)
  41. }
  42. return Chunk{start, end}, nil
  43. }
  44. // Of returns a sequence of contiguous Chunks of size chunkSize that cover
  45. // the range [0, size), in order.
  46. func Of(size, chunkSize int64) iter.Seq[Chunk] {
  47. return func(yield func(Chunk) bool) {
  48. for start := int64(0); start < size; start += chunkSize {
  49. end := min(start+chunkSize-1, size-1)
  50. if !yield(Chunk{start, end}) {
  51. break
  52. }
  53. }
  54. }
  55. }
  56. // Count returns the number of Chunks of size chunkSize needed to cover the
  57. // range [0, size).
  58. func Count(size, chunkSize int64) int64 {
  59. return (size + chunkSize - 1) / chunkSize
  60. }
  61. // Size returns end minus start plus one.
  62. func (c Chunk) Size() int64 {
  63. return c.End - c.Start + 1
  64. }
  65. // String returns the string representation of the Chunk in the form
  66. // "{start}-{end}".
  67. func (c Chunk) String() string {
  68. return fmt.Sprintf("%d-%d", c.Start, c.End)
  69. }