Remove/replace "github.com/pkg/errors" and "errors" with "fmt" or "corteza/server/pkg/errors" Closes #528
179 lines
3.5 KiB
Go
179 lines
3.5 KiB
Go
package eventbus
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type (
|
|
mustBeEqual struct {
|
|
not bool
|
|
name string
|
|
values []string
|
|
}
|
|
|
|
mustBeLike struct {
|
|
not bool
|
|
name string
|
|
values []string
|
|
}
|
|
|
|
mustMatch struct {
|
|
not bool
|
|
name string
|
|
values []*regexp.Regexp
|
|
}
|
|
|
|
ConstraintMatcher interface {
|
|
Name() string
|
|
Values() []string
|
|
Match(value string) bool
|
|
}
|
|
|
|
constraintSet []ConstraintMatcher
|
|
)
|
|
|
|
var ErrUnsupportedOp = fmt.Errorf("operator not supported")
|
|
var ErrUnsupportedName = fmt.Errorf("constraint name not supported")
|
|
|
|
func (c mustBeEqual) Name() string { return c.name }
|
|
func (c mustBeLike) Name() string { return c.name }
|
|
func (c mustMatch) Name() string { return c.name }
|
|
func (c mustBeEqual) Values() []string { return c.values }
|
|
func (c mustBeLike) Values() []string { return c.values }
|
|
func (c mustMatch) Values() []string { return nil }
|
|
|
|
// Converts raw ConstraintMatcher into one of the
|
|
// ConstraintMatcher handlers
|
|
func ConstraintMaker(name, op string, vv ...string) (ConstraintMatcher, error) {
|
|
switch strings.ToLower(op) {
|
|
case "", "eq", "=", "==", "===":
|
|
return MustBeEqual(name, vv...)
|
|
case "not eq", "ne", "!=", "!==":
|
|
return MustNotBeEqual(name, vv...)
|
|
case "like":
|
|
return MustBeLike(name, vv...)
|
|
case "not like":
|
|
return MustNotBeLike(name, vv...)
|
|
case "~":
|
|
return MustMatch(name, vv...)
|
|
case "!~":
|
|
return MustNotMatch(name, vv...)
|
|
default:
|
|
return nil, ErrUnsupportedOp
|
|
}
|
|
}
|
|
|
|
func MustMakeConstraint(name, op string, vv ...string) ConstraintMatcher {
|
|
c, err := ConstraintMaker(name, op, vv...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func MustBeEqual(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return &mustBeEqual{name: name, values: vv}, nil
|
|
}
|
|
|
|
func MustNotBeEqual(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return &mustBeEqual{name: name, values: vv, not: true}, nil
|
|
}
|
|
|
|
func (c mustBeEqual) Match(value string) bool {
|
|
for _, v := range c.values {
|
|
if value == v {
|
|
return !c.not
|
|
}
|
|
}
|
|
|
|
return c.not
|
|
}
|
|
|
|
func mustLikeMaker(name string, not bool, vv ...string) (*mustBeLike, error) {
|
|
var (
|
|
m = &mustBeLike{
|
|
name: name,
|
|
values: make([]string, len(vv)),
|
|
not: not,
|
|
}
|
|
)
|
|
|
|
for i, v := range vv {
|
|
v = strings.ReplaceAll(v, "%", "*")
|
|
v = strings.ReplaceAll(v, "_", "?")
|
|
m.values[i] = v
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func MustBeLike(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return mustLikeMaker(name, false, vv...)
|
|
}
|
|
|
|
func MustNotBeLike(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return mustLikeMaker(name, true, vv...)
|
|
}
|
|
|
|
func (c mustBeLike) Match(value string) bool {
|
|
for _, v := range c.values {
|
|
if m, _ := path.Match(v, value); m {
|
|
return !c.not
|
|
}
|
|
}
|
|
|
|
return c.not
|
|
}
|
|
|
|
func mustMatchMaker(name string, not bool, vv ...string) (*mustMatch, error) {
|
|
var (
|
|
m = &mustMatch{
|
|
name: name,
|
|
values: make([]*regexp.Regexp, len(vv)),
|
|
not: not,
|
|
}
|
|
err error
|
|
)
|
|
|
|
for i, v := range vv {
|
|
if m.values[i], err = regexp.Compile(v); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func MustMatch(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return mustMatchMaker(name, false, vv...)
|
|
}
|
|
|
|
func MustNotMatch(name string, vv ...string) (ConstraintMatcher, error) {
|
|
return mustMatchMaker(name, true, vv...)
|
|
|
|
}
|
|
|
|
func (c mustMatch) Match(value string) bool {
|
|
for _, v := range c.values {
|
|
if v.MatchString(value) {
|
|
return !c.not
|
|
}
|
|
}
|
|
|
|
return c.not
|
|
}
|
|
|
|
func MatchFirst(checks ...func() bool) bool {
|
|
for _, check := range checks {
|
|
if check() {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|