forked from cloudflare/ahocorasick
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rules.go
84 lines (72 loc) · 2.11 KB
/
rules.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package ac
import (
"errors"
"fmt"
"sort"
"time"
)
var ErrRuleNotExists = errors.New("rule not exists")
var ErrRuleTooOld = errors.New("rule too old")
var ErrRuleAlreadyExists = errors.New("rule already exists")
// Rule 一条匹配规则
type Rule struct {
ID uint32 // 规则ID 和key是一一对应关系 !!!ID全局唯一!!!
Key []rune // 匹配模式 !!!Key可重复!!!
Value interface{} // 自定义值
UpdateTs time.Time // 更新时间戳
ExpireTime time.Time // 过期时间点时间戳
}
// Rules represents rule slice
type Rules []*Rule
func (rs *Rules) Add(r *Rule) error {
index := rs.IndexOf(r.ID)
// 新增规则
if index == -1 {
*rs = append(*rs, r)
sort.Sort(*rs)
return nil
}
// 如果时间戳更新
// 直接替换规则
if r.UpdateTs.After((*rs)[index].UpdateTs) {
(*rs)[index] = r
return nil
}
// log.Debugf("[lowlevel-Add] new(%v) old(%v)", spew.Sdump(r), spew.Sdump((*rs)[index]))
return fmt.Errorf("id(%d) err(%v)", r.ID, ErrRuleTooOld)
}
func (rs *Rules) Delete(r *Rule) error {
index := rs.IndexOf(r.ID)
if index == -1 {
return fmt.Errorf("id(%d) err(%v)", r.ID, ErrRuleNotExists)
}
// 删除操作的时间戳 > 已有规则
if r.UpdateTs.After((*rs)[index].UpdateTs) {
*rs = append((*rs)[:index], (*rs)[index+1:]...)
return nil
}
// log.Debugf("[lowlevel-Delete] new(%v) old(%v)", spew.Sdump(r), spew.Sdump((*rs)[index]))
return fmt.Errorf("id(%d) err(%v)", r.ID, ErrRuleTooOld)
}
//IndexOf returns index of expectMatched byte or -1
func (n Rules) IndexOf(rid uint32) int {
lowerBoundIndex := 0
upperBoundIndex := len(n) - 1
loop:
if lowerBoundIndex <= upperBoundIndex {
mediumIndex := (lowerBoundIndex + upperBoundIndex) / 2
candidate := n[mediumIndex].ID
if candidate < rid {
lowerBoundIndex = mediumIndex + 1
} else if candidate > rid {
upperBoundIndex = mediumIndex - 1
} else {
return mediumIndex
}
goto loop
}
return -1
}
func (n Rules) Len() int { return len(n) }
func (n Rules) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
func (n Rules) Less(i, j int) bool { return n[i].ID < n[j].ID }