Files
clash-meta/common/utils/range.go
T

104 lines
2.1 KiB
Go

package utils
import (
"fmt"
"strconv"
"strings"
"golang.org/x/exp/constraints"
)
type Range[T constraints.Ordered] struct {
start T
end T
}
func NewRange[T constraints.Ordered](start, end T) Range[T] {
if start > end {
return Range[T]{
start: end,
end: start,
}
}
return Range[T]{
start: start,
end: end,
}
}
func (r Range[T]) Contains(t T) bool {
return t >= r.start && t <= r.end
}
func (r Range[T]) LeftContains(t T) bool {
return t >= r.start && t < r.end
}
func (r Range[T]) RightContains(t T) bool {
return t > r.start && t <= r.end
}
func (r Range[T]) Start() T {
return r.start
}
func (r Range[T]) End() T {
return r.end
}
func (r Range[T]) String() string {
if r.start == r.end {
return fmt.Sprintf("%v", r.start)
}
return fmt.Sprintf("%v-%v", r.start, r.end)
}
func NewUnsignedRange[T constraints.Unsigned](expected string) (Range[T], error) {
return newIntRange(expected, parseUnsigned[T])
}
func NewSignedRange[T constraints.Signed](expected string) (Range[T], error) {
return newIntRange(expected, parseSigned[T])
}
func newIntRange[T constraints.Integer](s string, parseFn func(string) (T, error)) (Range[T], error) {
s = strings.TrimSpace(s)
if len(s) == 0 {
return NewRange[T](0, 0), nil
}
status := strings.Split(s, "-")
start, err := parseFn(strings.Trim(status[0], "[ ]"))
if err != nil {
return Range[T]{}, fmt.Errorf("invalid range: %s", s)
}
switch len(status) {
case 1: // Port range
return NewRange(start, start), nil
case 2: // Single port
end, err := parseFn(strings.Trim(status[1], "[ ]"))
if err != nil {
return Range[T]{}, fmt.Errorf("invalid range: %s", s)
}
return NewRange(start, end), nil
default:
return Range[T]{}, fmt.Errorf("invalid range: %s", s)
}
}
func parseUnsigned[T constraints.Unsigned](s string) (T, error) {
if val, err := strconv.ParseUint(s, 10, 64); err == nil {
return T(val), nil
} else {
return 0, err
}
}
func parseSigned[T constraints.Signed](s string) (T, error) {
if val, err := strconv.ParseInt(s, 10, 64); err == nil {
return T(val), nil
} else {
return 0, err
}
}