3
0
Files
corteza/server/pkg/eventbus/constraints.go
Denis Arh e5d67c6e16 Error package related codebase improvements
Remove/replace "github.com/pkg/errors" and "errors"
with "fmt" or "corteza/server/pkg/errors"

Closes #528
2022-11-27 10:29:36 +01:00

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
}