status-go/vendor/github.com/anacrolix/missinggo/httptoo/bytes_content_range.go

107 lines
1.9 KiB
Go

package httptoo
import (
"fmt"
"math"
"regexp"
"strconv"
"strings"
)
type BytesContentRange struct {
First, Last, Length int64
}
type BytesRange struct {
First, Last int64
}
func (me BytesRange) String() string {
if me.Last == math.MaxInt64 {
return fmt.Sprintf("bytes=%d-", me.First)
}
return fmt.Sprintf("bytes=%d-%d", me.First, me.Last)
}
var (
httpBytesRangeRegexp = regexp.MustCompile(`bytes[ =](\d+)-(\d*)`)
)
func ParseBytesRange(s string) (ret BytesRange, ok bool) {
ss := httpBytesRangeRegexp.FindStringSubmatch(s)
if ss == nil {
return
}
var err error
ret.First, err = strconv.ParseInt(ss[1], 10, 64)
if err != nil {
return
}
if ss[2] == "" {
ret.Last = math.MaxInt64
} else {
ret.Last, err = strconv.ParseInt(ss[2], 10, 64)
if err != nil {
return
}
}
ok = true
return
}
func parseUnitRanges(s string) (unit, ranges string) {
s = strings.TrimSpace(s)
i := strings.IndexAny(s, " =")
if i == -1 {
return
}
unit = s[:i]
ranges = s[i+1:]
return
}
func parseFirstLast(s string) (first, last int64) {
ss := strings.SplitN(s, "-", 2)
first, err := strconv.ParseInt(ss[0], 10, 64)
if err != nil {
panic(err)
}
last, err = strconv.ParseInt(ss[1], 10, 64)
if err != nil {
panic(err)
}
return
}
func parseContentRange(s string) (ret BytesContentRange) {
ss := strings.SplitN(s, "/", 2)
firstLast := strings.TrimSpace(ss[0])
if firstLast == "*" {
ret.First = -1
ret.Last = -1
} else {
ret.First, ret.Last = parseFirstLast(firstLast)
}
il := strings.TrimSpace(ss[1])
if il == "*" {
ret.Length = -1
} else {
var err error
ret.Length, err = strconv.ParseInt(il, 10, 64)
if err != nil {
panic(err)
}
}
return
}
func ParseBytesContentRange(s string) (ret BytesContentRange, ok bool) {
unit, ranges := parseUnitRanges(s)
if unit != "bytes" {
return
}
ret = parseContentRange(ranges)
ok = true
return
}