Skip to content

Commit

Permalink
Dev when and skip on empty
Browse files Browse the repository at this point in the history
  • Loading branch information
raoptimus committed Mar 6, 2024
1 parent 089d240 commit 7aa0672
Show file tree
Hide file tree
Showing 24 changed files with 646 additions and 400 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ test:
-bench=$(TEST_PATTERN) \
-timeout=2m

lint: ## Run lint
golangci-lint run --timeout 5m

bench:
@[ -d ${REPORTS_DIR} ] || mkdir -p ${REPORTS_DIR}
@rm -rf ${REPORTS_DIR}/*
Expand Down
6 changes: 3 additions & 3 deletions basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ func toString(v any) (string, bool) {
return "", false
}

func hasRequiredRule(rules []Rule) (Required, bool) {
func hasRequiredRule(rules []Rule) (*Required, bool) {
for _, r := range rules {
if v, ok := r.(Required); ok {
if v, ok := r.(*Required); ok {
return v, ok
}
}

return Required{}, false
return nil, false
}
40 changes: 36 additions & 4 deletions callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,48 @@ import (

type CallbackFunc[T any] func(ctx context.Context, value T) error
type Callback[T any] struct {
f CallbackFunc[T]
f CallbackFunc[T]
whenFunc WhenFunc
skipEmpty bool
}

func NewCallback[T any](f CallbackFunc[T]) Callback[T] {
return Callback[T]{
func NewCallback[T any](f CallbackFunc[T]) *Callback[T] {
return &Callback[T]{
f: f,
}
}

func (c Callback[T]) ValidateValue(ctx context.Context, value any) error {
func (r *Callback[T]) When(v WhenFunc) *Callback[T] {
rc := *r
rc.whenFunc = v

return &rc
}

func (r *Callback[T]) when() WhenFunc {
return r.whenFunc
}

func (r *Callback[T]) setWhen(v WhenFunc) {
r.whenFunc = v
}

func (r *Callback[T]) SkipOnEmpty(v bool) *Callback[T] {
rc := *r
rc.skipEmpty = v

return &rc
}

func (r *Callback[T]) skipOnEmpty() bool {
return r.skipEmpty
}

func (r *Callback[T]) setSkipOnEmpty(v bool) {
r.skipEmpty = v
}

func (c *Callback[T]) ValidateValue(ctx context.Context, value any) error {
v, ok := value.(T)
if !ok {
var v T
Expand Down
2 changes: 1 addition & 1 deletion callback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestCallback_ValidateValue_Error(t *testing.T) {
rules := RuleSet{
"A": {
NewCallback(func(ctx context.Context, value int) error {
if ds, ok := extractDataSet(ctx); ok {
if ds, ok := ExtractDataSet[DataSet](ctx); ok {
if obj, ok := ds.Data().(*TestCallback); ok {
if obj.B > value {
return errAMustGreatB
Expand Down
79 changes: 48 additions & 31 deletions compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type Compare struct {
skipEmpty bool
}

func NewCompare(targetValue any, targetAttribute, operator string) Compare {
c := Compare{
func NewCompare(targetValue any, targetAttribute, operator string) *Compare {
c := &Compare{
targetValue: targetValue,
targetAttribute: targetAttribute,
operator: operator,
Expand All @@ -43,28 +43,45 @@ func NewCompare(targetValue any, targetAttribute, operator string) Compare {
return c
}

func (c Compare) When(v WhenFunc) Compare {
c.whenFunc = v
func (r *Compare) WithMessage(v string) *Compare {
rc := *r
rc.message = v

return c
return &rc
}

func (c Compare) when() WhenFunc {
return c.whenFunc
func (r *Compare) When(v WhenFunc) *Compare {
rc := *r
rc.whenFunc = v

return &rc
}

func (c Compare) SkipOnEmpty(v bool) Compare {
c.skipEmpty = v
func (r *Compare) when() WhenFunc {
return r.whenFunc
}

return c
func (r *Compare) setWhen(v WhenFunc) {
r.whenFunc = v
}

func (r *Compare) SkipOnEmpty(v bool) *Compare {
rc := *r
rc.skipEmpty = v

return &rc
}

func (r *Compare) skipOnEmpty() bool {
return r.skipEmpty
}

func (c Compare) skipOnEmpty() bool {
return c.skipEmpty
func (r *Compare) setSkipOnEmpty(v bool) {
r.skipEmpty = v
}

func (c Compare) ValidateValue(ctx context.Context, value any) error {
if !c.operatorIsValid {
func (r *Compare) ValidateValue(ctx context.Context, value any) error {
if !r.operatorIsValid {
return UnknownOperatorError
}

Expand All @@ -73,60 +90,60 @@ func (c Compare) ValidateValue(ctx context.Context, value any) error {
targetValueOrAttr any
err error
)
targetValue = c.targetValue
targetValueOrAttr = c.targetAttribute
targetValue = r.targetValue
targetValueOrAttr = r.targetAttribute

if c.targetValue == nil {
dataSet, ok := extractDataSet(ctx)
if r.targetValue == nil {
dataSet, ok := ExtractDataSet[DataSet](ctx)
if !ok {
return NotExistsDataSetIntoContextError
}
targetValue, err = dataSet.FieldValue(c.targetAttribute)
targetValue, err = dataSet.FieldValue(r.targetAttribute)
if err != nil {
return err
}
targetValueOrAttr = targetValue
}

switch c.operator {
switch r.operator {
case "==":
if c.eq(value, targetValue) {
if r.eq(value, targetValue) {
return nil
}
case "!=":
if !c.eq(value, targetValue) {
if !r.eq(value, targetValue) {
return nil
}
case ">":
if c.gt(value, targetValue) {
if r.gt(value, targetValue) {
return nil
}
case ">=":
if c.eq(value, targetValue) || c.gt(value, targetValue) {
if r.eq(value, targetValue) || r.gt(value, targetValue) {
return nil
}
case "<":
if !c.eq(value, targetValue) && !c.gt(value, targetValue) {
if !r.eq(value, targetValue) && !r.gt(value, targetValue) {
return nil
}
case "<=":
if c.eq(value, targetValue) || !c.gt(value, targetValue) {
if r.eq(value, targetValue) || !r.gt(value, targetValue) {
return nil
}
}

return NewResult().
WithError(
NewValidationError(c.message).
NewValidationError(r.message).
WithParams(map[string]any{
"targetValue": c.targetValue,
"targetAttribute": c.targetAttribute,
"targetValue": r.targetValue,
"targetAttribute": r.targetAttribute,
"targetValueOrAttribute": targetValueOrAttr,
}),
)
}

func (c Compare) eq(a, b any) bool {
func (r *Compare) eq(a, b any) bool {
if ia, ok := a.(int); ok {
if ib, ok := b.(int); ok {
return ia == ib
Expand Down Expand Up @@ -166,7 +183,7 @@ func (c Compare) eq(a, b any) bool {
return a == b
}

func (c Compare) gt(a, b any) bool {
func (r *Compare) gt(a, b any) bool {
if ia, ok := a.(int); ok {
if ib, ok := b.(int); ok {
return ia > ib
Expand Down
69 changes: 63 additions & 6 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Key uint8

const (
KeyDataSet Key = iota + 1
PreviousRulesErrored
)

type DataSet interface {
Expand All @@ -19,17 +20,73 @@ type DataSet interface {
Data() any
}

type Context struct {
context.Context
ds DataSet
}

func NewContext(ctx context.Context) *Context {
return &Context{Context: ctx}
}

func (c *Context) Value(key any) any {
if key == KeyDataSet {
return c.ds
}

return c.Context.Value(key)
}

func (c *Context) withDataSet(ds DataSet) *Context {
cc := *c
cc.ds = ds

return &cc
}

func (c *Context) dataSet() (DataSet, bool) {
return c.ds, c.ds != nil
}

func DataSetFromContext[T DataSet](ctx *Context) (T, bool) {
if ds, ok := ctx.dataSet(); ok {
if dsT, ok2 := ds.(T); ok2 {
return dsT, true
}
}
var v T

return v, false
}

// todo: write funcs if context.Context interface

func withDataSet(ctx context.Context, ds DataSet) context.Context {
return context.WithValue(ctx, KeyDataSet, ds)
return NewContext(ctx).withDataSet(ds)
//return context.WithValue(ctx, KeyDataSet, ds)
}

func extractDataSet(ctx context.Context) (DataSet, bool) {
func ExtractDataSet[T DataSet](ctx context.Context) (T, bool) {
var v T
if ctx == nil {
return nil, false
return v, false
}
if ds, ok := ctx.Value(KeyDataSet).(DataSet); ok {
return ds, true

ds, ok := ctx.Value(KeyDataSet).(T)
if !ok {
return v, false
}

return nil, false
return ds, true
}

//func withPreviousRulesErrored(ctx context.Context) context.Context {
// return context.WithValue(ctx, PreviousRulesErrored, true)
//}

func previousRulesErrored(ctx context.Context) bool {
if y, ok := ctx.Value(PreviousRulesErrored).(bool); ok {
return y
}
return false
}
Loading

0 comments on commit 7aa0672

Please sign in to comment.