constraints

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DictContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{}
View Source
var DocumentContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{}
View Source
var ListContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{
	"not_empty": {
		Name:    "not_empty",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if val.Kind() != box.ValueList {
				return fmt.Errorf("expected list, got %s", val.Kind())
			}
			if lst, ok := val.ListValue(); ok && len(lst) == 0 {
				return fmt.Errorf("list is empty - expected non-empty list")
			}
			return nil
		},
	},
}
View Source
var NumberContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{
	"min": {
		Name:    "min",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("min constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum < arg {
				return fmt.Errorf("value %v is not >= %v", val, arg)
			}
			return nil
		},
	},
	"max": {
		Name:    "max",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("max constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum > arg {
				return fmt.Errorf("value %v is not <= %v", val, arg)
			}
			return nil
		},
	},
	"eq": {
		Name:    "eq",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("eq constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum != arg {
				return fmt.Errorf("value %v is not equal to %v", val, arg)
			}
			return nil
		},
	},
	"neq": {
		Name:    "neq",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("neq constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum == arg {
				return fmt.Errorf("value %v is equal to %v", val, arg)
			}
			return nil
		},
	},
	"gt": {
		Name:    "gt",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("gt constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum <= arg {
				return fmt.Errorf("value %v is not > %v", val, arg)
			}
			return nil
		},
	},
	"lt": {
		Name:    "lt",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("lt constraint requires 1 argument")
			}
			arg, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum >= arg {
				return fmt.Errorf("value %v is not < %v", val, arg)
			}
			return nil
		},
	},
	"in": {
		Name:    "in",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("in constraint requires 1 argument")
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			set, err := numberConstraintSet(args[0])
			if err != nil {
				return err
			}

			if !slices.Contains(set, valNum) {
				return fmt.Errorf("value %v is not in the set", val)
			}
			return nil
		},
	},
	"not_in": {
		Name:    "not_in",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("not_in constraint requires 1 argument")
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			set, err := numberConstraintSet(args[0])
			if err != nil {
				return err
			}

			if slices.Contains(set, valNum) {
				return fmt.Errorf("value %v is in the set", val)
			}
			return nil
		},
	},
	"range": {
		Name:    "range",
		NumArgs: 2,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 2 {
				return fmt.Errorf("range constraint requires 2 arguments")
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			min, ok0 := args[0].NumberValue()
			max, ok1 := args[1].NumberValue()
			if !ok0 {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			if !ok1 {
				return fmt.Errorf("expected number, got %s", args[1].Kind())
			}
			if valNum < min || valNum > max {
				return fmt.Errorf("value %v is not in range [%v, %v]", val, min, max)
			}
			return nil
		},
	},
	"even": {
		Name:    "even",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if math.Mod(valNum, 2) != 0 {
				return fmt.Errorf("value %v is not even", val)
			}
			return nil
		},
	},
	"odd": {
		Name:    "odd",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if math.Mod(valNum, 2) == 0 {
				return fmt.Errorf("value %v is not odd", val)
			}
			return nil
		},
	},
	"multiple_of": {
		Name:    "multiple_of",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			if len(args) != 1 {
				return fmt.Errorf("multiple_of constraint requires 1 argument")
			}
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			divisor, ok := args[0].NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			if divisor == 0 {
				return fmt.Errorf("divisor cannot be zero")
			}

			epsilon := 1e-10
			remainder := math.Mod(valNum, divisor)
			if remainder > epsilon && remainder < divisor-epsilon {
				return fmt.Errorf("value %v is not a multiple of %v", val, divisor)
			}
			return nil
		},
	},
	"positive": {
		Name:    "positive",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum <= 0 {
				return fmt.Errorf("value %v is not positive", val)
			}
			return nil
		},
	},
	"negative": {
		Name:    "negative",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum >= 0 {
				return fmt.Errorf("value %v is not negative", val)
			}
			return nil
		},
	},
	"non_negative": {
		Name:    "non_negative",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum < 0 {
				return fmt.Errorf("value %v is negative", val)
			}
			return nil
		},
	},
	"non_positive": {
		Name:    "non_positive",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if valNum > 0 {
				return fmt.Errorf("value %v is positive", val)
			}
			return nil
		},
	},
	"finite": {
		Name:    "finite",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if math.IsInf(valNum, 0) || math.IsNaN(valNum) {
				return fmt.Errorf("value %v is not finite", val)
			}
			return nil
		},
	},
	"infinite": {
		Name:    "infinite",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if !math.IsInf(valNum, 0) {
				return fmt.Errorf("value %v is not infinite", val)
			}
			return nil
		},
	},
	"nan": {
		Name:    "nan",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			valNum, ok := val.NumberValue()
			if !ok {
				return fmt.Errorf("expected number, got %s", val.Kind())
			}
			if !math.IsNaN(valNum) {
				return fmt.Errorf("value %v is not NaN", val)
			}
			return nil
		},
	},
}
View Source
var RecordContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{}
View Source
var ShapeContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{}
View Source
var StringContraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{
	"length": {
		Name:    "length",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("length constraint requires 1 argument")
			}
			expectedLen, okn := args[0].NumberValue()
			if !okn {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			if len(s) != int(expectedLen) {
				return fmt.Errorf("string length %d is not equal to %g", len(s), expectedLen)
			}
			return nil
		},
	},
	"minlength": {
		Name:    "minlength",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("minlength constraint requires 1 argument")
			}
			expectedLen, okn := args[0].NumberValue()
			if !okn {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			if len(s) < int(expectedLen) {
				return fmt.Errorf("string length %d is not greater than or equal to %g", len(s), expectedLen)
			}
			return nil
		},
	},
	"maxlength": {
		Name:    "maxlength",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("maxlength constraint requires 1 argument")
			}
			expectedLen, okn := args[0].NumberValue()
			if !okn {
				return fmt.Errorf("expected number, got %s", args[0].Kind())
			}
			if len(s) > int(expectedLen) {
				return fmt.Errorf("string length %d is not less than or equal to %g", len(s), expectedLen)
			}
			return nil
		},
	},
	"regexp": {
		Name:    "regexp",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("regexp constraint requires 1 argument")
			}
			pattern, okp := args[0].StringValue()
			if !okp {
				return fmt.Errorf("expected string, got %s", args[0].Kind())
			}
			matched, err := regexp.MatchString(pattern, s)
			if err != nil {
				return fmt.Errorf("invalid regexp pattern: %v", err)
			}
			if !matched {
				return fmt.Errorf("string %q does not match pattern %q", s, pattern)
			}
			return nil
		},
	},
	"starts_with": {
		Name:    "starts_with",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("starts_with constraint requires 1 argument")
			}
			prefix, okp := args[0].StringValue()
			if !okp {
				return fmt.Errorf("expected string, got %s", args[0].Kind())
			}
			if !strings.HasPrefix(s, prefix) {
				return fmt.Errorf("string %q does not start with %q", s, prefix)
			}
			return nil
		},
	},
	"ends_with": {
		Name:    "ends_with",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("ends_with constraint requires 1 argument")
			}
			suffix, okp := args[0].StringValue()
			if !okp {
				return fmt.Errorf("expected string, got %s", args[0].Kind())
			}
			if !strings.HasSuffix(s, suffix) {
				return fmt.Errorf("string %q does not end with %q", s, suffix)
			}
			return nil
		},
	},
	"has_substring": {
		Name:    "has_substring",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("has_substring constraint requires 1 argument")
			}
			substring, okp := args[0].StringValue()
			if !okp {
				return fmt.Errorf("expected string, got %s", args[0].Kind())
			}
			if !strings.Contains(s, substring) {
				return fmt.Errorf("string %q does not contain %q", s, substring)
			}
			return nil
		},
	},
	"not_has_substring": {
		Name:    "not_has_substring",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("not_has_substring constraint requires 1 argument")
			}
			substring, okp := args[0].StringValue()
			if !okp {
				return fmt.Errorf("expected string, got %s", args[0].Kind())
			}
			if strings.Contains(s, substring) {
				return fmt.Errorf("string %q contains %q", s, substring)
			}
			return nil
		},
	},
	"email": {
		Name:    "email",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
			if !emailRegex.MatchString(s) {
				return fmt.Errorf("string %q is not a valid email", s)
			}
			return nil
		},
	},
	"url": {
		Name:    "url",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			urlRegex := regexp.MustCompile(`^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$`)
			if !urlRegex.MatchString(s) {
				return fmt.Errorf("string %q is not a valid URL", s)
			}
			return nil
		},
	},
	"uuid": {
		Name:    "uuid",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			err := uuid.Validate(s)
			if err != nil {
				return fmt.Errorf("string %q is not a valid UUID: %v", s, err)
			}
			return nil
		},
	},
	"alphanumeric": {
		Name:    "alphanumeric",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			for _, r := range s {
				if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
					return fmt.Errorf("string %q contains non-alphanumeric characters", s)
				}
			}
			return nil
		},
	},
	"alpha": {
		Name:    "alpha",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			for _, r := range s {
				if !unicode.IsLetter(r) {
					return fmt.Errorf("string %q contains non-letter characters", s)
				}
			}
			return nil
		},
	},
	"numeric": {
		Name:    "numeric",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}

			if _, err := strconv.ParseFloat(s, 64); err != nil {
				return fmt.Errorf("string %q is not a valid numeric value", s)
			}
			return nil
		},
	},
	"lowercase": {
		Name:    "lowercase",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if s != strings.ToLower(s) {
				return fmt.Errorf("string %q is not lowercase", s)
			}
			return nil
		},
	},
	"uppercase": {
		Name:    "uppercase",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if s != strings.ToUpper(s) {
				return fmt.Errorf("string %q is not uppercase", s)
			}
			return nil
		},
	},
	"trimmed": {
		Name:    "trimmed",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if s != strings.TrimSpace(s) {
				return fmt.Errorf("string %q has leading or trailing whitespace", s)
			}
			return nil
		},
	},
	"not_empty": {
		Name:    "not_empty",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if s == "" {
				return fmt.Errorf("string is empty")
			}
			return nil
		},
	},
	"one_of": {
		Name:    "one_of",
		NumArgs: -1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) < 1 {
				return fmt.Errorf("one_of constraint requires at least 1 argument")
			}
			for _, arg := range args {
				argString, oka := arg.StringValue()
				if !oka {
					return fmt.Errorf("expected string, got %s", arg.Kind())
				}
				if s == argString {
					return nil
				}
			}
			return fmt.Errorf("string %q is not one of the allowed values", s)
		},
	},
	"not_one_of": {
		Name:    "not_one_of",
		NumArgs: -1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			s, ok := val.StringValue()
			if !ok {
				return fmt.Errorf("expected string, got %s", val.Kind())
			}
			if len(args) < 1 {
				return fmt.Errorf("not_one_of constraint requires at least 1 argument")
			}
			for _, arg := range args {
				argString, oka := arg.StringValue()
				if !oka {
					return fmt.Errorf("expected string, got %s", arg.Kind())
				}
				if s == argString {
					return fmt.Errorf("string %q is one of the allowed values", s)
				}
			}

			return nil
		},
	},
}
View Source
var TrinaryConstraintCheckers map[string]ConstraintDefinition = map[string]ConstraintDefinition{
	"not_unknown": {
		Name:    "not_unknown",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			tv, ok := val.TrinaryValue()
			if !ok {
				return fmt.Errorf("expected trinary, got %s", val.Kind())
			}
			if tv == trinary.Unknown {
				return fmt.Errorf("value is unknown")
			}
			return nil
		},
	},
	"eq": {
		Name:    "eq",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			tv, ok := val.TrinaryValue()
			if !ok {
				return fmt.Errorf("expected trinary, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("eq constraint requires 1 argument")
			}
			expected, oka := args[0].TrinaryValue()
			if !oka {
				return fmt.Errorf("eq constraint expects a boolean argument")
			}
			if tv != expected {
				return fmt.Errorf("value %v is not equal to %v", tv, expected)
			}
			return nil
		},
	},
	"neq": {
		Name:    "neq",
		NumArgs: 1,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			tv, ok := val.TrinaryValue()
			if !ok {
				return fmt.Errorf("expected trinary, got %s", val.Kind())
			}
			if len(args) != 1 {
				return fmt.Errorf("neq constraint requires 1 argument")
			}
			expected, oka := args[0].TrinaryValue()
			if !oka {
				return fmt.Errorf("neq constraint expects a boolean argument")
			}
			if tv == expected {
				return fmt.Errorf("value %v is equal to %v - expected not equal", tv, expected)
			}
			return nil
		},
	},
	"is_true": {
		Name:    "is_true",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			tv, ok := val.TrinaryValue()
			if !ok {
				return fmt.Errorf("expected trinary, got %s", val.Kind())
			}
			if tv != trinary.True {
				return fmt.Errorf("value %v is not true", tv)
			}
			return nil
		},
	},
	"is_false": {
		Name:    "is_false",
		NumArgs: 0,
		Checker: func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error {
			tv, ok := val.TrinaryValue()
			if !ok {
				return fmt.Errorf("expected trinary, got %s", val.Kind())
			}
			if tv != trinary.False {
				return fmt.Errorf("value %v is not false", tv)
			}
			return nil
		},
	},
}

TrinaryConstraintCheckers contains supported boolean constraint validators. For trinaries, common constraints include eq/neq (compare to true/false/unknown), and truthiness helpers like is_true/is_false.

Functions

This section is empty.

Types

type ConstraintChecker

type ConstraintChecker func(ctx context.Context, p *index.Policy, val box.Value, args []box.Value) error

type ConstraintDefinition

type ConstraintDefinition struct {
	Name    string
	NumArgs int
	Checker ConstraintChecker
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL