100 lines
1.9 KiB
Go
100 lines
1.9 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
type IntRanges[T constraints.Integer] []Range[T]
|
|
|
|
var errIntRanges = errors.New("intRanges error")
|
|
|
|
func NewIntRanges[T constraints.Integer](expected string) (IntRanges[T], error) {
|
|
// example: 200 or 200/302 or 200-400 or 200/204/401-429/501-503
|
|
expected = strings.TrimSpace(expected)
|
|
if len(expected) == 0 || expected == "*" {
|
|
return nil, nil
|
|
}
|
|
|
|
list := strings.Split(expected, "/")
|
|
if len(list) > 28 {
|
|
return nil, fmt.Errorf("%w, too many ranges to use, maximum support 28 ranges", errIntRanges)
|
|
}
|
|
|
|
return NewIntRangesFromList[T](list)
|
|
}
|
|
|
|
func NewIntRangesFromList[T constraints.Integer](list []string) (IntRanges[T], error) {
|
|
var ranges IntRanges[T]
|
|
for _, s := range list {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
|
|
status := strings.Split(s, "-")
|
|
statusLen := len(status)
|
|
if statusLen > 2 {
|
|
return nil, errIntRanges
|
|
}
|
|
|
|
start, err := strconv.ParseInt(strings.Trim(status[0], "[ ]"), 10, 64)
|
|
if err != nil {
|
|
return nil, errIntRanges
|
|
}
|
|
|
|
switch statusLen {
|
|
case 1:
|
|
ranges = append(ranges, NewRange(T(start), T(start)))
|
|
case 2:
|
|
end, err := strconv.ParseUint(strings.Trim(status[1], "[ ]"), 10, 64)
|
|
if err != nil {
|
|
return nil, errIntRanges
|
|
}
|
|
|
|
ranges = append(ranges, NewRange(T(start), T(end)))
|
|
}
|
|
}
|
|
|
|
return ranges, nil
|
|
}
|
|
|
|
func (ranges IntRanges[T]) Check(status T) bool {
|
|
if len(ranges) == 0 {
|
|
return true
|
|
}
|
|
|
|
for _, segment := range ranges {
|
|
if segment.Contains(status) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (ranges IntRanges[T]) ToString() string {
|
|
if len(ranges) == 0 {
|
|
return "*"
|
|
}
|
|
|
|
terms := make([]string, len(ranges))
|
|
for i, r := range ranges {
|
|
start := r.Start()
|
|
end := r.End()
|
|
|
|
var term string
|
|
if start == end {
|
|
term = strconv.Itoa(int(start))
|
|
} else {
|
|
term = strconv.Itoa(int(start)) + "-" + strconv.Itoa(int(end))
|
|
}
|
|
|
|
terms[i] = term
|
|
}
|
|
|
|
return strings.Join(terms, "/")
|
|
}
|