Simplify built-in database field types
This commit is contained in:
parent
e52f0d3243
commit
26b138b9b0
14 changed files with 329 additions and 236 deletions
13
glide.lock
generated
13
glide.lock
generated
|
@ -1,8 +1,8 @@
|
|||
hash: 7227d566f4817cbb8b1eb609aeb5928f1bc420f763fbf387d5effcfa2e8e6509
|
||||
updated: 2018-09-11T13:25:49.903968+01:00
|
||||
hash: bb2fdd0ae1ce4cc20cd04c5fb3720722f46051ec869b6e61e21d9b8e7f020081
|
||||
updated: 2018-10-17T23:52:04.807878+01:00
|
||||
imports:
|
||||
- name: cloud.google.com/go
|
||||
version: c728a003b238b26cef9ab6753a5dc424b331c3ad
|
||||
version: dfffe386c33fb24c34ee501e5723df5b97b98514
|
||||
subpackages:
|
||||
- compute/metadata
|
||||
- iam
|
||||
|
@ -39,7 +39,7 @@ imports:
|
|||
- name: github.com/armon/go-metrics
|
||||
version: 3c58d8115a78a6879e5df75ae900846768d36895
|
||||
- name: github.com/aws/aws-sdk-go
|
||||
version: 71a2a92b0063297b055b6f5a014d441c142da2ce
|
||||
version: 66832f7f150914a46ffbfc03210f3b9cb0e4c005
|
||||
subpackages:
|
||||
- aws
|
||||
- aws/awserr
|
||||
|
@ -58,6 +58,7 @@ imports:
|
|||
- aws/request
|
||||
- aws/session
|
||||
- aws/signer/v4
|
||||
- internal/s3err
|
||||
- internal/sdkio
|
||||
- internal/sdkrand
|
||||
- internal/sdkuri
|
||||
|
@ -139,6 +140,8 @@ imports:
|
|||
version: 80517062f582ea3340cd4baf70e86d539ae7d84d
|
||||
subpackages:
|
||||
- internal/load
|
||||
- name: github.com/konsorten/go-windows-terminal-sequences
|
||||
version: 5c8c8bd35d3832f5d134ae1e1e375b69a4d25242
|
||||
- name: github.com/kr/text
|
||||
version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f
|
||||
- name: github.com/mattn/go-colorable
|
||||
|
@ -175,7 +178,7 @@ imports:
|
|||
subpackages:
|
||||
- diffmatchpatch
|
||||
- name: github.com/sirupsen/logrus
|
||||
version: 3e01752db0189b9157070a0e1668a620f9a85da2
|
||||
version: ad15b42461921f1fb3529b058c6786c6a45d5162
|
||||
- name: github.com/spf13/cobra
|
||||
version: ef82de70bb3f60c65fb8eebacbb2d122ef517385
|
||||
- name: github.com/spf13/pflag
|
||||
|
|
|
@ -33,7 +33,7 @@ import:
|
|||
subpackages:
|
||||
- diffmatchpatch
|
||||
- package: github.com/sirupsen/logrus
|
||||
version: ^1.0.6
|
||||
version: ^1.1.1
|
||||
- package: github.com/spf13/cobra
|
||||
version: ^0.0.3
|
||||
- package: github.com/ugorji/go
|
||||
|
|
15
sql/funcs.go
15
sql/funcs.go
|
@ -84,13 +84,11 @@ var funcs = map[string]map[int]interface{}{
|
|||
"union": {-1: nil},
|
||||
|
||||
// Count implementation
|
||||
|
||||
"count": {1: nil},
|
||||
"count.if": {2: nil},
|
||||
"count.not": {2: nil},
|
||||
|
||||
// Purge implementation
|
||||
|
||||
"purge": {1: nil},
|
||||
"purge.if": {2: nil},
|
||||
"purge.not": {2: nil},
|
||||
|
@ -217,6 +215,19 @@ var funcs = map[string]map[int]interface{}{
|
|||
"scrypt.compare": {2: nil},
|
||||
"scrypt.generate": {1: nil},
|
||||
|
||||
// Check implementation
|
||||
"is.alpha": {1: nil},
|
||||
"is.alphanum": {1: nil},
|
||||
"is.ascii": {1: nil},
|
||||
"is.domain": {1: nil},
|
||||
"is.email": {1: nil},
|
||||
"is.hexadecimal": {1: nil},
|
||||
"is.latitude": {1: nil},
|
||||
"is.longitude": {1: nil},
|
||||
"is.numeric": {1: nil},
|
||||
"is.semver": {1: nil},
|
||||
"is.uuid": {1: nil},
|
||||
|
||||
// Random implementation
|
||||
"rand": {0: nil},
|
||||
"guid": {0: nil},
|
||||
|
|
|
@ -34,11 +34,9 @@ const (
|
|||
var (
|
||||
allowedTypes = []string{
|
||||
"array", "boolean", "circle",
|
||||
"datetime", "domain", "double",
|
||||
"email", "latitude", "longitude",
|
||||
"number", "object", "password",
|
||||
"phone", "point", "polygon",
|
||||
"record", "string", "uuid",
|
||||
"datetime", "number", "object",
|
||||
"point", "polygon", "record",
|
||||
"string", "uuid",
|
||||
}
|
||||
|
||||
allowedAlgorithms = []string{
|
||||
|
|
|
@ -2709,29 +2709,11 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE`,
|
||||
err: "Found `` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`",
|
||||
err: "Found `` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE something`,
|
||||
err: "Found `something` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE email`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Name: &Ident{"temp"},
|
||||
What: Tables{&Table{"person"}},
|
||||
Type: "email",
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE phone`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Name: &Ident{"temp"},
|
||||
What: Tables{&Table{"person"}},
|
||||
Type: "phone",
|
||||
}}},
|
||||
err: "Found `something` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE array`,
|
||||
|
@ -2769,15 +2751,6 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
Type: "number",
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE double`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Name: &Ident{"temp"},
|
||||
What: Tables{&Table{"person"}},
|
||||
Type: "double",
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE record`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
|
|
|
@ -127,6 +127,8 @@ func toQuote(s string) bool {
|
|||
continue
|
||||
case c == '.', c == '*':
|
||||
continue
|
||||
case c == '_':
|
||||
continue
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chck
|
||||
|
||||
func IsBase64(s string) bool {
|
||||
return rBase64.MatchString(s)
|
||||
}
|
||||
|
||||
func IsDomain(s string) bool {
|
||||
return rDomain.MatchString(s)
|
||||
}
|
||||
|
||||
func IsEmail(s string) bool {
|
||||
return rEmail.MatchString(s)
|
||||
}
|
||||
|
||||
func IsLatitude(s string) bool {
|
||||
return rLatitude.MatchString(s)
|
||||
}
|
||||
|
||||
func IsLongitude(s string) bool {
|
||||
return rLongitude.MatchString(s)
|
||||
}
|
||||
|
||||
func IsPhone(s string) bool {
|
||||
return rPhone.MatchString(s)
|
||||
}
|
||||
|
||||
func IsUUID(s string) bool {
|
||||
return rUUID.MatchString(s)
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chck
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
sBase64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
|
||||
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
|
||||
sEmail string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
||||
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
||||
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
||||
sPhone string = `^[\s\d\+\-\(\)]+$`
|
||||
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
)
|
||||
|
||||
var (
|
||||
rBase64 = regexp.MustCompile(sBase64)
|
||||
rDomain = regexp.MustCompile(sDomain)
|
||||
rEmail = regexp.MustCompile(sEmail)
|
||||
rLatitude = regexp.MustCompile(sLatitude)
|
||||
rLongitude = regexp.MustCompile(sLongitude)
|
||||
rPhone = regexp.MustCompile(sPhone)
|
||||
rUUID = regexp.MustCompile(sUUID)
|
||||
)
|
|
@ -20,7 +20,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
"github.com/abcum/surreal/util/chck"
|
||||
)
|
||||
|
||||
func toNumber(str string) (float64, error) {
|
||||
|
@ -30,15 +29,6 @@ func toNumber(str string) (float64, error) {
|
|||
err = fmt.Errorf("Expected a number, but found '%v'", str)
|
||||
|
||||
}
|
||||
return float64(int64(val)), err
|
||||
}
|
||||
|
||||
func toDouble(str string) (float64, error) {
|
||||
val, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
val = 0.0
|
||||
err = fmt.Errorf("Expected a number, but found '%v'", str)
|
||||
}
|
||||
return float64(val), err
|
||||
}
|
||||
|
||||
|
@ -117,63 +107,23 @@ func ConvertTo(t, k string, obj interface{}) (val interface{}, err error) {
|
|||
switch t {
|
||||
default:
|
||||
return obj, nil
|
||||
case "uuid":
|
||||
return ConvertToUuid(obj)
|
||||
case "email":
|
||||
return ConvertToEmail(obj)
|
||||
case "phone":
|
||||
return ConvertToPhone(obj)
|
||||
case "array":
|
||||
return ConvertToArray(obj)
|
||||
case "object":
|
||||
return ConvertToObject(obj)
|
||||
case "domain":
|
||||
return ConvertToDomain(obj)
|
||||
case "base64":
|
||||
return ConvertToBase64(obj)
|
||||
case "string":
|
||||
return ConvertToString(obj)
|
||||
case "number":
|
||||
return ConvertToNumber(obj)
|
||||
case "double":
|
||||
return ConvertToDouble(obj)
|
||||
case "boolean":
|
||||
return ConvertToBoolean(obj)
|
||||
case "datetime":
|
||||
return ConvertToDatetime(obj)
|
||||
case "latitude":
|
||||
return ConvertToLatitude(obj)
|
||||
case "longitude":
|
||||
return ConvertToLongitude(obj)
|
||||
case "record":
|
||||
return ConvertToRecord(obj, k)
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertToUuid(obj interface{}) (val string, err error) {
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !chck.IsUUID(val) {
|
||||
err = fmt.Errorf("Expected a UUID, but found '%v'", obj)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertToEmail(obj interface{}) (val string, err error) {
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !chck.IsEmail(val) {
|
||||
err = fmt.Errorf("Expected an email address, but found '%v'", obj)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertToPhone(obj interface{}) (val string, err error) {
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !chck.IsPhone(val) {
|
||||
err = fmt.Errorf("Expected a phone number, but found '%v'", obj)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertToArray(obj interface{}) (val []interface{}, err error) {
|
||||
if now, ok := obj.([]interface{}); ok {
|
||||
val = now
|
||||
|
@ -192,22 +142,6 @@ func ConvertToObject(obj interface{}) (val map[string]interface{}, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func ConvertToDomain(obj interface{}) (val string, err error) {
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !chck.IsDomain(val) {
|
||||
err = fmt.Errorf("Expected a domain name, but found '%v'", obj)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertToBase64(obj interface{}) (val string, err error) {
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !chck.IsBase64(val) {
|
||||
err = fmt.Errorf("Expected base64 data, but found '%v'", obj)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertToString(obj interface{}) (val string, err error) {
|
||||
switch now := obj.(type) {
|
||||
case string:
|
||||
|
@ -232,19 +166,6 @@ func ConvertToNumber(obj interface{}) (val float64, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
func ConvertToDouble(obj interface{}) (val float64, err error) {
|
||||
switch now := obj.(type) {
|
||||
case int64:
|
||||
return float64(now), err
|
||||
case float64:
|
||||
return float64(now), err
|
||||
case string:
|
||||
return toDouble(now)
|
||||
default:
|
||||
return toDouble(fmt.Sprintf("%v", obj))
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertToBoolean(obj interface{}) (val bool, err error) {
|
||||
switch now := obj.(type) {
|
||||
case int64:
|
||||
|
@ -270,22 +191,6 @@ func ConvertToDatetime(obj interface{}) (val time.Time, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func ConvertToLatitude(obj interface{}) (val float64, err error) {
|
||||
str := fmt.Sprintf("%v", obj)
|
||||
if !chck.IsLatitude(str) {
|
||||
err = fmt.Errorf("Expected a latitude value, but found '%v'", obj)
|
||||
}
|
||||
return toNumber(str)
|
||||
}
|
||||
|
||||
func ConvertToLongitude(obj interface{}) (val float64, err error) {
|
||||
str := fmt.Sprintf("%v", obj)
|
||||
if !chck.IsLongitude(str) {
|
||||
err = fmt.Errorf("Expected a longitude value, but found '%v'", obj)
|
||||
}
|
||||
return toNumber(str)
|
||||
}
|
||||
|
||||
func ConvertToRecord(obj interface{}, tb string) (val *sql.Thing, err error) {
|
||||
switch now := obj.(type) {
|
||||
case *sql.Thing:
|
||||
|
|
|
@ -17,8 +17,6 @@ package fncs
|
|||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/abcum/surreal/util/chck"
|
||||
)
|
||||
|
||||
func emailUser(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
|
@ -36,8 +34,3 @@ func emailDomain(ctx context.Context, args ...interface{}) (interface{}, error)
|
|||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func emailValid(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
return chck.IsEmail(v), nil
|
||||
}
|
||||
|
|
|
@ -47,14 +47,4 @@ func TestEmail(t *testing.T) {
|
|||
So(res, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
Convey("email.valid(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.valid", "tobie@abcum.com")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("email.valid(a) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.valid", "test")
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
@ -272,8 +272,6 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
|||
return emailUser(ctx, args...)
|
||||
case "email.domain":
|
||||
return emailDomain(ctx, args...)
|
||||
case "email.valid":
|
||||
return emailValid(ctx, args...)
|
||||
|
||||
// Bcrypt implementation
|
||||
case "bcrypt.compare":
|
||||
|
@ -287,6 +285,30 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
|||
case "scrypt.generate":
|
||||
return scryptGenerate(ctx, args...)
|
||||
|
||||
// Check implementation
|
||||
case "is.alpha":
|
||||
return isAlpha(ctx, args...)
|
||||
case "is.alphanum":
|
||||
return isAlphanum(ctx, args...)
|
||||
case "is.ascii":
|
||||
return isAscii(ctx, args...)
|
||||
case "is.domain":
|
||||
return isDomain(ctx, args...)
|
||||
case "is.email":
|
||||
return isEmail(ctx, args...)
|
||||
case "is.hexadecimal":
|
||||
return isHexadecimal(ctx, args...)
|
||||
case "is.latitude":
|
||||
return isLatitude(ctx, args...)
|
||||
case "is.longitude":
|
||||
return isLongitude(ctx, args...)
|
||||
case "is.numeric":
|
||||
return isNumeric(ctx, args...)
|
||||
case "is.semver":
|
||||
return isSemver(ctx, args...)
|
||||
case "is.uuid":
|
||||
return isUuid(ctx, args...)
|
||||
|
||||
// Rand implementation
|
||||
case "rand":
|
||||
return rand(ctx, args...)
|
||||
|
|
125
util/fncs/is.go
Normal file
125
util/fncs/is.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/mail"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
sAlpha string = "^[a-zA-Z]+$"
|
||||
sAlphanum string = "^[a-zA-Z0-9]+$"
|
||||
sAscii string = "^[\x00-\x7F]+$"
|
||||
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
|
||||
sHexadecimal string = "^[0-9a-fA-F]+$"
|
||||
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
||||
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
||||
sNumeric string = "^[0-9]+$"
|
||||
sSemver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
|
||||
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
)
|
||||
|
||||
var (
|
||||
rAlpha = regexp.MustCompile(sAlpha)
|
||||
rAlphanum = regexp.MustCompile(sAlphanum)
|
||||
rAscii = regexp.MustCompile(sAscii)
|
||||
rDomain = regexp.MustCompile(sDomain)
|
||||
rHexadecimal = regexp.MustCompile(sHexadecimal)
|
||||
rLatitude = regexp.MustCompile(sLatitude)
|
||||
rLongitude = regexp.MustCompile(sLongitude)
|
||||
rNumeric = regexp.MustCompile(sNumeric)
|
||||
rSemver = regexp.MustCompile(sSemver)
|
||||
rUUID = regexp.MustCompile(sUUID)
|
||||
)
|
||||
|
||||
func isAlpha(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rAlpha.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isAlphanum(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rAlphanum.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isAscii(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rAscii.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isDomain(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rDomain.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isEmail(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); len(val) > 0 && ok {
|
||||
pse, err := mail.ParseAddress(val)
|
||||
return err == nil && val == pse.Address, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isHexadecimal(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rHexadecimal.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isLatitude(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rLatitude.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isLongitude(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rLongitude.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isNumeric(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rNumeric.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isSemver(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rSemver.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isUuid(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureString(args[0]); ok {
|
||||
return rUUID.MatchString(val), nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
151
util/fncs/is_test.go
Normal file
151
util/fncs/is_test.go
Normal file
|
@ -0,0 +1,151 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIs(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("is.alpha(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.alpha", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.alpha", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.alpha", "aBcDe")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.alphanum(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.alphanum", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.alphanum", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.alphanum", "aB3De")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.ascii(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.ascii", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.ascii", "testing®")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.ascii", "aB3De")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.domain(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.domain", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.domain", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.domain", "abcum.com")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.email(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.email", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.email", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.email", "info@abcum.com")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.hexadecimal(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.hexadecimal", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.hexadecimal", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.hexadecimal", "00bfff")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.latitude(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.latitude", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.latitude", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.latitude", 0)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.latitude", -90)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.latitude", +90)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.latitude", "-90")
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.latitude", "+90")
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.latitude", -95)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.latitude", +95)
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
Convey("is.longitude(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.longitude", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.longitude", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.longitude", 0)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.longitude", -180)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.longitude", +180)
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.longitude", "-180")
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.longitude", "+180")
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "is.longitude", -185)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.longitude", +185)
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
Convey("is.numeric(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.numeric", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.numeric", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.numeric", "123456")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.semver(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.semver", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.semver", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.semver", "1.0.32")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("is.uuid(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "is.uuid", nil)
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.uuid", "test-©")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "is.uuid", "8ddb11e8-755f-47cf-a84f-8033d1cfa1b9")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
}
|
Loading…
Reference in a new issue