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') } return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0 } // 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') } return checksum%11 == 0 } // ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within 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 within 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 within 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 within 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 within 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 within 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 fieldType == timeType || fieldType == 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 fieldType == timeType || fieldType == 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 }