refactor: semantic move 'builtin' into 'validator'
This commit is contained in:
parent
defa2c3645
commit
de547576c9
|
@ -96,9 +96,9 @@ func main() {
|
||||||
builder := &aicra.Builder{}
|
builder := &aicra.Builder{}
|
||||||
|
|
||||||
// add custom type validators
|
// add custom type validators
|
||||||
builder.Validate(builtin.BoolDataType{})
|
builder.Validate(validator.BoolDataType{})
|
||||||
builder.Validate(builtin.UintDataType{})
|
builder.Validate(validator.UintDataType{})
|
||||||
builder.Validate(builtin.StringDataType{})
|
builder.Validate(validator.StringDataType{})
|
||||||
|
|
||||||
// load your configuration
|
// load your configuration
|
||||||
config, err := os.Open("api.json")
|
config, err := os.Open("api.json")
|
||||||
|
|
|
@ -8,26 +8,26 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/api"
|
"github.com/xdrm-io/aicra/api"
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addBuiltinTypes(b *Builder) error {
|
func addBuiltinTypes(b *Builder) error {
|
||||||
if err := b.Validate(builtin.AnyDataType{}); err != nil {
|
if err := b.Validate(validator.AnyType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.BoolDataType{}); err != nil {
|
if err := b.Validate(validator.BoolType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.FloatDataType{}); err != nil {
|
if err := b.Validate(validator.FloatType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.IntDataType{}); err != nil {
|
if err := b.Validate(validator.IntType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.StringDataType{}); err != nil {
|
if err := b.Validate(validator.StringType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.UintDataType{}); err != nil {
|
if err := b.Validate(validator.UintType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -35,7 +35,7 @@ func addBuiltinTypes(b *Builder) error {
|
||||||
|
|
||||||
func TestAddType(t *testing.T) {
|
func TestAddType(t *testing.T) {
|
||||||
builder := &Builder{}
|
builder := &Builder{}
|
||||||
err := builder.Validate(builtin.BoolDataType{})
|
err := builder.Validate(validator.BoolType{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func TestAddType(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
err = builder.Validate(builtin.FloatDataType{})
|
err = builder.Validate(validator.FloatType{})
|
||||||
if err != errLateType {
|
if err != errLateType {
|
||||||
t.Fatalf("expected <%v> got <%v>", errLateType, err)
|
t.Fatalf("expected <%v> got <%v>", errLateType, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,26 +12,26 @@ import (
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra"
|
"github.com/xdrm-io/aicra"
|
||||||
"github.com/xdrm-io/aicra/api"
|
"github.com/xdrm-io/aicra/api"
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addBuiltinTypes(b *aicra.Builder) error {
|
func addBuiltinTypes(b *aicra.Builder) error {
|
||||||
if err := b.Validate(builtin.AnyDataType{}); err != nil {
|
if err := b.Validate(validator.AnyType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.BoolDataType{}); err != nil {
|
if err := b.Validate(validator.BoolType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.FloatDataType{}); err != nil {
|
if err := b.Validate(validator.FloatType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.IntDataType{}); err != nil {
|
if err := b.Validate(validator.IntType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.StringDataType{}); err != nil {
|
if err := b.Validate(validator.StringType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := b.Validate(builtin.UintDataType{}); err != nil {
|
if err := b.Validate(validator.UintType{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLegalServiceName(t *testing.T) {
|
func TestLegalServiceName(t *testing.T) {
|
||||||
|
@ -239,7 +239,7 @@ func TestParamEmptyRenameNoRename(t *testing.T) {
|
||||||
}
|
}
|
||||||
]`)
|
]`)
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.AnyDataType{})
|
srv.Validators = append(srv.Validators, validator.AnyType{})
|
||||||
err := srv.Parse(r)
|
err := srv.Parse(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: '%s'", err)
|
t.Errorf("unexpected error: '%s'", err)
|
||||||
|
@ -275,8 +275,8 @@ func TestOptionalParam(t *testing.T) {
|
||||||
}
|
}
|
||||||
]`)
|
]`)
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.AnyDataType{})
|
srv.Validators = append(srv.Validators, validator.AnyType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.BoolDataType{})
|
srv.Validators = append(srv.Validators, validator.BoolType{})
|
||||||
err := srv.Parse(r)
|
err := srv.Parse(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: '%s'", err)
|
t.Errorf("unexpected error: '%s'", err)
|
||||||
|
@ -588,7 +588,7 @@ func TestParseParameters(t *testing.T) {
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.AnyDataType{})
|
srv.Validators = append(srv.Validators, validator.AnyType{})
|
||||||
err := srv.Parse(strings.NewReader(test.Raw))
|
err := srv.Parse(strings.NewReader(test.Raw))
|
||||||
|
|
||||||
if err == nil && test.Error != nil {
|
if err == nil && test.Error != nil {
|
||||||
|
@ -827,8 +827,8 @@ func TestServiceCollision(t *testing.T) {
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.StringDataType{})
|
srv.Validators = append(srv.Validators, validator.StringType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.UintDataType{})
|
srv.Validators = append(srv.Validators, validator.UintType{})
|
||||||
err := srv.Parse(strings.NewReader(test.Config))
|
err := srv.Parse(strings.NewReader(test.Config))
|
||||||
|
|
||||||
if err == nil && test.Error != nil {
|
if err == nil && test.Error != nil {
|
||||||
|
@ -997,9 +997,9 @@ func TestMatchSimple(t *testing.T) {
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.AnyDataType{})
|
srv.Validators = append(srv.Validators, validator.AnyType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.IntDataType{})
|
srv.Validators = append(srv.Validators, validator.IntType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.BoolDataType{})
|
srv.Validators = append(srv.Validators, validator.BoolType{})
|
||||||
err := srv.Parse(strings.NewReader(test.Config))
|
err := srv.Parse(strings.NewReader(test.Config))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1081,9 +1081,9 @@ func TestFindPriority(t *testing.T) {
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
||||||
srv := &Server{}
|
srv := &Server{}
|
||||||
srv.Validators = append(srv.Validators, builtin.AnyDataType{})
|
srv.Validators = append(srv.Validators, validator.AnyType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.IntDataType{})
|
srv.Validators = append(srv.Validators, validator.IntType{})
|
||||||
srv.Validators = append(srv.Validators, builtin.BoolDataType{})
|
srv.Validators = append(srv.Validators, validator.BoolType{})
|
||||||
err := srv.Parse(strings.NewReader(test.Config))
|
err := srv.Parse(strings.NewReader(test.Config))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package validator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AnyType makes the "any" type available in the aicra configuration
|
||||||
|
// It considers valid any value
|
||||||
|
type AnyType struct{}
|
||||||
|
|
||||||
|
// GoType returns the interface{} type
|
||||||
|
func (AnyType) GoType() reflect.Type {
|
||||||
|
return reflect.TypeOf(interface{}(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validator that considers any value valid
|
||||||
|
func (AnyType) Validator(typename string, avail ...Type) ValidateFunc {
|
||||||
|
if typename != "any" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return func(value interface{}) (interface{}, bool) {
|
||||||
|
return value, true
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAny_AvailableTypes(t *testing.T) {
|
func TestAny_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.AnyDataType{}
|
dt := validator.AnyType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -47,7 +47,7 @@ func TestAny_AlwaysTrue(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "any"
|
const typeName = "any"
|
||||||
|
|
||||||
validator := builtin.AnyDataType{}.Validator(typeName)
|
validator := validator.AnyType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -1,23 +1,24 @@
|
||||||
package builtin
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BoolDataType is what its name tells
|
// BoolType makes the "bool" type available in the aicra configuration
|
||||||
type BoolDataType struct{}
|
// It considers valid:
|
||||||
|
// - booleans
|
||||||
|
// - strings containing "true" or "false"
|
||||||
|
// - []byte containing "true" or "false"
|
||||||
|
type BoolType struct{}
|
||||||
|
|
||||||
// GoType returns the type of data
|
// GoType returns the `bool` type
|
||||||
func (BoolDataType) GoType() reflect.Type {
|
func (BoolType) GoType() reflect.Type {
|
||||||
return reflect.TypeOf(true)
|
return reflect.TypeOf(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns the validator
|
// Validator for bool values
|
||||||
func (BoolDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
func (BoolType) Validator(typename string, avail ...Type) ValidateFunc {
|
||||||
// nothing if type not handled
|
if typename != "bool" {
|
||||||
if typeName != "bool" {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBool_AvailableTypes(t *testing.T) {
|
func TestBool_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.BoolDataType{}
|
dt := validator.BoolType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -49,7 +49,7 @@ func TestBool_Values(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "bool"
|
const typeName = "bool"
|
||||||
|
|
||||||
validator := builtin.BoolDataType{}.Validator(typeName)
|
validator := validator.BoolType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -1,26 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AnyDataType is what its name tells
|
|
||||||
type AnyDataType struct{}
|
|
||||||
|
|
||||||
// GoType returns the type of data
|
|
||||||
func (AnyDataType) GoType() reflect.Type {
|
|
||||||
return reflect.TypeOf(interface{}(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validator returns the validator
|
|
||||||
func (AnyDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
|
||||||
// nothing if type not handled
|
|
||||||
if typeName != "any" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return func(value interface{}) (interface{}, bool) {
|
|
||||||
return value, true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +1,27 @@
|
||||||
package builtin
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FloatDataType is what its name tells
|
// FloatType makes the "float" (or "float64") type available in the aicra configuration
|
||||||
type FloatDataType struct{}
|
// It considers valid:
|
||||||
|
// - float64
|
||||||
|
// - int (since it does not overflow)
|
||||||
|
// - uint (since it does not overflow)
|
||||||
|
// - strings containing json-compatible floats
|
||||||
|
// - []byte containing json-compatible floats
|
||||||
|
type FloatType struct{}
|
||||||
|
|
||||||
// GoType returns the type of data
|
// GoType returns the `float64` type
|
||||||
func (FloatDataType) GoType() reflect.Type {
|
func (FloatType) GoType() reflect.Type {
|
||||||
return reflect.TypeOf(float64(0))
|
return reflect.TypeOf(float64(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns the validator
|
// Validator for float64 values
|
||||||
func (FloatDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
func (FloatType) Validator(typename string, avail ...Type) ValidateFunc {
|
||||||
// nothing if type not handled
|
if typename != "float64" && typename != "float" {
|
||||||
if typeName != "float64" && typeName != "float" {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return func(value interface{}) (interface{}, bool) {
|
return func(value interface{}) (interface{}, bool) {
|
|
@ -1,17 +1,17 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFloat64_AvailableTypes(t *testing.T) {
|
func TestFloat64_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.FloatDataType{}
|
dt := validator.FloatType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -56,7 +56,7 @@ func TestFloat64_Values(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "float"
|
const typeName = "float"
|
||||||
|
|
||||||
validator := builtin.FloatDataType{}.Validator(typeName)
|
validator := validator.FloatType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -1,25 +1,29 @@
|
||||||
package builtin
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IntDataType is what its name tells
|
// IntType makes the "int" type available in the aicra configuration
|
||||||
type IntDataType struct{}
|
// It considers valid:
|
||||||
|
// - int
|
||||||
|
// - float64 (since it does not overflow)
|
||||||
|
// - uint (since it does not overflow)
|
||||||
|
// - strings containing json-compatible integers
|
||||||
|
// - []byte containing json-compatible integers
|
||||||
|
type IntType struct{}
|
||||||
|
|
||||||
// GoType returns the type of data
|
// GoType returns the `int` type
|
||||||
func (IntDataType) GoType() reflect.Type {
|
func (IntType) GoType() reflect.Type {
|
||||||
return reflect.TypeOf(int(0))
|
return reflect.TypeOf(int(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns the validator
|
// Validator for int values
|
||||||
func (IntDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
func (IntType) Validator(typename string, avail ...Type) ValidateFunc {
|
||||||
// nothing if type not handled
|
// nothing if type not handled
|
||||||
if typeName != "int" {
|
if typename != "int" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInt_AvailableTypes(t *testing.T) {
|
func TestInt_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.IntDataType{}
|
dt := validator.IntType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -50,7 +50,7 @@ func TestInt_Values(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "int"
|
const typeName = "int"
|
||||||
|
|
||||||
validator := builtin.IntDataType{}.Validator(typeName)
|
validator := validator.IntType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -1,32 +1,37 @@
|
||||||
package builtin
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var fixedLengthRegex = regexp.MustCompile(`^string\((\d+)\)$`)
|
var (
|
||||||
var variableLengthRegex = regexp.MustCompile(`^string\((\d+), ?(\d+)\)$`)
|
fixedLengthRegex = regexp.MustCompile(`^string\((\d+)\)$`)
|
||||||
|
variableLengthRegex = regexp.MustCompile(`^string\((\d+), ?(\d+)\)$`)
|
||||||
|
)
|
||||||
|
|
||||||
// StringDataType is what its name tells
|
// StringType makes the types beloz available in the aicra configuration:
|
||||||
type StringDataType struct{}
|
// - "string" considers any string valid
|
||||||
|
// - "string(n)" considers any string with an exact size of `n` valid
|
||||||
|
// - "string(a,b)" considers any string with a size between `a` and `b` valid
|
||||||
|
// > for the last one, `a` and `b` are included in the valid sizes
|
||||||
|
type StringType struct{}
|
||||||
|
|
||||||
// GoType returns the type of data
|
// GoType returns the `string` type
|
||||||
func (StringDataType) GoType() reflect.Type {
|
func (StringType) GoType() reflect.Type {
|
||||||
return reflect.TypeOf(string(""))
|
return reflect.TypeOf(string(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns the validator.
|
// Validator for strings with any/fixed/bound sizes
|
||||||
// availables type names are : `string`, `string(length)` and `string(minLength, maxLength)`.
|
func (s StringType) Validator(typename string, avail ...Type) ValidateFunc {
|
||||||
func (s StringDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
var (
|
||||||
simple := typeName == "string"
|
simple = (typename == "string")
|
||||||
fixedLengthMatches := fixedLengthRegex.FindStringSubmatch(typeName)
|
fixedLengthMatches = fixedLengthRegex.FindStringSubmatch(typename)
|
||||||
variableLengthMatches := variableLengthRegex.FindStringSubmatch(typeName)
|
variableLengthMatches = variableLengthRegex.FindStringSubmatch(typename)
|
||||||
|
)
|
||||||
|
|
||||||
// nothing if type not handled
|
// ignore unknown typename
|
||||||
if !simple && fixedLengthMatches == nil && variableLengthMatches == nil {
|
if !simple && fixedLengthMatches == nil && variableLengthMatches == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -40,7 +45,7 @@ func (s StringDataType) Validator(typeName string, registry ...validator.Type) v
|
||||||
if fixedLengthMatches != nil {
|
if fixedLengthMatches != nil {
|
||||||
exLen, ok := s.getFixedLength(fixedLengthMatches)
|
exLen, ok := s.getFixedLength(fixedLengthMatches)
|
||||||
if !ok {
|
if !ok {
|
||||||
mustFail = true
|
return nil
|
||||||
}
|
}
|
||||||
min = exLen
|
min = exLen
|
||||||
max = exLen
|
max = exLen
|
||||||
|
@ -49,7 +54,7 @@ func (s StringDataType) Validator(typeName string, registry ...validator.Type) v
|
||||||
} else if variableLengthMatches != nil {
|
} else if variableLengthMatches != nil {
|
||||||
exMin, exMax, ok := s.getVariableLength(variableLengthMatches)
|
exMin, exMax, ok := s.getVariableLength(variableLengthMatches)
|
||||||
if !ok {
|
if !ok {
|
||||||
mustFail = true
|
return nil
|
||||||
}
|
}
|
||||||
min = exMin
|
min = exMin
|
||||||
max = exMax
|
max = exMax
|
||||||
|
@ -84,7 +89,7 @@ func (s StringDataType) Validator(typeName string, registry ...validator.Type) v
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFixedLength returns the fixed length from regex matches and a success state.
|
// getFixedLength returns the fixed length from regex matches and a success state.
|
||||||
func (StringDataType) getFixedLength(regexMatches []string) (int, bool) {
|
func (StringType) getFixedLength(regexMatches []string) (int, bool) {
|
||||||
// incoherence error
|
// incoherence error
|
||||||
if regexMatches == nil || len(regexMatches) < 2 {
|
if regexMatches == nil || len(regexMatches) < 2 {
|
||||||
return 0, false
|
return 0, false
|
||||||
|
@ -100,7 +105,7 @@ func (StringDataType) getFixedLength(regexMatches []string) (int, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVariableLength returns the length min and max from regex matches and a success state.
|
// getVariableLength returns the length min and max from regex matches and a success state.
|
||||||
func (StringDataType) getVariableLength(regexMatches []string) (int, int, bool) {
|
func (StringType) getVariableLength(regexMatches []string) (int, int, bool) {
|
||||||
// incoherence error
|
// incoherence error
|
||||||
if regexMatches == nil || len(regexMatches) < 3 {
|
if regexMatches == nil || len(regexMatches) < 3 {
|
||||||
return 0, 0, false
|
return 0, 0, false
|
|
@ -1,16 +1,16 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestString_AvailableTypes(t *testing.T) {
|
func TestString_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.StringDataType{}
|
dt := validator.StringType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -75,7 +75,7 @@ func TestString_AnyLength(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "string"
|
const typeName = "string"
|
||||||
|
|
||||||
validator := builtin.StringDataType{}.Validator(typeName)
|
validator := validator.StringType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
|
@ -133,7 +133,7 @@ func TestString_FixedLength(t *testing.T) {
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||||
validator := builtin.StringDataType{}.Validator(test.Type)
|
validator := validator.StringType{}.Validator(test.Type)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", test.Type)
|
t.Errorf("expect %q to be handled", test.Type)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
|
@ -194,7 +194,7 @@ func TestString_VariableLength(t *testing.T) {
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||||
validator := builtin.StringDataType{}.Validator(test.Type)
|
validator := validator.StringType{}.Validator(test.Type)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", test.Type)
|
t.Errorf("expect %q to be handled", test.Type)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -1,25 +1,28 @@
|
||||||
package builtin
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UintDataType is what its name tells
|
// UintType makes the "uint" type available in the aicra configuration
|
||||||
type UintDataType struct{}
|
// It considers valid:
|
||||||
|
// - uint
|
||||||
|
// - int (since it does not overflow)
|
||||||
|
// - float64 (since it does not overflow)
|
||||||
|
// - strings containing json-compatible integers
|
||||||
|
// - []byte containing json-compatible integers
|
||||||
|
type UintType struct{}
|
||||||
|
|
||||||
// GoType returns the type of data
|
// GoType returns the `uint` type
|
||||||
func (UintDataType) GoType() reflect.Type {
|
func (UintType) GoType() reflect.Type {
|
||||||
return reflect.TypeOf(uint(0))
|
return reflect.TypeOf(uint(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns the validator
|
// Validator for uint values
|
||||||
func (UintDataType) Validator(typeName string, registry ...validator.Type) validator.ValidateFunc {
|
func (UintType) Validator(other string, avail ...Type) ValidateFunc {
|
||||||
// nothing if type not handled
|
if other != "uint" {
|
||||||
if typeName != "uint" {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package builtin_test
|
package validator_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xdrm-io/aicra/validator/builtin"
|
"github.com/xdrm-io/aicra/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUint_AvailableTypes(t *testing.T) {
|
func TestUint_AvailableTypes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
dt := builtin.UintDataType{}
|
dt := validator.UintType{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -50,7 +50,7 @@ func TestUint_Values(t *testing.T) {
|
||||||
|
|
||||||
const typeName = "uint"
|
const typeName = "uint"
|
||||||
|
|
||||||
validator := builtin.UintDataType{}.Validator(typeName)
|
validator := validator.UintType{}.Validator(typeName)
|
||||||
if validator == nil {
|
if validator == nil {
|
||||||
t.Errorf("expect %q to be handled", typeName)
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
t.Fail()
|
t.Fail()
|
|
@ -37,17 +37,17 @@ type Type interface {
|
||||||
// - `VarcharType.Validator("varchar(1,3)")` validates any string
|
// - `VarcharType.Validator("varchar(1,3)")` validates any string
|
||||||
// with a length between 1 and 3
|
// with a length between 1 and 3
|
||||||
//
|
//
|
||||||
// The `registry` argument represents all other available Types. It allows a
|
// The `avail` argument represents all other available Types. It allows a
|
||||||
// Type to use other available Types internally.
|
// Type to use other available Types internally.
|
||||||
//
|
//
|
||||||
// recursive example: slices
|
// recursive example: slices
|
||||||
// - `SliceType.Validator("[]int", reg...)` validates a slice containing
|
// - `SliceType.Validator("[]int", avail...)` validates a slice containing
|
||||||
// values that are valide to the `IntType`
|
// values that are valide to the `IntType`
|
||||||
// - `SliceType.Validator("[]varchar", reg...)` validates a slice containing
|
// - `SliceType.Validator("[]varchar", avail...)` validates a slice containing
|
||||||
// values that are valid to the `VarcharType`
|
// values that are valid to the `VarcharType`
|
||||||
//
|
//
|
||||||
// and so on.. this works for maps, structs, etc
|
// and so on.. this works for maps, structs, etc
|
||||||
Validator(typename string, registry ...Type) ValidateFunc
|
Validator(typename string, avail ...Type) ValidateFunc
|
||||||
|
|
||||||
// GoType must return the go type associated with the output type of ValidateFunc.
|
// GoType must return the go type associated with the output type of ValidateFunc.
|
||||||
// It is used to define handlers' signature from the configuration file.
|
// It is used to define handlers' signature from the configuration file.
|
||||||
|
|
Loading…
Reference in New Issue