mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-27 12:21:03 +00:00
1419 lines
55 KiB
Go
1419 lines
55 KiB
Go
|
package validator
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"net/url"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"time"
|
||
|
"unicode/utf8"
|
||
|
)
|
||
|
|
||
|
// BakedInAliasValidators is a default mapping of a single validationstag that
|
||
|
// defines a common or complex set of validation(s) to simplify
|
||
|
// adding validation to structs. i.e. set key "_ageok" and the tags
|
||
|
// are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60"
|
||
|
var bakedInAliasValidators = map[string]string{
|
||
|
"iscolor": "hexcolor|rgb|rgba|hsl|hsla",
|
||
|
}
|
||
|
|
||
|
// BakedInValidators is the default map of ValidationFunc
|
||
|
// you can add, remove or even replace items to suite your needs,
|
||
|
// or even disregard and use your own map if so desired.
|
||
|
var bakedInValidators = map[string]Func{
|
||
|
"required": HasValue,
|
||
|
"len": HasLengthOf,
|
||
|
"min": HasMinOf,
|
||
|
"max": HasMaxOf,
|
||
|
"eq": IsEq,
|
||
|
"ne": IsNe,
|
||
|
"lt": IsLt,
|
||
|
"lte": IsLte,
|
||
|
"gt": IsGt,
|
||
|
"gte": IsGte,
|
||
|
"eqfield": IsEqField,
|
||
|
"eqcsfield": IsEqCrossStructField,
|
||
|
"necsfield": IsNeCrossStructField,
|
||
|
"gtcsfield": IsGtCrossStructField,
|
||
|
"gtecsfield": IsGteCrossStructField,
|
||
|
"ltcsfield": IsLtCrossStructField,
|
||
|
"ltecsfield": IsLteCrossStructField,
|
||
|
"nefield": IsNeField,
|
||
|
"gtefield": IsGteField,
|
||
|
"gtfield": IsGtField,
|
||
|
"ltefield": IsLteField,
|
||
|
"ltfield": IsLtField,
|
||
|
"alpha": IsAlpha,
|
||
|
"alphanum": IsAlphanum,
|
||
|
"numeric": IsNumeric,
|
||
|
"number": IsNumber,
|
||
|
"hexadecimal": IsHexadecimal,
|
||
|
"hexcolor": IsHEXColor,
|
||
|
"rgb": IsRGB,
|
||
|
"rgba": IsRGBA,
|
||
|
"hsl": IsHSL,
|
||
|
"hsla": IsHSLA,
|
||
|
"email": IsEmail,
|
||
|
"url": IsURL,
|
||
|
"uri": IsURI,
|
||
|
"base64": IsBase64,
|
||
|
"contains": Contains,
|
||
|
"containsany": ContainsAny,
|
||
|
"containsrune": ContainsRune,
|
||
|
"excludes": Excludes,
|
||
|
"excludesall": ExcludesAll,
|
||
|
"excludesrune": ExcludesRune,
|
||
|
"isbn": IsISBN,
|
||
|
"isbn10": IsISBN10,
|
||
|
"isbn13": IsISBN13,
|
||
|
"uuid": IsUUID,
|
||
|
"uuid3": IsUUID3,
|
||
|
"uuid4": IsUUID4,
|
||
|
"uuid5": IsUUID5,
|
||
|
"ascii": IsASCII,
|
||
|
"printascii": IsPrintableASCII,
|
||
|
"multibyte": HasMultiByteCharacter,
|
||
|
"datauri": IsDataURI,
|
||
|
"latitude": IsLatitude,
|
||
|
"longitude": IsLongitude,
|
||
|
"ssn": IsSSN,
|
||
|
"ipv4": IsIPv4,
|
||
|
"ipv6": IsIPv6,
|
||
|
"ip": IsIP,
|
||
|
"cidrv4": IsCIDRv4,
|
||
|
"cidrv6": IsCIDRv6,
|
||
|
"cidr": IsCIDR,
|
||
|
"tcp4_addr": IsTCP4AddrResolvable,
|
||
|
"tcp6_addr": IsTCP6AddrResolvable,
|
||
|
"tcp_addr": IsTCPAddrResolvable,
|
||
|
"udp4_addr": IsUDP4AddrResolvable,
|
||
|
"udp6_addr": IsUDP6AddrResolvable,
|
||
|
"udp_addr": IsUDPAddrResolvable,
|
||
|
"ip4_addr": IsIP4AddrResolvable,
|
||
|
"ip6_addr": IsIP6AddrResolvable,
|
||
|
"ip_addr": IsIPAddrResolvable,
|
||
|
"unix_addr": IsUnixAddrResolvable,
|
||
|
"mac": IsMAC,
|
||
|
}
|
||
|
|
||
|
// IsMAC is the validation function for validating if the field's value is a valid MAC address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsMAC(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
_, err := net.ParseMAC(field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsCIDRv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
ip, _, err := net.ParseCIDR(field.String())
|
||
|
|
||
|
return err == nil && ip.To4() != nil
|
||
|
}
|
||
|
|
||
|
// IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsCIDRv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
ip, _, err := net.ParseCIDR(field.String())
|
||
|
|
||
|
return err == nil && ip.To4() == nil
|
||
|
}
|
||
|
|
||
|
// IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsCIDR(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
_, _, err := net.ParseCIDR(field.String())
|
||
|
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsIPv4 is the validation function for validating if a value is a valid v4 IP address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIPv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
ip := net.ParseIP(field.String())
|
||
|
|
||
|
return ip != nil && ip.To4() != nil
|
||
|
}
|
||
|
|
||
|
// IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIPv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
ip := net.ParseIP(field.String())
|
||
|
|
||
|
return ip != nil && ip.To4() == nil
|
||
|
}
|
||
|
|
||
|
// IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIP(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
ip := net.ParseIP(field.String())
|
||
|
|
||
|
return ip != nil
|
||
|
}
|
||
|
|
||
|
// IsSSN is the validation function for validating if the field's value is a valid SSN.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsSSN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if field.Len() != 11 {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return sSNRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLongitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return longitudeRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLatitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return latitudeRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsDataURI is the validation function for validating if the field's value is a valid data URI.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsDataURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
uri := strings.SplitN(field.String(), ",", 2)
|
||
|
|
||
|
if len(uri) != 2 {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if !dataURIRegex.MatchString(uri[0]) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
fld := reflect.ValueOf(uri[1])
|
||
|
|
||
|
return IsBase64(v, topStruct, currentStructOrField, fld, fld.Type(), fld.Kind(), param)
|
||
|
}
|
||
|
|
||
|
// HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func HasMultiByteCharacter(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if field.Len() == 0 {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
return multibyteRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsPrintableASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return printableASCIIRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsASCII is the validation function for validating if the field's value is a valid ASCII character.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return aSCIIRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUUID5(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return uUID5Regex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUUID4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return uUID4Regex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUUID3(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return uUID3Regex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsUUID is the validation function for validating if the field's value is a valid UUID of any version.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUUID(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return uUIDRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsISBN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return IsISBN10(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) || IsISBN13(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsISBN13(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
s := strings.Replace(strings.Replace(field.String(), "-", "", 4), " ", "", 4)
|
||
|
|
||
|
if !iSBN13Regex.MatchString(s) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
var checksum int32
|
||
|
var i int32
|
||
|
|
||
|
factor := []int32{1, 3}
|
||
|
|
||
|
for i = 0; i < 12; i++ {
|
||
|
checksum += factor[i%2] * int32(s[i]-'0')
|
||
|
}
|
||
|
|
||
|
if (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0 {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsISBN10(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
s := strings.Replace(strings.Replace(field.String(), "-", "", 3), " ", "", 3)
|
||
|
|
||
|
if !iSBN10Regex.MatchString(s) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
var checksum int32
|
||
|
var i int32
|
||
|
|
||
|
for i = 0; i < 9; i++ {
|
||
|
checksum += (i + 1) * int32(s[i]-'0')
|
||
|
}
|
||
|
|
||
|
if s[9] == 'X' {
|
||
|
checksum += 10 * 10
|
||
|
} else {
|
||
|
checksum += 10 * int32(s[9]-'0')
|
||
|
}
|
||
|
|
||
|
if checksum%11 == 0 {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// ExcludesRune is the validation function for validating that the field's value does not contain the rune specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func ExcludesRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return !ContainsRune(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func ExcludesAll(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return !ContainsAny(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// Excludes is the validation function for validating that the field's value does not contain the text specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func Excludes(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return !Contains(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// ContainsRune is the validation function for validating that the field's value contains the rune specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func ContainsRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
r, _ := utf8.DecodeRuneInString(param)
|
||
|
|
||
|
return strings.ContainsRune(field.String(), r)
|
||
|
}
|
||
|
|
||
|
// ContainsAny is the validation function for validating that the field's value contains any of the characters specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func ContainsAny(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return strings.ContainsAny(field.String(), param)
|
||
|
}
|
||
|
|
||
|
// Contains is the validation function for validating that the field's value contains the text specified withing the param.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func Contains(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return strings.Contains(field.String(), param)
|
||
|
}
|
||
|
|
||
|
// IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() != currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() != currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() != currentField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) != int64(currentField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return !fieldTime.Equal(t)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() != currentField.String()
|
||
|
}
|
||
|
|
||
|
// IsNe is the validation function for validating that the field's value does not equal the provided param value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsNe(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return !IsEq(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || topKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() <= topField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() <= topField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() <= topField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) <= int64(topField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
topTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() <= topField.String()
|
||
|
}
|
||
|
|
||
|
// IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || topKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() < topField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() < topField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() < topField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) < int64(topField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
topTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Before(topTime)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() < topField.String()
|
||
|
}
|
||
|
|
||
|
// IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || topKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() >= topField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() >= topField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() >= topField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) >= int64(topField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
topTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.After(topTime) || fieldTime.Equal(topTime)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() >= topField.String()
|
||
|
}
|
||
|
|
||
|
// IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || topKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() > topField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() > topField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() > topField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) > int64(topField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
topTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.After(topTime)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() > topField.String()
|
||
|
}
|
||
|
|
||
|
// IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, currentKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return topField.Int() != field.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return topField.Uint() != field.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return topField.Float() != field.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(topField.Len()) != int64(field.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := field.Interface().(time.Time)
|
||
|
fieldTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return !fieldTime.Equal(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return topField.String() != field.String()
|
||
|
}
|
||
|
|
||
|
// IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
|
||
|
if !ok || topKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return topField.Int() == field.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return topField.Uint() == field.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return topField.Float() == field.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(topField.Len()) == int64(field.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != topField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := field.Interface().(time.Time)
|
||
|
fieldTime := topField.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Equal(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return topField.String() == field.String()
|
||
|
}
|
||
|
|
||
|
// IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
return field.Int() == currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
return field.Uint() == currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
return field.Float() == currentField.Float()
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
return int64(field.Len()) == int64(currentField.Len())
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Equal(t)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// default reflect.String:
|
||
|
return field.String() == currentField.String()
|
||
|
}
|
||
|
|
||
|
// IsEq is the validation function for validating if the current field's value is equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsEq(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
return field.String() == param
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) == p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() == p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() == p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() == p
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// IsBase64 is the validation function for validating if the current field's value is a valid base 64.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsBase64(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return base64Regex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsURI is the validation function for validating if the current field's value is a valid URI.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
|
||
|
s := field.String()
|
||
|
|
||
|
// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
|
||
|
// emulate browser and strip the '#' suffix prior to validation. see issue-#237
|
||
|
if i := strings.Index(s, "#"); i > -1 {
|
||
|
s = s[:i]
|
||
|
}
|
||
|
|
||
|
if s == blank {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := url.ParseRequestURI(s)
|
||
|
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// IsURL is the validation function for validating if the current field's value is a valid URL.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
|
||
|
var i int
|
||
|
s := field.String()
|
||
|
|
||
|
// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
|
||
|
// emulate browser and strip the '#' suffix prior to validation. see issue-#237
|
||
|
if i = strings.Index(s, "#"); i > -1 {
|
||
|
s = s[:i]
|
||
|
}
|
||
|
|
||
|
if s == blank {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
url, err := url.ParseRequestURI(s)
|
||
|
|
||
|
if err != nil || url.Scheme == blank {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// IsEmail is the validation function for validating if the current field's value is a valid email address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsEmail(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return emailRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsHSLA is the validation function for validating if the current field's value is a valid HSLA color.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsHSLA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return hslaRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsHSL is the validation function for validating if the current field's value is a valid HSL color.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsHSL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return hslRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsRGBA is the validation function for validating if the current field's value is a valid RGBA color.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsRGBA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return rgbaRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsRGB is the validation function for validating if the current field's value is a valid RGB color.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsRGB(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return rgbRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsHEXColor(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return hexcolorRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsHexadecimal(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return hexadecimalRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsNumber is the validation function for validating if the current field's value is a valid number.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsNumber(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return numberRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsNumeric is the validation function for validating if the current field's value is a valid numeric value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsNumeric(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return numericRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsAlphanum(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return alphaNumericRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// IsAlpha is the validation function for validating if the current field's value is a valid alpha value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsAlpha(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return alphaRegex.MatchString(field.String())
|
||
|
}
|
||
|
|
||
|
// HasValue is the validation function for validating if the current field's value is not the default static value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func HasValue(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
|
||
|
return !field.IsNil()
|
||
|
default:
|
||
|
return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
|
||
|
return field.Int() >= currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
|
||
|
return field.Uint() >= currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
|
||
|
return field.Float() >= currentField.Float()
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.After(t) || fieldTime.Equal(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String
|
||
|
return len(field.String()) >= len(currentField.String())
|
||
|
}
|
||
|
|
||
|
// IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
|
||
|
return field.Int() > currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
|
||
|
return field.Uint() > currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
|
||
|
return field.Float() > currentField.Float()
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.After(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String
|
||
|
return len(field.String()) > len(currentField.String())
|
||
|
}
|
||
|
|
||
|
// IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(utf8.RuneCountInString(field.String())) >= p
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) >= p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() >= p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() >= p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() >= p
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
if fieldType == timeType || fieldType == timePtrType {
|
||
|
|
||
|
now := time.Now().UTC()
|
||
|
t := field.Interface().(time.Time)
|
||
|
|
||
|
return t.After(now) || t.Equal(now)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// IsGt is the validation function for validating if the current field's value is greater than the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(utf8.RuneCountInString(field.String())) > p
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) > p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() > p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() > p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() > p
|
||
|
case reflect.Struct:
|
||
|
|
||
|
if field.Type() == timeType || field.Type() == timePtrType {
|
||
|
|
||
|
return field.Interface().(time.Time).After(time.Now().UTC())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// HasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func HasLengthOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(utf8.RuneCountInString(field.String())) == p
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) == p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() == p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() == p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() == p
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func HasMinOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
return IsGte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
|
||
|
return field.Int() <= currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
|
||
|
return field.Uint() <= currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
|
||
|
return field.Float() <= currentField.Float()
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Before(t) || fieldTime.Equal(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String
|
||
|
return len(field.String()) <= len(currentField.String())
|
||
|
}
|
||
|
|
||
|
// IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
|
||
|
if !ok || currentKind != fieldKind {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
|
||
|
return field.Int() < currentField.Int()
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
|
||
|
return field.Uint() < currentField.Uint()
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
|
||
|
return field.Float() < currentField.Float()
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
// Not Same underlying type i.e. struct and time
|
||
|
if fieldType != currentField.Type() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldType == timeType {
|
||
|
|
||
|
t := currentField.Interface().(time.Time)
|
||
|
fieldTime := field.Interface().(time.Time)
|
||
|
|
||
|
return fieldTime.Before(t)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default reflect.String
|
||
|
return len(field.String()) < len(currentField.String())
|
||
|
}
|
||
|
|
||
|
// IsLte is the validation function for validating if the current field's value is less than or equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(utf8.RuneCountInString(field.String())) <= p
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) <= p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() <= p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() <= p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() <= p
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
if fieldType == timeType || fieldType == timePtrType {
|
||
|
|
||
|
now := time.Now().UTC()
|
||
|
t := field.Interface().(time.Time)
|
||
|
|
||
|
return t.Before(now) || t.Equal(now)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// IsLt is the validation function for validating if the current field's value is less than the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
switch fieldKind {
|
||
|
|
||
|
case reflect.String:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(utf8.RuneCountInString(field.String())) < p
|
||
|
|
||
|
case reflect.Slice, reflect.Map, reflect.Array:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return int64(field.Len()) < p
|
||
|
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
p := asInt(param)
|
||
|
|
||
|
return field.Int() < p
|
||
|
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||
|
p := asUint(param)
|
||
|
|
||
|
return field.Uint() < p
|
||
|
|
||
|
case reflect.Float32, reflect.Float64:
|
||
|
p := asFloat(param)
|
||
|
|
||
|
return field.Float() < p
|
||
|
|
||
|
case reflect.Struct:
|
||
|
|
||
|
if field.Type() == timeType || field.Type() == timePtrType {
|
||
|
|
||
|
return field.Interface().(time.Time).Before(time.Now().UTC())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
|
||
|
}
|
||
|
|
||
|
// HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func HasMaxOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
return IsLte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
|
||
|
}
|
||
|
|
||
|
// IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsTCP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveTCPAddr("tcp4", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsTCP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveTCPAddr("tcp6", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsTCPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
|
||
|
!isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveTCPAddr("tcp", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUDP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveUDPAddr("udp4", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUDP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveUDPAddr("udp6", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUDPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
|
||
|
!isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveUDPAddr("udp", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !IsIPv4(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveIPAddr("ip4", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !IsIPv6(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveIPAddr("ip6", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsIPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
|
||
|
if !IsIP(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
_, err := net.ResolveIPAddr("ip", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
// IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
|
||
|
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
|
||
|
func IsUnixAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
_, err := net.ResolveUnixAddr("unix", field.String())
|
||
|
return err == nil
|
||
|
}
|
||
|
|
||
|
func isIP4Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
val := field.String()
|
||
|
|
||
|
if idx := strings.LastIndex(val, ":"); idx != -1 {
|
||
|
val = val[0:idx]
|
||
|
}
|
||
|
|
||
|
if !IsIPv4(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func isIP6Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
||
|
val := field.String()
|
||
|
|
||
|
if idx := strings.LastIndex(val, ":"); idx != -1 {
|
||
|
if idx != 0 && val[idx-1:idx] == "]" {
|
||
|
val = val[1 : idx-1]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !IsIPv6(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|