chore: simplified logic rule parsing
Some checks failed
Test / test (1.20, macos-15-intel) (push) Has been cancelled
Test / test (1.20, macos-latest) (push) Has been cancelled
Test / test (1.20, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.20, ubuntu-latest) (push) Has been cancelled
Test / test (1.20, windows-latest) (push) Has been cancelled
Test / test (1.21, macos-15-intel) (push) Has been cancelled
Test / test (1.21, macos-latest) (push) Has been cancelled
Test / test (1.21, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.21, ubuntu-latest) (push) Has been cancelled
Test / test (1.21, windows-latest) (push) Has been cancelled
Test / test (1.22, macos-15-intel) (push) Has been cancelled
Test / test (1.22, macos-latest) (push) Has been cancelled
Test / test (1.22, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.22, ubuntu-latest) (push) Has been cancelled
Test / test (1.22, windows-latest) (push) Has been cancelled
Test / test (1.23, macos-15-intel) (push) Has been cancelled
Test / test (1.23, macos-latest) (push) Has been cancelled
Test / test (1.23, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.23, ubuntu-latest) (push) Has been cancelled
Test / test (1.23, windows-latest) (push) Has been cancelled
Test / test (1.24, macos-15-intel) (push) Has been cancelled
Test / test (1.24, macos-latest) (push) Has been cancelled
Test / test (1.24, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.24, ubuntu-latest) (push) Has been cancelled
Test / test (1.24, windows-latest) (push) Has been cancelled
Test / test (1.25, macos-15-intel) (push) Has been cancelled
Test / test (1.25, macos-latest) (push) Has been cancelled
Test / test (1.25, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.25, ubuntu-latest) (push) Has been cancelled
Test / test (1.25, windows-latest) (push) Has been cancelled
Test / test (1.26.0-rc.1, macos-15-intel) (push) Has been cancelled
Test / test (1.26.0-rc.1, macos-latest) (push) Has been cancelled
Test / test (1.26.0-rc.1, ubuntu-24.04-arm) (push) Has been cancelled
Test / test (1.26.0-rc.1, ubuntu-latest) (push) Has been cancelled
Test / test (1.26.0-rc.1, windows-latest) (push) Has been cancelled
Trigger CMFA Update / trigger-CMFA-update (push) Has been cancelled

This commit is contained in:
wwqgtxx 2026-01-08 23:42:01 +08:00
parent 0f2baca2de
commit 94c8d60f72
2 changed files with 41 additions and 45 deletions

View File

@ -2,14 +2,12 @@ package logic
import ( import (
"fmt" "fmt"
"regexp" "sort"
"strings" "strings"
"sync" "sync"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/rules/common" "github.com/metacubex/mihomo/rules/common"
list "github.com/bahlo/generic-list-go"
) )
type Logic struct { type Logic struct {
@ -70,7 +68,6 @@ func NewAND(payload string, adapter string, parseRule common.ParseRuleFunc) (*Lo
type Range struct { type Range struct {
start int start int
end int end int
index int
} }
func (r Range) containRange(preStart, preEnd int) bool { func (r Range) containRange(preStart, preEnd int) bool {
@ -89,40 +86,35 @@ func (logic *Logic) payloadToRule(subPayload string, parseRule common.ParseRuleF
} }
func (logic *Logic) format(payload string) ([]Range, error) { func (logic *Logic) format(payload string) ([]Range, error) {
stack := list.New[Range]() stack := make([]int, 0)
num := 0
subRanges := make([]Range, 0) subRanges := make([]Range, 0)
for i, c := range payload { for i, c := range payload {
if c == '(' { if c == '(' {
sr := Range{ stack = append(stack, i) // push
start: i,
index: num,
}
num++
stack.PushBack(sr)
} else if c == ')' { } else if c == ')' {
if stack.Len() == 0 { if len(stack) == 0 {
return nil, fmt.Errorf("missing '('") return nil, fmt.Errorf("missing '('")
} }
sr := stack.Back() back := len(stack) - 1
stack.Remove(sr) start := stack[back] // back
sr.Value.end = i stack = stack[:back] // pop
subRanges = append(subRanges, sr.Value) subRanges = append(subRanges, Range{
start: start,
end: i,
})
} }
} }
if stack.Len() != 0 { if len(stack) != 0 {
return nil, fmt.Errorf("format error is missing )") return nil, fmt.Errorf("format error is missing )")
} }
sortResult := make([]Range, len(subRanges)) sort.Slice(subRanges, func(i, j int) bool {
for _, sr := range subRanges { return subRanges[i].start < subRanges[j].start
sortResult[sr.index] = sr })
}
return sortResult, nil return subRanges, nil
} }
func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range { func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range {
@ -152,36 +144,32 @@ func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range
} }
func (logic *Logic) parsePayload(payload string, parseRule common.ParseRuleFunc) error { func (logic *Logic) parsePayload(payload string, parseRule common.ParseRuleFunc) error {
regex, err := regexp.Compile("\\(.*\\)") if !strings.HasPrefix(payload, "(") || !strings.HasSuffix(payload, ")") { // the payload must be "(xxx)" format
return fmt.Errorf("payload format error")
}
subAllRanges, err := logic.format(payload)
if err != nil { if err != nil {
return err return err
} }
if regex.MatchString(payload) { rules := make([]C.Rule, 0, len(subAllRanges))
subAllRanges, err := logic.format(payload)
subRanges := logic.findSubRuleRange(payload, subAllRanges)
for _, subRange := range subRanges {
subPayload := payload[subRange.start+1 : subRange.end]
rule, err := logic.payloadToRule(subPayload, parseRule)
if err != nil { if err != nil {
return err return err
} }
rules := make([]C.Rule, 0, len(subAllRanges))
subRanges := logic.findSubRuleRange(payload, subAllRanges) rules = append(rules, rule)
for _, subRange := range subRanges {
subPayload := payload[subRange.start+1 : subRange.end]
rule, err := logic.payloadToRule(subPayload, parseRule)
if err != nil {
return err
}
rules = append(rules, rule)
}
logic.rules = rules
return nil
} }
return fmt.Errorf("payload format error") logic.rules = rules
return nil
} }
func (logic *Logic) RuleType() C.RuleType { func (logic *Logic) RuleType() C.RuleType {

View File

@ -1,13 +1,15 @@
package logic_test package logic_test
import ( import (
"testing"
// https://github.com/golang/go/wiki/CodeReviewComments#import-dot // https://github.com/golang/go/wiki/CodeReviewComments#import-dot
. "github.com/metacubex/mihomo/rules/logic" . "github.com/metacubex/mihomo/rules/logic"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/rules" "github.com/metacubex/mihomo/rules"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
var ParseRule = rules.ParseRule var ParseRule = rules.ParseRule
@ -38,6 +40,12 @@ func TestNOT(t *testing.T) {
}, C.RuleMatchHelper{}) }, C.RuleMatchHelper{})
assert.Equal(t, false, m) assert.Equal(t, false, m)
_, err = NewNOT("(DST-PORT,5600-6666)", "DIRECT", ParseRule)
assert.NotEqual(t, nil, err)
_, err = NewNOT("DST-PORT,5600-6666", "DIRECT", ParseRule)
assert.NotEqual(t, nil, err)
_, err = NewNOT("((DST-PORT,5600-6666),(DOMAIN,baidu.com))", "DIRECT", ParseRule) _, err = NewNOT("((DST-PORT,5600-6666),(DOMAIN,baidu.com))", "DIRECT", ParseRule)
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)