Skip to content

Commit

Permalink
add default
Browse files Browse the repository at this point in the history
  • Loading branch information
aacebo committed Apr 4, 2024
1 parent c72dfa0 commit d9e0e9f
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
| Name | Description | Status |
|---------------|-------------------------------------------------------|--------|
| required | not nil or zero value ||
| default | default value | |
| default | default value | |
| enum | one of a set of options ||

### String
Expand Down
3 changes: 2 additions & 1 deletion rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Rule interface {
Validate(
schema map[string]string,
parent reflect.Value,
// _type reflect.Type,
value reflect.Value,
) []error
) (reflect.Value, []error)
}
70 changes: 70 additions & 0 deletions rules/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package rules

import (
"errors"
"reflect"
"strconv"
)

type Default struct{}

func (self Default) Select(schema map[string]string, parent reflect.Value, value reflect.Value) bool {
return true
}

func (self Default) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
config, ok := schema["default"]

if !ok || config == "" {
errs = append(errs, errors.New("config is required"))
return value, errs
}

if value.Kind() == reflect.Pointer && value.IsZero() {
t := value.Type()
ptr := reflect.New(t.Elem())

if t.Elem().ConvertibleTo(reflect.TypeFor[int]()) {
v, err := strconv.ParseInt(config, 10, 64)

if err != nil {
errs = append(errs, errors.New("config must be an int"))
}

ptr.Elem().Set(reflect.ValueOf(v).Convert(t.Elem()))
return ptr, errs
}

if t.Elem().ConvertibleTo(reflect.TypeFor[float64]()) {
v, err := strconv.ParseFloat(config, 64)

if err != nil {
errs = append(errs, errors.New("config must be an float"))
}

ptr.Elem().Set(reflect.ValueOf(v).Convert(t.Elem()))
return ptr, errs
}

if t.Elem().Kind() == reflect.Bool {
v, err := strconv.ParseBool(config)

if err != nil {
errs = append(errs, errors.New("config must be a bool"))
}

ptr.Elem().SetBool(v)
return ptr, errs
}

if t.Elem().Kind() == reflect.String {
ptr.Elem().SetString(config)
return ptr, errs
}

errs = append(errs, errors.New("default can only be used on primitive types"))
}

return value, errs
}
125 changes: 125 additions & 0 deletions rules/default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package rules_test

import (
"testing"

"github.com/aacebo/owl"
)

