Refactor: Use struct Int32Range widely (#3867)

https://github.com/XTLS/Xray-core/pull/3867#issuecomment-2412847316
This commit is contained in:
风扇滑翔翼 2024-10-15 12:05:22 +08:00 committed by RPRX
parent 19f3f709b2
commit 82bd5f3046
2 changed files with 75 additions and 97 deletions

View file

@ -246,43 +246,76 @@ func (v *User) Build() *protocol.User {
// Int32Range deserializes from "1-2" or 1, so can deserialize from both int and number.
// Negative integers can be passed as sentinel values, but do not parse as ranges.
// Value will be exchanged if From > To, use .Left and .Right to get original value if need.
type Int32Range struct {
From int32
To int32
Left int32
Right int32
From int32
To int32
}
func (v *Int32Range) UnmarshalJSON(data []byte) error {
defer v.ensureOrder()
var str string
var rawint int32
if err := json.Unmarshal(data, &str); err == nil {
// for number in string format like "114" or "-1"
if value, err := strconv.Atoi(str); err == nil {
v.From = int32(value)
v.To = int32(value)
left, right, err := ParseRangeString(str)
if err == nil {
v.Left, v.Right = int32(left), int32(right)
return nil
}
// for empty "", we treat it as 0
if str == "" {
v.From = 0
v.To = 0
return nil
}
// for range value, like "114-514"
pair := strings.SplitN(str, "-", 2)
if len(pair) == 2 {
from, err := strconv.Atoi(pair[0])
to, err2 := strconv.Atoi(pair[1])
if err == nil && err2 == nil {
v.From = int32(from)
v.To = int32(to)
return nil
}
}
} else if err := json.Unmarshal(data, &rawint); err == nil {
v.From = rawint
v.To = rawint
v.Left = rawint
v.Right = rawint
return nil
}
return errors.New("Invalid integer range, expected either string of form \"1-2\" or plain integer.")
}
// ensureOrder() gives value to .From & .To and make sure .From < .To
func (r *Int32Range) ensureOrder() {
r.From, r.To = r.Left, r.Right
if r.From > r.To {
r.From, r.To = r.To, r.From
}
}
// "-114-514" → ["-114","514"]
// "-1919--810" → ["-1919","-810"]
func splitFromSecondDash(s string) []string {
parts := strings.SplitN(s, "-", 3)
if len(parts) < 3 {
return []string{s}
}
return []string{parts[0] + "-" + parts[1], parts[2]}
}
// Parse rang in string. Support negative number.
// eg: "114-514" "-114-514" "-1919--810" "114514" ""(return 0)
func ParseRangeString(str string) (int, int, error) {
// for number in string format like "114" or "-1"
if value, err := strconv.Atoi(str); err == nil {
return value, value, nil
}
// for empty "", we treat it as 0
if str == "" {
return 0, 0, nil
}
// for range value, like "114-514"
var pair []string
// Process sth like "-114-514" "-1919--810"
if strings.HasPrefix(str, "-") {
pair = splitFromSecondDash(str)
} else {
pair = strings.SplitN(str, "-", 2)
}
if len(pair) == 2 {
left, err := strconv.Atoi(pair[0])
right, err2 := strconv.Atoi(pair[1])
if err == nil && err2 == nil {
return left, right, nil
}
}
return 0, 0, errors.New("invalid range string: ", str)
}