-
Notifications
You must be signed in to change notification settings - Fork 0
/
matcher.go
75 lines (60 loc) · 2.16 KB
/
matcher.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
package bus
import (
"errors"
"fmt"
"regexp"
"strings"
)
var (
ErrInvalidSubjectPattern = errors.New("invalid subject pattern")
)
// same as in nats: https://github.com/nats-io/nats.go/blob/610da835da9546f9132cf4d566aa80d1e95ef93b/jetstream/jetstream.go#L216
var subjectRegexp = regexp.MustCompile(`^[^ >]*>?$`)
// MatchSubject checks whether a given subject matches a given pattern.
// The pattern can be expressed in the same syntax as in NATS.
// For more information about valid patterns check: https://docs.nats.io/nats-concepts/subjects#wildcards
func MatchSubject(subject, pattern string) bool {
subjectTokens := strings.Split(subject, ".")
patternTokens := strings.Split(pattern, ".")
return matchTokens(subjectTokens, patternTokens)
}
func ValidatePattern(pattern string) error {
if pattern == "" {
return fmt.Errorf("%w: %s", ErrInvalidSubjectPattern, "pattern cannot be empty")
}
if !subjectRegexp.MatchString(pattern) {
return fmt.Errorf("%w: %s", ErrInvalidSubjectPattern, pattern)
}
return nil
}
func matchTokens(subjectTokens, patternTokens []string) bool {
// If there are no more tokens in the pattern, and no more tokens in the subject,
// then it is a match.
if len(patternTokens) == 0 && len(subjectTokens) == 0 {
return true
}
// If there are no more tokens in the pattern, but there are still tokens in the subject,
// then it is not a match.
if len(patternTokens) == 0 {
return false
}
// If there are more tokens in the pattern, but no more tokens in the subject,
// then check if the remaining pattern token is ">", which means it's a match.
if len(subjectTokens) == 0 {
return patternTokens[0] == ">"
}
// If the pattern token is ">", it matches the remaining subject tokens.
if patternTokens[0] == ">" {
return true
}
// If the pattern token is "*", it matches any single subject token.
if patternTokens[0] == "*" {
return matchTokens(subjectTokens[1:], patternTokens[1:])
}
// If the current tokens are equal, continue with the next tokens.
if subjectTokens[0] == patternTokens[0] {
return matchTokens(subjectTokens[1:], patternTokens[1:])
}
// If none of the above conditions are met, it is not a match.
return false
}