func Test_Default(t *testing.T) {
t.Run("should error on no config", func(t *testing.T) {
errs := owl.Validate(struct {
A *string `json:"a" owl:"default"`
}{})

if len(errs) == 0 {
t.Error("should have error")
}
})

t.Run("should error on type mismatch", func(t *testing.T) {
errs := owl.Validate(struct {
A *int `json:"a" owl:"default=abc"`
}{})

if len(errs) == 0 {
t.Error("should have error")
}
})

t.Run("should succeed with int", func(t *testing.T) {
v := struct {
A *int `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != 123 {
t.Error("should set default value")
}
})

t.Run("should succeed with int64", func(t *testing.T) {
v := struct {
A *int64 `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != 123 {
t.Error("should set default value")
}
})

t.Run("should succeed with float32", func(t *testing.T) {
v := struct {
A *float32 `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != 123 {
t.Error("should set default value")
}
})

t.Run("should succeed with float64", func(t *testing.T) {
v := struct {
A *float64 `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != 123 {
t.Error("should set default value")
}
})

t.Run("should succeed with uint", func(t *testing.T) {
v := struct {
A *uint `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != 123 {
t.Error("should set default value")
}
})

t.Run("should succeed with string", func(t *testing.T) {
v := struct {
A *string `json:"a" owl:"default=123"`
}{}

errs := owl.Validate(&v)

if len(errs) > 0 {
t.Error(errs)
}

if v.A == nil || *v.A != "123" {
t.Error("should set default value")
}
})
}
8 changes: 4 additions & 4 deletions rules/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ func (self Format) Select(schema map[string]string, parent reflect.Value, value
return value.Kind() == reflect.String
}

func (self Format) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) []error {
func (self Format) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
config, ok := schema["format"]

if !ok {
errs = append(errs, errors.New("empty config"))
return errs
return value, errs
}

if !self.HasFormat(config) {
Expand All @@ -30,12 +30,12 @@ func (self Format) Validate(schema map[string]string, parent reflect.Value, valu
config,
)))

return errs
return value, errs
}

if err := self.Format(config, value.String()); err != nil {
errs = append(errs, err)
}

return errs
return value, errs
}
20 changes: 10 additions & 10 deletions rules/max.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ func (self Max) Select(schema map[string]string, parent reflect.Value, value ref
return value.CanFloat() || value.CanConvert(floatType) || value.Kind() == reflect.String
}

func (self Max) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) []error {
func (self Max) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) (reflect.Value, []error) {
errs := []error{}

if _, ok := schema["max"]; !ok {
errs = append(errs, errors.New("must be greater than or equal to 0"))
return errs
return value, errs
}

if value.Kind() == reflect.String {
Expand All @@ -28,18 +28,18 @@ func (self Max) Validate(schema map[string]string, parent reflect.Value, value r
return self.validateNumber(schema, value)
}

func (self Max) validateNumber(schema map[string]string, value reflect.Value) []error {
func (self Max) validateNumber(schema map[string]string, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
max, err := strconv.ParseFloat(schema["max"], 64)

if err != nil {
errs = append(errs, err)
return errs
return value, errs
}

if max < 0 {
errs = append(errs, errors.New("must be greater than or equal to 0"))
return errs
return value, errs
}

if v, ok := schema["min"]; ok {
Expand All @@ -62,21 +62,21 @@ func (self Max) validateNumber(schema map[string]string, value reflect.Value) []
)))
}

return errs
return value, errs
}

func (self Max) validateString(schema map[string]string, value reflect.Value) []error {
func (self Max) validateString(schema map[string]string, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
max, err := strconv.ParseInt(schema["max"], 10, 64)

if err != nil {
errs = append(errs, err)
return errs
return value, errs
}

if max < 0 {
errs = append(errs, errors.New("config must be greater than or equal to 0"))
return errs
return value, errs
}

if v, ok := schema["min"]; ok {
Expand All @@ -96,5 +96,5 @@ func (self Max) validateString(schema map[string]string, value reflect.Value) []
)))
}

return errs
return value, errs
}
20 changes: 10 additions & 10 deletions rules/min.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ func (self Min) Select(schema map[string]string, parent reflect.Value, value ref
return value.CanFloat() || value.CanConvert(floatType) || value.Kind() == reflect.String
}

func (self Min) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) []error {
func (self Min) Validate(schema map[string]string, parent reflect.Value, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
config, ok := schema["min"]

if !ok {
errs = append(errs, errors.New("must be greater than or equal to 0"))
return errs
return value, errs
}

if value.Kind() == reflect.String {
Expand All @@ -31,18 +31,18 @@ func (self Min) Validate(schema map[string]string, parent reflect.Value, value r
return self.validateNumber(config, value)
}

func (self Min) validateNumber(config string, value reflect.Value) []error {
func (self Min) validateNumber(config string, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
min, err := strconv.ParseFloat(config, 64)

if err != nil {
errs = append(errs, err)
return errs
return value, errs
}

if min < 0 {
errs = append(errs, errors.New("must be greater than or equal to 0"))
return errs
return value, errs
}

if value.Kind() != reflect.Float64 && value.CanConvert(floatType) {
Expand All @@ -57,21 +57,21 @@ func (self Min) validateNumber(config string, value reflect.Value) []error {
)))
}

return errs
return value, errs
}

func (self Min) validateString(config string, value reflect.Value) []error {
func (self Min) validateString(config string, value reflect.Value) (reflect.Value, []error) {
errs := []error{}
min, err := strconv.ParseInt(config, 10, 64)

if err != nil {
errs = append(errs, err)
return errs
return value, errs
}

if min < 0 {
errs = append(errs, errors.New("config must be greater than or equal to 0"))
return errs
return value, errs
}

if min > int64(value.Len()) {
Expand All @@ -83,5 +83,5 @@ func (self Min) validateString(config string, value reflect.Value) []error {
)))
}

return errs
return value, errs
}
Loading

0 comments on commit d9e0e9f

Please sign in to comment.