From 6fdb45c52c6222a190c3e083219353693124442f Mon Sep 17 00:00:00 2001 From: Ali OYGUR Date: Wed, 31 Aug 2016 18:21:14 +0300 Subject: [PATCH] first commit --- .gitignore | 1 + .travis.yml | 13 + LICENSE | 22 + README.md | 183 +++++ is.go | 592 ++++++++++++++++ is_test.go | 1914 +++++++++++++++++++++++++++++++++++++++++++++++++++ patterns.go | 344 +++++++++ 7 files changed, 3069 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 is.go create mode 100644 is_test.go create mode 100644 patterns.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c2f433 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tmp \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..71ff298 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: go + +install: + - go get github.com/alioygur/is + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c27dc91 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2016 Ali OYGUR + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5067901 --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +# godash + +[![Build Status](https://travis-ci.org/alioygur/is.svg?branch=master)](https://travis-ci.org/alioygur/is) +[![GoDoc](https://godoc.org/github.com/alioygur/is?status.svg)](https://godoc.org/github.com/alioygur/is) +[![Go Report Card](https://goreportcard.com/badge/github.com/alioygur/is)](https://goreportcard.com/report/github.com/alioygur/is) + +A utility library in Golang inspired by lodash + +## installation + +`go get gopkg.in/alioygur/is.v0` + +## Contribute + +**we are waiting your contribution** + +- Report problems +- Add/Suggest new features/recipes +- Improve/fix documentation + +Many thanks to our contributors: [contributors](https://github.com/alioygur/is/graphs/contributors) + + +## Is* (collection of checking) + +An Example; + +```go +func IsEmail(str string) bool +``` + +```go +func ExampleIsEmail() { + fmt.Println(IsEmail("jhon@example.com")) + fmt.Println(IsEmail("invalid.com")) + fmt.Println(IsEmail(`very.(),:;<>[]".VERY."very@\ "very".unusual@strange.example.com`)) + // Output: + // true + // false + // true +} +``` + +Full list of Is* functions; + +```go +func IsASCII(s string) bool +func IsAlpha(s string) bool +func IsAlphanumeric(s string) bool +func IsBase64(s string) bool +func IsByteLength(str string, min, max int) bool +func IsCreditCard(str string) bool +func IsDNSName(str string) bool +func IsDataURI(str string) bool +func IsDialString(str string) bool +func IsDivisibleBy(str, num string) bool +func IsEmail(s string) bool +func IsFilePath(str string) (bool, int) +func IsFloat(str string) bool +func IsFullWidth(str string) bool +func IsHalfWidth(str string) bool +func IsHexadecimal(str string) bool +func IsHexcolor(str string) bool +func IsIP(str string) bool +func IsIPv4(str string) bool +func IsIPv6(str string) bool +func IsISBN(str string, version int) bool +func IsISBN10(str string) bool +func IsISBN13(str string) bool +func IsISO3166Alpha2(str string) bool +func IsISO3166Alpha3(str string) bool +func IsInRange(value, left, right float64) bool +func IsInt(str string) bool +func IsJSON(str string) bool +func IsLatitude(str string) bool +func IsLongitude(str string) bool +func IsLowerCase(str string) bool +func IsMAC(str string) bool +func IsMatches(str, pattern string) bool +func IsMongoID(str string) bool +func IsMultibyte(s string) bool +func IsNatural(value float64) bool +func IsNegative(value float64) bool +func IsNonNegative(value float64) bool +func IsNonPositive(value float64) bool +func IsNull(str string) bool +func IsNumeric(s string) bool +func IsPort(str string) bool +func IsPositive(value float64) bool +func IsPrintableASCII(s string) bool +func IsRGBcolor(str string) bool +func IsRequestURI(rawurl string) bool +func IsRequestURL(rawurl string) bool +func IsSSN(str string) bool +func IsSemver(str string) bool +func IsStringLength(str string, params ...string) bool +func IsStringMatches(s string, params ...string) bool +func IsURL(str string) bool +func IsUTFDigit(s string) bool +func IsUTFLetter(str string) bool +func IsUTFLetterNumeric(s string) bool +func IsUTFNumeric(s string) bool +func IsUUID(str string) bool +func IsUUIDv3(str string) bool +func IsUUIDv4(str string) bool +func IsUUIDv5(str string) bool +func IsUpperCase(str string) bool +func IsVariableWidth(str string) bool +func IsWhole(value float64) bool +``` + +## To* (collection of converting) + +Examples; + +```go +func ExampleToBoolean() { + fmt.Println(ToBoolean("True")) + fmt.Println(ToBoolean("true")) + fmt.Println(ToBoolean("1")) + fmt.Println(ToBoolean("False")) + fmt.Println(ToBoolean("false")) + fmt.Println(ToBoolean("0")) + // Output: + // true + // true + // true + // false + // false + // false +} + +func ExampleToCamelCase() { + fmt.Println(ToCamelCase("camel case")) + fmt.Println(ToCamelCase(" camel case ")) + fmt.Println(ToCamelCase("!!!camel case====")) + fmt.Println(ToCamelCase("camel-case")) + fmt.Println(ToCamelCase("camel_case")) + // Output: + // CamelCase + // CamelCase + // CamelCase + // CamelCase + // CamelCase +} + +func ExampleToSnakeCase() { + fmt.Println(ToSnakeCase("SnakeCase")) + fmt.Println(ToSnakeCase("snake case")) + fmt.Println(ToSnakeCase(" snake case ")) + fmt.Println(ToSnakeCase("!!!snake case====")) + fmt.Println(ToSnakeCase("snake-case")) + fmt.Println(ToSnakeCase("snake_case")) + // Output: + // snake_case + // snake_case + // snake_case + // snake_case + // snake_case + // snake_case +} +``` + +Full list of To* functions; + +```go +func ToBoolean(str string) (bool, error) +func ToCamelCase(s string) string +func ToFloat(str string) (float64, error) +func ToInt(str string) (int64, error) +func ToJSON(obj interface{}) (string, error) +func ToSnakeCase(str string) string +func ToString(obj interface{}) string +``` + +for more documentation [godoc](https://godoc.org/github.com/alioygur/is) + +## Thanks & Authors + +I use code/got inspiration from these excellent libraries: + +- [asaskevich/govalidator](https://github.com/asaskevich/govalidator) [Go] Package of validators and sanitizers for strings, numerics, slices and structs +- [lodash/lodash](https://github.com/lodash/lodash) A modern JavaScript utility library delivering modularity, performance, & extras. \ No newline at end of file diff --git a/is.go b/is.go new file mode 100644 index 0000000..8d47504 --- /dev/null +++ b/is.go @@ -0,0 +1,592 @@ +package is + +import ( + "encoding/base64" + "encoding/json" + "math" + "net" + "net/url" + "regexp" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +// InRange returns true if value lies between left and right border +func InRange(value, left, right float64) bool { + if left > right { + left, right = right, left + } + return value >= left && value <= right +} + +// Email is a constraint to do a simple validation for email addresses, it only check if the string contains "@" +// and that it is not in the first or last character of the string +// https://en.wikipedia.org/wiki/Email_address#Valid_email_addresses +func Email(s string) bool { + if !strings.Contains(s, "@") || string(s[0]) == "@" || string(s[len(s)-1]) == "@" { + return false + } + return true +} + +// URL check if the string is an URL. +func URL(str string) bool { + if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") { + return false + } + u, err := url.Parse(str) + if err != nil { + return false + } + if strings.HasPrefix(u.Host, ".") { + return false + } + if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) { + return false + } + return rxURL.MatchString(str) + +} + +// RequestURL check if the string rawurl, assuming +// it was recieved in an HTTP request, is a valid +// URL confirm to RFC 3986 +func RequestURL(rawurl string) bool { + url, err := url.ParseRequestURI(rawurl) + if err != nil { + return false //Couldn't even parse the rawurl + } + if len(url.Scheme) == 0 { + return false //No Scheme found + } + return true +} + +// RequestURI check if the string rawurl, assuming +// it was recieved in an HTTP request, is an +// absolute URI or an absolute path. +func RequestURI(rawurl string) bool { + _, err := url.ParseRequestURI(rawurl) + return err == nil +} + +// Alpha check if the string contains only letters (a-zA-Z). Empty string is valid. +func Alpha(s string) bool { + for _, v := range s { + if ('Z' < v || v < 'A') && ('z' < v || v < 'a') { + return false + } + } + return true +} + +//IsUTFLetter check if the string contains only unicode letter characters. +//Similar to IsAlpha but for all languages. Empty string is valid. +func UTFLetter(str string) bool { + for _, v := range str { + if !unicode.IsLetter(v) { + return false + } + } + return true + +} + +// Alphanumeric check if the string contains only letters and numbers. Empty string is valid. +func Alphanumeric(s string) bool { + for _, v := range s { + if ('Z' < v || v < 'A') && ('z' < v || v < 'a') && ('9' < v || v < '0') { + return false + } + } + return true +} + +// UTFLetterNumeric check if the string contains only unicode letters and numbers. Empty string is valid. +func UTFLetterNumeric(s string) bool { + for _, v := range s { + if !unicode.IsLetter(v) && !unicode.IsNumber(v) { //letters && numbers are ok + return false + } + } + return true +} + +// Numeric check if the string contains only numbers. Empty string is valid. +func Numeric(s string) bool { + for _, v := range s { + if '9' < v || v < '0' { + return false + } + } + return true +} + +// UTFNumeric check if the string contains only unicode numbers of any kind. +// Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid. +func UTFNumeric(s string) bool { + for _, v := range s { + if unicode.IsNumber(v) == false { + return false + } + } + return true +} + +// Negative returns true if value < 0 +func Negative(value float64) bool { + return value < 0 +} + +// Positive returns true if value > 0 +func Positive(value float64) bool { + return value > 0 +} + +// NonNegative returns true if value >= 0 +func NonNegative(value float64) bool { + return value >= 0 +} + +// NonPositive returns true if value <= 0 +func NonPositive(value float64) bool { + return value <= 0 +} + +// Whole returns true if value is whole number +func Whole(value float64) bool { + return math.Abs(math.Remainder(value, 1)) == 0 +} + +// Natural returns true if value is natural number (positive and whole) +func Natural(value float64) bool { + return Whole(value) && Positive(value) +} + +// UTFDigit check if the string contains only unicode radix-10 decimal digits. Empty string is valid. +func UTFDigit(s string) bool { + for _, v := range s { + if !unicode.IsDigit(v) { + return false + } + } + return true +} + +// Hexadecimal check if the string is a hexadecimal number. +func Hexadecimal(str string) bool { + return rxHexadecimal.MatchString(str) +} + +// Hexcolor check if the string is a hexadecimal color. +func Hexcolor(str string) bool { + return rxHexcolor.MatchString(str) +} + +// RGBcolor check if the string is a valid RGB color in form rgb(RRR, GGG, BBB). +func RGBcolor(str string) bool { + return rxRGBcolor.MatchString(str) +} + +// LowerCase check if the string is lowercase. Empty string is valid. +func LowerCase(str string) bool { + if Null(str) { + return true + } + return str == strings.ToLower(str) +} + +// UpperCase check if the string is uppercase. Empty string is valid. +func UpperCase(str string) bool { + if Null(str) { + return true + } + return str == strings.ToUpper(str) +} + +// Int check if the string is an integer. Empty string is valid. +func Int(str string) bool { + if Null(str) { + return true + } + return rxInt.MatchString(str) +} + +// Float check if the string is a float. +func Float(str string) bool { + return str != "" && rxFloat.MatchString(str) +} + +// DivisibleBy check if the string is a number that's divisible by another. +// If second argument is not valid integer or zero, it's return false. +// Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero). +func DivisibleBy(str, num string) bool { + f, _ := toFloat(str) + p := int64(f) + q, _ := toInt(num) + if q == 0 { + return false + } + return (p == 0) || (p%q == 0) +} + +// Null check if the string is null. +func Null(str string) bool { + return len(str) == 0 +} + +// ByteLength check if the string's length (in bytes) falls in a range. +func ByteLength(str string, min, max int) bool { + return len(str) >= min && len(str) <= max +} + +// UUIDv3 check if the string is a UUID version 3. +func UUIDv3(str string) bool { + return rxUUID3.MatchString(str) +} + +// UUIDv4 check if the string is a UUID version 4. +func UUIDv4(str string) bool { + return rxUUID4.MatchString(str) +} + +// UUIDv5 check if the string is a UUID version 5. +func UUIDv5(str string) bool { + return rxUUID5.MatchString(str) +} + +// UUID check if the string is a UUID (version 3, 4 or 5). +func UUID(str string) bool { + return rxUUID.MatchString(str) +} + +// CreditCard check if the string is a credit card. +func CreditCard(str string) bool { + r, _ := regexp.Compile("[^0-9]+") + sanitized := r.ReplaceAll([]byte(str), []byte("")) + if !rxCreditCard.MatchString(string(sanitized)) { + return false + } + var sum int64 + var digit string + var tmpNum int64 + var shouldDouble bool + for i := len(sanitized) - 1; i >= 0; i-- { + digit = string(sanitized[i:(i + 1)]) + tmpNum, _ = toInt(digit) + if shouldDouble { + tmpNum *= 2 + if tmpNum >= 10 { + sum += ((tmpNum % 10) + 1) + } else { + sum += tmpNum + } + } else { + sum += tmpNum + } + shouldDouble = !shouldDouble + } + + if sum%10 == 0 { + return true + } + return false +} + +// ISBN10 check if the string is an ISBN version 10. +func ISBN10(str string) bool { + return ISBN(str, 10) +} + +// ISBN13 check if the string is an ISBN version 13. +func ISBN13(str string) bool { + return ISBN(str, 13) +} + +// ISBN check if the string is an ISBN (version 10 or 13). +// If version value is not equal to 10 or 13, it will be check both variants. +func ISBN(str string, version int) bool { + r, _ := regexp.Compile("[\\s-]+") + sanitized := r.ReplaceAll([]byte(str), []byte("")) + var checksum int32 + var i int32 + if version == 10 { + if !rxISBN10.MatchString(string(sanitized)) { + return false + } + for i = 0; i < 9; i++ { + checksum += (i + 1) * int32(sanitized[i]-'0') + } + if sanitized[9] == 'X' { + checksum += 10 * 10 + } else { + checksum += 10 * int32(sanitized[9]-'0') + } + if checksum%11 == 0 { + return true + } + return false + } else if version == 13 { + if !rxISBN13.MatchString(string(sanitized)) { + return false + } + factor := []int32{1, 3} + for i = 0; i < 12; i++ { + checksum += factor[i%2] * int32(sanitized[i]-'0') + } + if (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0 { + return true + } + return false + } + return ISBN(str, 10) || ISBN(str, 13) +} + +// JSON check if the string is valid JSON (note: uses json.Unmarshal). +func JSON(str string) bool { + var js json.RawMessage + return json.Unmarshal([]byte(str), &js) == nil +} + +// Multibyte check if the string contains one or more multibyte chars. Empty string is valid. +func Multibyte(s string) bool { + for _, v := range s { + if v >= utf8.RuneSelf { + return true + } + } + + return Null(s) +} + +// ASCII check if the string contains ASCII chars only. Empty string is valid. +func ASCII(s string) bool { + for _, v := range s { + if v >= utf8.RuneSelf { + return false + } + } + return true +} + +// PrintableASCII check if the string contains printable ASCII chars only. Empty string is valid. +func PrintableASCII(s string) bool { + for _, v := range s { + if v < ' ' || v > '~' { + return false + } + } + return true +} + +// FullWidth check if the string contains any full-width chars. Empty string is valid. +func FullWidth(str string) bool { + if Null(str) { + return true + } + return rxFullWidth.MatchString(str) +} + +// HalfWidth check if the string contains any half-width chars. Empty string is valid. +func HalfWidth(str string) bool { + if Null(str) { + return true + } + return rxHalfWidth.MatchString(str) +} + +// VariableWidth check if the string contains a mixture of full and half-width chars. Empty string is valid. +func VariableWidth(str string) bool { + if Null(str) { + return true + } + return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str) +} + +// Base64 check if a string is base64 encoded. +func Base64(s string) bool { + if Null(s) { + return false + } + _, err := base64.StdEncoding.DecodeString(s) + + return err == nil +} + +// FilePath check is a string is Win or Unix file path and returns it's type. +func FilePath(str string) (bool, int) { + if rxWinPath.MatchString(str) { + //check windows path limit see: + // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + if len(str[3:]) > 32767 { + return false, Win + } + return true, Win + } else if rxUnixPath.MatchString(str) { + return true, Unix + } + return false, Unknown +} + +// DataURI checks if a string is base64 encoded data URI such as an image +func DataURI(str string) bool { + dataURI := strings.Split(str, ",") + if !rxDataURI.MatchString(dataURI[0]) { + return false + } + return Base64(dataURI[1]) +} + +// ISO3166Alpha2 checks if a string is valid two-letter country code +func ISO3166Alpha2(str string) bool { + for _, entry := range ISO3166List { + if str == entry.Alpha2Code { + return true + } + } + return false +} + +// ISO3166Alpha3 checks if a string is valid three-letter country code +func ISO3166Alpha3(str string) bool { + for _, entry := range ISO3166List { + if str == entry.Alpha3Code { + return true + } + } + return false +} + +// DNSName will validate the given string as a DNS name +func DNSName(str string) bool { + if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 { + // constraints already violated + return false + } + return rxDNSName.MatchString(str) +} + +// DialString validates the given string for usage with the various Dial() functions +func DialString(str string) bool { + + if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (DNSName(h) || IP(h)) && Port(p) { + return true + } + + return false +} + +// IP checks if a string is either IP version 4 or 6. +func IP(str string) bool { + return net.ParseIP(str) != nil +} + +// Port checks if a string represents a valid port +func Port(str string) bool { + if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 { + return true + } + return false +} + +// IPv4 check if the string is an IP version 4. +func IPv4(str string) bool { + ip := net.ParseIP(str) + return ip != nil && strings.Contains(str, ".") +} + +// IPv6 check if the string is an IP version 6. +func IPv6(str string) bool { + ip := net.ParseIP(str) + return ip != nil && strings.Contains(str, ":") +} + +// MAC check if a string is valid MAC address. +// Possible MAC formats: +// 01:23:45:67:89:ab +// 01:23:45:67:89:ab:cd:ef +// 01-23-45-67-89-ab +// 01-23-45-67-89-ab-cd-ef +// 0123.4567.89ab +// 0123.4567.89ab.cdef +func MAC(str string) bool { + _, err := net.ParseMAC(str) + return err == nil +} + +// MongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId. +func MongoID(str string) bool { + return rxHexadecimal.MatchString(str) && (len(str) == 24) +} + +// Latitude check if a string is valid latitude. +func Latitude(str string) bool { + return rxLatitude.MatchString(str) +} + +// Longitude check if a string is valid longitude. +func Longitude(str string) bool { + return rxLongitude.MatchString(str) +} + +// SSN will validate the given string as a U.S. Social Security Number +func SSN(str string) bool { + if str == "" || len(str) != 11 { + return false + } + return rxSSN.MatchString(str) +} + +// Semver check if string is valid semantic version +func Semver(str string) bool { + return rxSemver.MatchString(str) +} + +// Matches check if string matches the pattern (pattern is regular expression) +// In case of error return false +func Matches(str, pattern string) bool { + match, _ := regexp.MatchString(pattern, str) + return match +} + +// StringMatches checks if a string matches a given pattern. +func StringMatches(s string, params ...string) bool { + if len(params) == 1 { + pattern := params[0] + return Matches(s, pattern) + } + return false +} + +// StringLength check string's length (including multi byte strings) +func StringLength(str string, params ...string) bool { + + if len(params) == 2 { + strLength := utf8.RuneCountInString(str) + min, _ := toInt(params[0]) + max, _ := toInt(params[1]) + return strLength >= int(min) && strLength <= int(max) + } + + return false +} + +// toFloat convert the input string to a float, or 0.0 if the input is not a float. +func toFloat(str string) (float64, error) { + res, err := strconv.ParseFloat(str, 64) + if err != nil { + res = 0.0 + } + return res, err +} + +// toInt convert the input string to an integer, or 0 if the input is not an integer. +func toInt(str string) (int64, error) { + res, err := strconv.ParseInt(str, 0, 64) + if err != nil { + res = 0 + } + return res, err +} diff --git a/is_test.go b/is_test.go new file mode 100644 index 0000000..7cc8738 --- /dev/null +++ b/is_test.go @@ -0,0 +1,1914 @@ +package is + +import ( + "fmt" + "strings" + "testing" +) + +func TestAlpha(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", true}, + {"소주", false}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", false}, //UTF-8(ASCII): 0 + {"123", false}, + {"0123", false}, + {"-00123", false}, + {"0", false}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := Alpha(test.param) + if actual != test.expected { + t.Errorf("Expected Alpha(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUTFLetter(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"", true}, + {"abc", true}, + {"소주", true}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", true}, + {"소", true}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", false}, //UTF-8(ASCII): 0 + {"123", false}, + {"0123", false}, + {"-00123", false}, + {"0", false}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", true}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := UTFLetter(test.param) + if actual != test.expected { + t.Errorf("Expected UTFLetter(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestAlphanumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc123", true}, + {"ABC111", true}, + {"abc1", true}, + {"abc〩", false}, + {"abc", true}, + {"소주", false}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := Alphanumeric(test.param) + if actual != test.expected { + t.Errorf("Expected Alphanumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUTFLetterNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", true}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", true}, + {"abc〩", true}, + {"abc", true}, + {"소주", true}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", true}, + {"소", true}, + {"달기&Co.", false}, + {"〩Hours", true}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", true}, + {"〥〩", true}, + {"모자", true}, + {"ix", true}, + {"۳۵۶۰", true}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := UTFLetterNumeric(test.param) + if actual != test.expected { + t.Errorf("Expected UTFLetterNumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"+00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := Numeric(test.param) + if actual != test.expected { + t.Errorf("Expected Numeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUTFNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", true}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"--0", false}, + {"-0-", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", true}, + {"-1¾", false}, + {"1¾", true}, + {"〥〩", true}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", true}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := UTFNumeric(test.param) + if actual != test.expected { + t.Errorf("Expected UTFNumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUTFDigit(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"--0", false}, + {"-0-", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", false}, + {"1483920", true}, + {"", true}, + {"۳۵۶۰", true}, + {"-29", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", true}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := UTFDigit(test.param) + if actual != test.expected { + t.Errorf("Expected UTFDigit(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestLowerCase(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc123", true}, + {"abc", true}, + {"a b c", true}, + {"abcß", true}, + {"abcẞ", false}, + {"ABCẞ", false}, + {"tr竪s 端ber", true}, + {"fooBar", false}, + {"123ABC", false}, + {"ABC123", false}, + {"ABC", false}, + {"S T R", false}, + {"fooBar", false}, + {"abacaba123", true}, + } + for _, test := range tests { + actual := LowerCase(test.param) + if actual != test.expected { + t.Errorf("Expected LowerCase(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUpperCase(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc123", false}, + {"abc", false}, + {"a b c", false}, + {"abcß", false}, + {"abcẞ", false}, + {"ABCẞ", true}, + {"tr竪s 端ber", false}, + {"fooBar", false}, + {"123ABC", true}, + {"ABC123", true}, + {"ABC", true}, + {"S T R", true}, + {"fooBar", false}, + {"abacaba123", false}, + } + for _, test := range tests { + actual := UpperCase(test.param) + if actual != test.expected { + t.Errorf("Expected UpperCase(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestInt(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"-2147483648", true}, //Signed 32 Bit Min Int + {"2147483647", true}, //Signed 32 Bit Max Int + {"-2147483649", true}, //Signed 32 Bit Min Int - 1 + {"2147483648", true}, //Signed 32 Bit Max Int + 1 + {"4294967295", true}, //Unsigned 32 Bit Max Int + {"4294967296", true}, //Unsigned 32 Bit Max Int + 1 + {"-9223372036854775808", true}, //Signed 64 Bit Min Int + {"9223372036854775807", true}, //Signed 64 Bit Max Int + {"-9223372036854775809", true}, //Signed 64 Bit Min Int - 1 + {"9223372036854775808", true}, //Signed 64 Bit Max Int + 1 + {"18446744073709551615", true}, //Unsigned 64 Bit Max Int + {"18446744073709551616", true}, //Unsigned 64 Bit Max Int + 1 + {"", true}, + {"123", true}, + {"0", true}, + {"-0", true}, + {"+0", true}, + {"01", false}, + {"123.123", false}, + {" ", false}, + {"000", false}, + } + for _, test := range tests { + actual := Int(test.param) + if actual != test.expected { + t.Errorf("Expected Int(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestEmail(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {``, false}, + {`foo@bar.com`, true}, + {`x@x.x`, true}, + {`foo@bar.com.au`, true}, + {`foo+bar@bar.com`, true}, + {`foo@bar.coffee`, true}, + {`foo@bar.中文网`, true}, + {`invalidemail@`, false}, + {`invalid.com`, false}, + {`@invalid.com`, false}, + {`test|123@m端ller.com`, true}, + {`hans@m端ller.com`, true}, + {`hans.m端ller@test.com`, true}, + {`NathAn.daVIeS@DomaIn.cOM`, true}, + {`NATHAN.DAVIES@DOMAIN.CO.UK`, true}, + {`very.(),:;<>[]".VERY."very@\ "very".unusual@strange.example.com`, true}, + } + for _, test := range tests { + actual := Email(test.param) + if actual != test.expected { + t.Errorf("Expected Email(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func ExampleEmail() { + fmt.Println(Email("jhon@example.com")) + fmt.Println(Email("invalid.com")) + fmt.Println(Email(`very.(),:;<>[]".VERY."very@\ "very".unusual@strange.example.com`)) + // Output: + // true + // false + // true +} + +func TestURL(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"http://foo.bar#com", true}, + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", true}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"ftp.foo.bar", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://user:pass@www.foobar.com/path/file", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"http://foobar.com/a-", true}, + {"http://foobar.پاکستان/", true}, + {"http://foobar.c_o_m", false}, + {"", false}, + {"xyz://foobar.com", false}, + {"invalid.", false}, + {".com", false}, + {"rtmp://foobar.com", false}, + {"http://www.foo_bar.com/", false}, + {"http://localhost:3000/", true}, + {"http://foobar.com#baz=qux", true}, + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", false}, + {"http://www.foo---bar.com/", false}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", false}, + {"irc://#channel@network", true}, + {"/abs/test/dir", false}, + {"./rel/test/dir", false}, + {"http://foo^bar.org", false}, + {"http://foo&*bar.org", false}, + {"http://foo&bar.org", false}, + {"http://foo bar.org", false}, + {"http://foo.bar.org", true}, + {"http://www.foo.bar.org", true}, + {"http://www.foo.co.uk", true}, + {"foo", false}, + {"http://.foo.com", false}, + {"http://,foo.com", false}, + {",foo.com", false}, + // according to issues #62 #66 + {"https://pbs.twimg.com/profile_images/560826135676588032/j8fWrmYY_normal.jpeg", true}, + {"http://me.example.com", true}, + {"http://www.me.example.com", true}, + {"https://farm6.static.flickr.com", true}, + {"https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5", true}, + {"google", false}, + // According to #87 + {"http://hyphenated-host-name.example.co.in", true}, + {"http://cant-end-with-hyphen-.example.com", false}, + {"http://-cant-start-with-hyphen.example.com", false}, + {"http://www.domain-can-have-dashes.com", true}, + } + for _, test := range tests { + actual := URL(test.param) + if actual != test.expected { + t.Errorf("Expected URL(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestRequestURL(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + // {"http://foo.bar#com", false}, goversion < 1.6: true, goversion > 1.5: false + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", false}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"", false}, + {"xyz://foobar.com", true}, + {"invalid.", false}, + {".com", false}, + {"rtmp://foobar.com", true}, + {"http://www.foo_bar.com/", true}, + {"http://localhost:3000/", true}, + // {"http://foobar.com#baz=qux", false}, goversion < 1.6: true, goversion > 1.5: false + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", true}, + {"http://www.foo---bar.com/", true}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", true}, + {"irc://#channel@network", true}, + {"/abs/test/dir", false}, + {"./rel/test/dir", false}, + } + for _, test := range tests { + actual := RequestURL(test.param) + if actual != test.expected { + t.Errorf("Expected RequestURL(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestRequestURI(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + // {"http://foo.bar#com", false}, goversion < 1.6: true, goversion > 1.5: false + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", false}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"xyz://foobar.com", true}, + {"invalid.", false}, + {".com", false}, + {"rtmp://foobar.com", true}, + {"http://www.foo_bar.com/", true}, + {"http://localhost:3000/", true}, + // {"http://foobar.com#baz=qux", false}, goversion < 1.6: true, goversion > 1.5: false + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", true}, + {"http://www.foo---bar.com/", true}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", true}, + {"irc://#channel@network", true}, + {"/abs/test/dir", true}, + {"./rel/test/dir", false}, + } + for _, test := range tests { + actual := RequestURI(test.param) + if actual != test.expected { + t.Errorf("Expected RequestURI(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestFloat(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {" ", false}, + {"-.123", false}, + {"abacaba", false}, + {"1f", false}, + {"-1f", false}, + {"+1f", false}, + {"123", true}, + {"123.", true}, + {"123.123", true}, + {"-123.123", true}, + {"+123.123", true}, + {"0.123", true}, + {"-0.123", true}, + {"+0.123", true}, + {".0", true}, + {"01.123", true}, + {"-0.22250738585072011e-307", true}, + {"+0.22250738585072011e-307", true}, + } + for _, test := range tests { + actual := Float(test.param) + if actual != test.expected { + t.Errorf("Expected Float(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestHexadecimal(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abcdefg", false}, + {"", false}, + {"..", false}, + {"deadBEEF", true}, + {"ff0044", true}, + } + for _, test := range tests { + actual := Hexadecimal(test.param) + if actual != test.expected { + t.Errorf("Expected Hexadecimal(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestHexcolor(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"#ff", false}, + {"fff0", false}, + {"#ff12FG", false}, + {"CCccCC", true}, + {"fff", true}, + {"#f00", true}, + } + for _, test := range tests { + actual := Hexcolor(test.param) + if actual != test.expected { + t.Errorf("Expected Hexcolor(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestRGBcolor(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"rgb(0,31,255)", true}, + {"rgb(1,349,275)", false}, + {"rgb(01,31,255)", false}, + {"rgb(0.6,31,255)", false}, + {"rgba(0,31,255)", false}, + {"rgb(0, 31, 255)", true}, + } + for _, test := range tests { + actual := RGBcolor(test.param) + if actual != test.expected { + t.Errorf("Expected RGBcolor(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNull(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abacaba", false}, + {"", true}, + } + for _, test := range tests { + actual := Null(test.param) + if actual != test.expected { + t.Errorf("Expected Null(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestDivibleBy(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected bool + }{ + {"4", "2", true}, + {"100", "10", true}, + {"", "1", true}, + {"123", "foo", false}, + {"123", "0", false}, + } + for _, test := range tests { + actual := DivisibleBy(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected DivisibleBy(%q, %q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +// This small example illustrate how to work with IsDivisibleBy function. +func ExampleDivisibleBy() { + println("1024 divisible by 64: ", DivisibleBy("1024", "64")) +} + +func TestByteLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 int + param3 int + expected bool + }{ + {"abacaba", 100, -1, false}, + {"abacaba", 1, 3, false}, + {"abacaba", 1, 7, true}, + {"abacaba", 0, 8, true}, + {"\ufff0", 1, 1, false}, + } + for _, test := range tests { + actual := ByteLength(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected ByteLength(%q, %q, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +func TestJSON(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"145", true}, + {"asdf", false}, + {"123:f00", false}, + {"{\"Name\":\"Alice\",\"Body\":\"Hello\",\"Time\":1294706395881547000}", true}, + {"{}", true}, + {"{\"Key\":{\"Key\":{\"Key\":123}}}", true}, + {"[]", true}, + {"null", true}, + } + for _, test := range tests { + actual := JSON(test.param) + if actual != test.expected { + t.Errorf("Expected JSON(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestMultibyte(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abc", false}, + {"123", false}, + {"<>@;.-=", false}, + {"ひらがな・カタカナ、.漢字", true}, + {"あいうえお foobar", true}, + {"test@example.com", true}, + {"test@example.com", true}, + {"1234abcDExyz", true}, + {"カタカナ", true}, + {"~", false}, + } + for _, test := range tests { + actual := Multibyte(test.param) + if actual != test.expected { + t.Errorf("Expected Multibyte(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestASCII(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"foobar", false}, + {"xyz098", false}, + {"123456", false}, + {"カタカナ", false}, + {"foobar", true}, + {"0987654321", true}, + {"test@example.com", true}, + {"1234abcDEF", true}, + {"", true}, + } + for _, test := range tests { + actual := ASCII(test.param) + if actual != test.expected { + t.Errorf("Expected ASCII(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestPrintableASCII(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"foobar", false}, + {"xyz098", false}, + {"123456", false}, + {"カタカナ", false}, + {"foobar", true}, + {"0987654321", true}, + {"test@example.com", true}, + {"1234abcDEF", true}, + {"newline\n", false}, + {"\x19test\x7F", false}, + } + for _, test := range tests { + actual := PrintableASCII(test.param) + if actual != test.expected { + t.Errorf("Expected PrintableASCII(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestFullWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc", false}, + {"abc123", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, + {"ひらがな・カタカナ、.漢字", true}, + {"3ー0 a@com", true}, + {"Fカタカナ゙ᆲ", true}, + {"Good=Parts", true}, + {"", true}, + } + for _, test := range tests { + actual := FullWidth(test.param) + if actual != test.expected { + t.Errorf("Expected FullWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestHalfWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"あいうえお", false}, + {"0011", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", true}, + {"l-btn_02--active", true}, + {"abc123い", true}, + {"カタカナ゙ᆲ←", true}, + {"", true}, + } + for _, test := range tests { + actual := HalfWidth(test.param) + if actual != test.expected { + t.Errorf("Expected HalfWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestVariableWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"ひらがなカタカナ漢字ABCDE", true}, + {"3ー0123", true}, + {"Fカタカナ゙ᆲ", true}, + {"", true}, + {"Good=Parts", true}, + {"abc", false}, + {"abc123", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, + {"ひらがな・カタカナ、.漢字", false}, + {"123456", false}, + {"カタカナ゙ᆲ", false}, + } + for _, test := range tests { + actual := VariableWidth(test.param) + if actual != test.expected { + t.Errorf("Expected VariableWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUUID(t *testing.T) { + t.Parallel() + + // Tests without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, + {"a987fbc94bed3078cf079141ba07c9f3", false}, + {"934859", false}, + {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false}, + {"aaaaaaaa-1111-1111-aaag-111111111111", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := UUID(test.param) + if actual != test.expected { + t.Errorf("Expected UUID(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 3 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"412452646", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := UUIDv3(test.param) + if actual != test.expected { + t.Errorf("Expected UUIDv3(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 4 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false}, + {"934859", false}, + {"57b73598-8764-4ad0-a76a-679bb6640eb1", true}, + {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true}, + } + for _, test := range tests { + actual := UUIDv4(test.param) + if actual != test.expected { + t.Errorf("Expected UUIDv4(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 5 + tests = []struct { + param string + expected bool + }{ + + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"9c858901-8a57-4791-81fe-4c455b099bc9", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"987fbc97-4bed-5078-af07-9141ba07c9f3", true}, + {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := UUIDv5(test.param) + if actual != test.expected { + t.Errorf("Expected UUIDv5(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestCreditCard(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"5398228707871528", false}, + {"375556917985515", true}, + {"36050234196908", true}, + {"4716461583322103", true}, + {"4716-2210-5188-5662", true}, + {"4929 7226 5379 7141", true}, + {"5398228707871527", true}, + } + for _, test := range tests { + actual := CreditCard(test.param) + if actual != test.expected { + t.Errorf("Expected CreditCard(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestBN(t *testing.T) { + t.Parallel() + + // Without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3836221195", true}, + {"1-61729-085-8", true}, + {"3 423 21412 0", true}, + {"3 401 01319 X", true}, + {"9784873113685", true}, + {"978-4-87311-368-5", true}, + {"978 3401013190", true}, + {"978-3-8362-2119-1", true}, + } + for _, test := range tests { + actual := ISBN(test.param, -1) + if actual != test.expected { + t.Errorf("Expected ISBN(%q, -1) to be %v, got %v", test.param, test.expected, actual) + } + } + + // ISBN 10 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3423214121", false}, + {"978-3836221191", false}, + {"3-423-21412-1", false}, + {"3 423 21412 1", false}, + {"3836221195", true}, + {"1-61729-085-8", true}, + {"3 423 21412 0", true}, + {"3 401 01319 X", true}, + } + for _, test := range tests { + actual := ISBN10(test.param) + if actual != test.expected { + t.Errorf("Expected ISBN10(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // ISBN 13 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3-8362-2119-5", false}, + {"01234567890ab", false}, + {"978 3 8362 2119 0", false}, + {"9784873113685", true}, + {"978-4-87311-368-5", true}, + {"978 3401013190", true}, + {"978-3-8362-2119-1", true}, + } + for _, test := range tests { + actual := ISBN13(test.param) + if actual != test.expected { + t.Errorf("Expected ISBN13(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestDataURI(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, + {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, + {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, + {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, + {"data:image/png;base64,12345", false}, + {"", false}, + {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, + } + for _, test := range tests { + actual := DataURI(test.param) + if actual != test.expected { + t.Errorf("Expected DataURI(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestBase64(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, + {"Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, + {"U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", true}, + {"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, + {"12345", false}, + {"", false}, + {"Vml2YW11cyBmZXJtZtesting123", false}, + } + for _, test := range tests { + actual := Base64(test.param) + if actual != test.expected { + t.Errorf("Expected Base64(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestO3166Alpha2(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"ABCD", false}, + {"A", false}, + {"AC", false}, + {"AP", false}, + {"GER", false}, + {"NU", true}, + {"DE", true}, + {"JP", true}, + {"JPN", false}, + {"ZWE", false}, + {"GER", false}, + {"DEU", false}, + } + for _, test := range tests { + actual := ISO3166Alpha2(test.param) + if actual != test.expected { + t.Errorf("Expected ISO3166Alpha2(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestO3166Alpha3(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"ABCD", false}, + {"A", false}, + {"AC", false}, + {"AP", false}, + {"NU", false}, + {"DE", false}, + {"JP", false}, + {"ZWE", true}, + {"JPN", true}, + {"GER", false}, + {"DEU", true}, + } + for _, test := range tests { + actual := ISO3166Alpha3(test.param) + if actual != test.expected { + t.Errorf("Expected ISO3166Alpha3(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIP(t *testing.T) { + t.Parallel() + + // Without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", true}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"1.2.3.4", true}, + {"::1", true}, + {"2001:db8:0000:1:1:1:1:1", true}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IP(test.param) + if actual != test.expected { + t.Errorf("Expected IP(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // IPv4 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", true}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"1.2.3.4", true}, + {"::1", false}, + {"2001:db8:0000:1:1:1:1:1", false}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IPv4(test.param) + if actual != test.expected { + t.Errorf("Expected IPv4(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // IPv6 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", false}, + {"0.0.0.0", false}, + {"255.255.255.255", false}, + {"1.2.3.4", false}, + {"::1", true}, + {"2001:db8:0000:1:1:1:1:1", true}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IPv6(test.param) + if actual != test.expected { + t.Errorf("Expected IPv6(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestPort(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"1", true}, + {"65535", true}, + {"0", false}, + {"65536", false}, + {"65538", false}, + } + + for _, test := range tests { + actual := Port(test.param) + if actual != test.expected { + t.Errorf("Expected Port(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestDNSName(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"localhost", true}, + {"localhost.local", true}, + {"localhost.localdomain.intern", true}, + {"-localhost", false}, + {"localhost.-localdomain", false}, + {"localhost.localdomain.-int", false}, + {"_localhost", false}, + {"localhost._localdomain", false}, + {"localhost.localdomain._int", false}, + {"lÖcalhost", false}, + {"localhost.lÖcaldomain", false}, + {"localhost.localdomain.üntern", false}, + {"漢字汉字", false}, + {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de", false}, + } + + for _, test := range tests { + actual := DNSName(test.param) + if actual != test.expected { + t.Errorf("Expected DNS(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestDialString(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"localhost.local:1", true}, + {"localhost.localdomain:9090", true}, + {"localhost.localdomain.intern:65535", true}, + {"127.0.0.1:30000", true}, + {"[::1]:80", true}, + {"[1200::AB00:1234::2552:7777:1313]:22", false}, + {"-localhost:1", false}, + {"localhost.-localdomain:9090", false}, + {"localhost.localdomain.-int:65535", false}, + {"localhost.loc:100000", false}, + {"漢字汉字:2", false}, + {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de:20000", false}, + } + + for _, test := range tests { + actual := DialString(test.param) + if actual != test.expected { + t.Errorf("Expected DialString(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestMAC(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"3D:F2:C9:A6:B3:4F", true}, + {"3D-F2-C9-A6-B3:4F", false}, + {"123", false}, + {"", false}, + {"abacaba", false}, + } + for _, test := range tests { + actual := MAC(test.param) + if actual != test.expected { + t.Errorf("Expected MAC(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestFilePath(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + osType int + }{ + {"c:\\" + strings.Repeat("a", 32767), true, Win}, //See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + {"c:\\" + strings.Repeat("a", 32768), false, Win}, + {"c:\\path\\file (x86)\bar", true, Win}, + {"c:\\path\\file", true, Win}, + {"c:\\path\\file:exe", false, Unknown}, + {"C:\\", true, Win}, + {"c:\\path\\file\\", true, Win}, + {"c:/path/file/", false, Unknown}, + {"/path/file/", true, Unix}, + {"/path/file:SAMPLE/", true, Unix}, + {"/path/file:/.txt", true, Unix}, + {"/path", true, Unix}, + } + for _, test := range tests { + actual, osType := FilePath(test.param) + if actual != test.expected || osType != test.osType { + t.Errorf("Expected FilePath(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestLatitude(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"-90.000", true}, + {"+90", true}, + {"47.1231231", true}, + {"+99.9", false}, + {"108", false}, + } + for _, test := range tests { + actual := Latitude(test.param) + if actual != test.expected { + t.Errorf("Expected Latitude(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestLongitude(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"-180.000", true}, + {"180.1", false}, + {"+73.234", true}, + {"+382.3811", false}, + {"23.11111111", true}, + } + for _, test := range tests { + actual := Longitude(test.param) + if actual != test.expected { + t.Errorf("Expected Longitude(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestSSN(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"00-90-8787", false}, + {"66690-76", false}, + {"191 60 2869", true}, + {"191-60-2869", true}, + } + for _, test := range tests { + actual := SSN(test.param) + if actual != test.expected { + t.Errorf("Expected SSN(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestMongoID(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"507f1f77bcf86cd799439011", true}, + {"507f1f77bcf86cd7994390", false}, + {"507f1f77bcf86cd79943901z", false}, + {"507f1f77bcf86cd799439011 ", false}, + {"", false}, + } + for _, test := range tests { + actual := MongoID(test.param) + if actual != test.expected { + t.Errorf("Expected MongoID(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestSemver(t *testing.T) { + t.Parallel() + var tests = []struct { + param string + expected bool + }{ + {"v1.0.0", true}, + {"1.0.0", true}, + {"1.1.01", false}, + {"1.01.0", false}, + {"01.1.0", false}, + {"v1.1.01", false}, + {"v1.01.0", false}, + {"v01.1.0", false}, + {"1.0.0-alpha", true}, + {"1.0.0-alpha.1", true}, + {"1.0.0-0.3.7", true}, + {"1.0.0-0.03.7", false}, + {"1.0.0-00.3.7", false}, + {"1.0.0-x.7.z.92", true}, + {"1.0.0-alpha+001", true}, + {"1.0.0+20130313144700", true}, + {"1.0.0-beta+exp.sha.5114f85", true}, + {"1.0.0-beta+exp.sha.05114f85", true}, + {"1.0.0-+beta", false}, + {"1.0.0-b+-9+eta", false}, + {"v+1.8.0-b+-9+eta", false}, + } + for _, test := range tests { + actual := Semver(test.param) + if actual != test.expected { + t.Errorf("Expected Semver(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNegative(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, true}, + {10, false}, + {3.14, false}, + {-96, true}, + {-10e-12, true}, + } + for _, test := range tests { + actual := Negative(test.param) + if actual != test.expected { + t.Errorf("Expected Negative(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNonNegative(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, false}, + {10, true}, + {3.14, true}, + {-96, false}, + {-10e-12, false}, + } + for _, test := range tests { + actual := NonNegative(test.param) + if actual != test.expected { + t.Errorf("Expected NonNegative(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestPositive(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, false}, + {10, true}, + {3.14, true}, + {-96, false}, + {-10e-12, false}, + } + for _, test := range tests { + actual := Positive(test.param) + if actual != test.expected { + t.Errorf("Expected Positive(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNonPositive(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, true}, + {10, false}, + {3.14, false}, + {-96, true}, + {-10e-12, true}, + } + for _, test := range tests { + actual := NonPositive(test.param) + if actual != test.expected { + t.Errorf("Expected NonPositive(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestWhole(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, true}, + {10, true}, + {3.14, false}, + {-96, true}, + {-10e-12, false}, + } + for _, test := range tests { + actual := Whole(test.param) + if actual != test.expected { + t.Errorf("Expected Whole(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNatural(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, false}, + {10, true}, + {3.14, false}, + {96, true}, + {-10e-12, false}, + } + for _, test := range tests { + actual := Natural(test.param) + if actual != test.expected { + t.Errorf("Expected Natural(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestInRange(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + left float64 + right float64 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range tests { + actual := InRange(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRange(%q, %q, %q) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) + } + } +} + +func TestMatches(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected bool + }{ + {"123456789", "[0-9]+", true}, + {"abacada", "cab$", false}, + {"111222333", "((111|222|333)+)+", true}, + {"abacaba", "((123+]", false}, + } + for _, test := range tests { + actual := Matches(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected Matches(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestStringLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + value string + min string + max string + expected bool + }{ + {"123456", "0", "100", true}, + {"1239999", "0", "0", false}, + {"1239asdfasf99", "100", "200", false}, + {"1239999asdff29", "10", "30", true}, + {"あいうえお", "0", "5", true}, + {"あいうえおか", "0", "5", false}, + {"あいうえお", "0", "0", false}, + {"あいうえ", "5", "10", false}, + } + for _, test := range tests { + actual := StringLength(test.value, test.min, test.max) + if actual != test.expected { + t.Errorf("Expected StringLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) + } + } +} diff --git a/patterns.go b/patterns.go new file mode 100644 index 0000000..92f8b6c --- /dev/null +++ b/patterns.go @@ -0,0 +1,344 @@ +package is + +import "regexp" + +// ISO3166Entry stores country codes +type ISO3166Entry struct { + EnglishShortName string + FrenchShortName string + Alpha2Code string + Alpha3Code string + Numeric string +} + +//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes" +var ISO3166List = []ISO3166Entry{ + {"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"}, + {"Albania", "Albanie (l')", "AL", "ALB", "008"}, + {"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"}, + {"Algeria", "Algérie (l')", "DZ", "DZA", "012"}, + {"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"}, + {"Andorra", "Andorre (l')", "AD", "AND", "020"}, + {"Angola", "Angola (l')", "AO", "AGO", "024"}, + {"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"}, + {"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"}, + {"Argentina", "Argentine (l')", "AR", "ARG", "032"}, + {"Australia", "Australie (l')", "AU", "AUS", "036"}, + {"Austria", "Autriche (l')", "AT", "AUT", "040"}, + {"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"}, + {"Bahrain", "Bahreïn", "BH", "BHR", "048"}, + {"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"}, + {"Armenia", "Arménie (l')", "AM", "ARM", "051"}, + {"Barbados", "Barbade (la)", "BB", "BRB", "052"}, + {"Belgium", "Belgique (la)", "BE", "BEL", "056"}, + {"Bermuda", "Bermudes (les)", "BM", "BMU", "060"}, + {"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"}, + {"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"}, + {"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"}, + {"Botswana", "Botswana (le)", "BW", "BWA", "072"}, + {"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"}, + {"Brazil", "Brésil (le)", "BR", "BRA", "076"}, + {"Belize", "Belize (le)", "BZ", "BLZ", "084"}, + {"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"}, + {"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"}, + {"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"}, + {"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"}, + {"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"}, + {"Myanmar", "Myanmar (le)", "MM", "MMR", "104"}, + {"Burundi", "Burundi (le)", "BI", "BDI", "108"}, + {"Belarus", "Bélarus (le)", "BY", "BLR", "112"}, + {"Cambodia", "Cambodge (le)", "KH", "KHM", "116"}, + {"Cameroon", "Cameroun (le)", "CM", "CMR", "120"}, + {"Canada", "Canada (le)", "CA", "CAN", "124"}, + {"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"}, + {"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"}, + {"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"}, + {"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"}, + {"Chad", "Tchad (le)", "TD", "TCD", "148"}, + {"Chile", "Chili (le)", "CL", "CHL", "152"}, + {"China", "Chine (la)", "CN", "CHN", "156"}, + {"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"}, + {"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"}, + {"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"}, + {"Colombia", "Colombie (la)", "CO", "COL", "170"}, + {"Comoros (the)", "Comores (les)", "KM", "COM", "174"}, + {"Mayotte", "Mayotte", "YT", "MYT", "175"}, + {"Congo (the)", "Congo (le)", "CG", "COG", "178"}, + {"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"}, + {"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"}, + {"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"}, + {"Croatia", "Croatie (la)", "HR", "HRV", "191"}, + {"Cuba", "Cuba", "CU", "CUB", "192"}, + {"Cyprus", "Chypre", "CY", "CYP", "196"}, + {"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"}, + {"Benin", "Bénin (le)", "BJ", "BEN", "204"}, + {"Denmark", "Danemark (le)", "DK", "DNK", "208"}, + {"Dominica", "Dominique (la)", "DM", "DMA", "212"}, + {"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"}, + {"Ecuador", "Équateur (l')", "EC", "ECU", "218"}, + {"El Salvador", "El Salvador", "SV", "SLV", "222"}, + {"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"}, + {"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"}, + {"Eritrea", "Érythrée (l')", "ER", "ERI", "232"}, + {"Estonia", "Estonie (l')", "EE", "EST", "233"}, + {"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"}, + {"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"}, + {"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"}, + {"Fiji", "Fidji (les)", "FJ", "FJI", "242"}, + {"Finland", "Finlande (la)", "FI", "FIN", "246"}, + {"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"}, + {"France", "France (la)", "FR", "FRA", "250"}, + {"French Guiana", "Guyane française (la )", "GF", "GUF", "254"}, + {"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"}, + {"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"}, + {"Djibouti", "Djibouti", "DJ", "DJI", "262"}, + {"Gabon", "Gabon (le)", "GA", "GAB", "266"}, + {"Georgia", "Géorgie (la)", "GE", "GEO", "268"}, + {"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"}, + {"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"}, + {"Germany", "Allemagne (l')", "DE", "DEU", "276"}, + {"Ghana", "Ghana (le)", "GH", "GHA", "288"}, + {"Gibraltar", "Gibraltar", "GI", "GIB", "292"}, + {"Kiribati", "Kiribati", "KI", "KIR", "296"}, + {"Greece", "Grèce (la)", "GR", "GRC", "300"}, + {"Greenland", "Groenland (le)", "GL", "GRL", "304"}, + {"Grenada", "Grenade (la)", "GD", "GRD", "308"}, + {"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"}, + {"Guam", "Guam", "GU", "GUM", "316"}, + {"Guatemala", "Guatemala (le)", "GT", "GTM", "320"}, + {"Guinea", "Guinée (la)", "GN", "GIN", "324"}, + {"Guyana", "Guyana (le)", "GY", "GUY", "328"}, + {"Haiti", "Haïti", "HT", "HTI", "332"}, + {"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"}, + {"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"}, + {"Honduras", "Honduras (le)", "HN", "HND", "340"}, + {"Hong Kong", "Hong Kong", "HK", "HKG", "344"}, + {"Hungary", "Hongrie (la)", "HU", "HUN", "348"}, + {"Iceland", "Islande (l')", "IS", "ISL", "352"}, + {"India", "Inde (l')", "IN", "IND", "356"}, + {"Indonesia", "Indonésie (l')", "ID", "IDN", "360"}, + {"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"}, + {"Iraq", "Iraq (l')", "IQ", "IRQ", "368"}, + {"Ireland", "Irlande (l')", "IE", "IRL", "372"}, + {"Israel", "Israël", "IL", "ISR", "376"}, + {"Italy", "Italie (l')", "IT", "ITA", "380"}, + {"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"}, + {"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"}, + {"Japan", "Japon (le)", "JP", "JPN", "392"}, + {"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"}, + {"Jordan", "Jordanie (la)", "JO", "JOR", "400"}, + {"Kenya", "Kenya (le)", "KE", "KEN", "404"}, + {"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"}, + {"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"}, + {"Kuwait", "Koweït (le)", "KW", "KWT", "414"}, + {"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"}, + {"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"}, + {"Lebanon", "Liban (le)", "LB", "LBN", "422"}, + {"Lesotho", "Lesotho (le)", "LS", "LSO", "426"}, + {"Latvia", "Lettonie (la)", "LV", "LVA", "428"}, + {"Liberia", "Libéria (le)", "LR", "LBR", "430"}, + {"Libya", "Libye (la)", "LY", "LBY", "434"}, + {"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"}, + {"Lithuania", "Lituanie (la)", "LT", "LTU", "440"}, + {"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"}, + {"Macao", "Macao", "MO", "MAC", "446"}, + {"Madagascar", "Madagascar", "MG", "MDG", "450"}, + {"Malawi", "Malawi (le)", "MW", "MWI", "454"}, + {"Malaysia", "Malaisie (la)", "MY", "MYS", "458"}, + {"Maldives", "Maldives (les)", "MV", "MDV", "462"}, + {"Mali", "Mali (le)", "ML", "MLI", "466"}, + {"Malta", "Malte", "MT", "MLT", "470"}, + {"Martinique", "Martinique (la)", "MQ", "MTQ", "474"}, + {"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"}, + {"Mauritius", "Maurice", "MU", "MUS", "480"}, + {"Mexico", "Mexique (le)", "MX", "MEX", "484"}, + {"Monaco", "Monaco", "MC", "MCO", "492"}, + {"Mongolia", "Mongolie (la)", "MN", "MNG", "496"}, + {"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"}, + {"Montenegro", "Monténégro (le)", "ME", "MNE", "499"}, + {"Montserrat", "Montserrat", "MS", "MSR", "500"}, + {"Morocco", "Maroc (le)", "MA", "MAR", "504"}, + {"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"}, + {"Oman", "Oman", "OM", "OMN", "512"}, + {"Namibia", "Namibie (la)", "NA", "NAM", "516"}, + {"Nauru", "Nauru", "NR", "NRU", "520"}, + {"Nepal", "Népal (le)", "NP", "NPL", "524"}, + {"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"}, + {"Curaçao", "Curaçao", "CW", "CUW", "531"}, + {"Aruba", "Aruba", "AW", "ABW", "533"}, + {"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"}, + {"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"}, + {"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"}, + {"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"}, + {"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"}, + {"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"}, + {"Niger (the)", "Niger (le)", "NE", "NER", "562"}, + {"Nigeria", "Nigéria (le)", "NG", "NGA", "566"}, + {"Niue", "Niue", "NU", "NIU", "570"}, + {"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"}, + {"Norway", "Norvège (la)", "NO", "NOR", "578"}, + {"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"}, + {"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"}, + {"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"}, + {"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"}, + {"Palau", "Palaos (les)", "PW", "PLW", "585"}, + {"Pakistan", "Pakistan (le)", "PK", "PAK", "586"}, + {"Panama", "Panama (le)", "PA", "PAN", "591"}, + {"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"}, + {"Paraguay", "Paraguay (le)", "PY", "PRY", "600"}, + {"Peru", "Pérou (le)", "PE", "PER", "604"}, + {"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"}, + {"Pitcairn", "Pitcairn", "PN", "PCN", "612"}, + {"Poland", "Pologne (la)", "PL", "POL", "616"}, + {"Portugal", "Portugal (le)", "PT", "PRT", "620"}, + {"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"}, + {"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"}, + {"Puerto Rico", "Porto Rico", "PR", "PRI", "630"}, + {"Qatar", "Qatar (le)", "QA", "QAT", "634"}, + {"Réunion", "Réunion (La)", "RE", "REU", "638"}, + {"Romania", "Roumanie (la)", "RO", "ROU", "642"}, + {"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"}, + {"Rwanda", "Rwanda (le)", "RW", "RWA", "646"}, + {"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"}, + {"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"}, + {"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"}, + {"Anguilla", "Anguilla", "AI", "AIA", "660"}, + {"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"}, + {"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"}, + {"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"}, + {"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"}, + {"San Marino", "Saint-Marin", "SM", "SMR", "674"}, + {"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"}, + {"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"}, + {"Senegal", "Sénégal (le)", "SN", "SEN", "686"}, + {"Serbia", "Serbie (la)", "RS", "SRB", "688"}, + {"Seychelles", "Seychelles (les)", "SC", "SYC", "690"}, + {"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"}, + {"Singapore", "Singapour", "SG", "SGP", "702"}, + {"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"}, + {"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"}, + {"Slovenia", "Slovénie (la)", "SI", "SVN", "705"}, + {"Somalia", "Somalie (la)", "SO", "SOM", "706"}, + {"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"}, + {"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"}, + {"Spain", "Espagne (l')", "ES", "ESP", "724"}, + {"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"}, + {"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"}, + {"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"}, + {"Suriname", "Suriname (le)", "SR", "SUR", "740"}, + {"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"}, + {"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"}, + {"Sweden", "Suède (la)", "SE", "SWE", "752"}, + {"Switzerland", "Suisse (la)", "CH", "CHE", "756"}, + {"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"}, + {"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"}, + {"Thailand", "Thaïlande (la)", "TH", "THA", "764"}, + {"Togo", "Togo (le)", "TG", "TGO", "768"}, + {"Tokelau", "Tokelau (les)", "TK", "TKL", "772"}, + {"Tonga", "Tonga (les)", "TO", "TON", "776"}, + {"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"}, + {"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"}, + {"Tunisia", "Tunisie (la)", "TN", "TUN", "788"}, + {"Turkey", "Turquie (la)", "TR", "TUR", "792"}, + {"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"}, + {"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"}, + {"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"}, + {"Uganda", "Ouganda (l')", "UG", "UGA", "800"}, + {"Ukraine", "Ukraine (l')", "UA", "UKR", "804"}, + {"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"}, + {"Egypt", "Égypte (l')", "EG", "EGY", "818"}, + {"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"}, + {"Guernsey", "Guernesey", "GG", "GGY", "831"}, + {"Jersey", "Jersey", "JE", "JEY", "832"}, + {"Isle of Man", "Île de Man", "IM", "IMN", "833"}, + {"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"}, + {"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"}, + {"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"}, + {"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"}, + {"Uruguay", "Uruguay (l')", "UY", "URY", "858"}, + {"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"}, + {"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"}, + {"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"}, + {"Samoa", "Samoa (le)", "WS", "WSM", "882"}, + {"Yemen", "Yémen (le)", "YE", "YEM", "887"}, + {"Zambia", "Zambie (la)", "ZM", "ZMB", "894"}, +} + +// Basic regular expressions for validating strings +const ( + pCreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$" + pISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$" + pISBN13 string = "^(?:[0-9]{13})$" + pUUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" + pUUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + uuid5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + pUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + // pAlpha string = "^[a-zA-Z]+$" + // pAlphanumeric string = "^[a-zA-Z0-9]+$" + // pNumeric string = "^[-+]?[0-9]+$" + pInt string = "^(?:[-+]?(?:0|[1-9][0-9]*))$" + pFloat string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$" + pHexadecimal string = "^[0-9a-fA-F]+$" + pHexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$" + pRGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$" + // pASCII string = "^[\x00-\x7F]+$" + pMultibyte string = "[^\x00-\x7F]" + pFullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" + pHalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" + // pBase64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" + // pPrintableASCII string = "^[\x20-\x7E]+$" + pDataURI string = "^data:.+\\/(.+);base64$" + pLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" + pLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" + pDNSName string = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62}){1}(.[a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62})*$` + pURL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$` + pSSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` + pWinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` + pUnixPath string = `^((?:\/[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$` + pSemver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$" +) + +// Used by IsFilePath func +const ( + // Unknown is unresolved OS type + Unknown = iota + // Win is Windows type + Win + // Unix is *nix OS types + Unix +) + +// Regular expressions patterns +var ( + // rxEmail = regexp.MustCompile(Email) + rxCreditCard = regexp.MustCompile(pCreditCard) + rxISBN10 = regexp.MustCompile(pISBN10) + rxISBN13 = regexp.MustCompile(pISBN13) + rxUUID3 = regexp.MustCompile(pUUID3) + rxUUID4 = regexp.MustCompile(pUUID4) + rxUUID5 = regexp.MustCompile(uuid5) + rxUUID = regexp.MustCompile(pUUID) + // rxAlpha = regexp.MustCompile(Alpha) + // rxAlphanumeric = regexp.MustCompile(Alphanumeric) + // rxNumeric = regexp.MustCompile(Numeric) + rxInt = regexp.MustCompile(pInt) + rxFloat = regexp.MustCompile(pFloat) + rxHexadecimal = regexp.MustCompile(pHexadecimal) + rxHexcolor = regexp.MustCompile(pHexcolor) + rxRGBcolor = regexp.MustCompile(pRGBcolor) + // rxASCII = regexp.MustCompile(ASCII) + // rxPrintableASCII = regexp.MustCompile(PrintableASCII) + rxMultibyte = regexp.MustCompile(pMultibyte) + rxFullWidth = regexp.MustCompile(pFullWidth) + rxHalfWidth = regexp.MustCompile(pHalfWidth) + // rxBase64 = regexp.MustCompile(Base64) + rxDataURI = regexp.MustCompile(pDataURI) + rxLatitude = regexp.MustCompile(pLatitude) + rxLongitude = regexp.MustCompile(pLongitude) + rxDNSName = regexp.MustCompile(pDNSName) + rxURL = regexp.MustCompile(pURL) + rxSSN = regexp.MustCompile(pSSN) + rxWinPath = regexp.MustCompile(pWinPath) + rxUnixPath = regexp.MustCompile(pUnixPath) + rxSemver = regexp.MustCompile(pSemver) +)