Remove dependencies
As separate commit, to make review easier
This commit is contained in:
		
							parent
							
								
									bb7eaaee6c
								
							
						
					
					
						commit
						62adb52ec4
					
				|  | @ -1,14 +0,0 @@ | |||
| language: go | ||||
| 
 | ||||
| go: | ||||
|   - 1.1 | ||||
|   - 1.2 | ||||
|   - 1.3 | ||||
|   - 1.4 | ||||
|   - 1.5 | ||||
|   - 1.6 | ||||
|   - tip | ||||
| 
 | ||||
| notifications: | ||||
|   email: | ||||
|     - bwatas@gmail.com | ||||
|  | @ -1,26 +0,0 @@ | |||
| #### Support | ||||
| If you do have a contribution to the package, feel free to create a Pull Request or an Issue. | ||||
| 
 | ||||
| #### What to contribute | ||||
| If you don't know what to do, there are some features and functions that need to be done | ||||
| 
 | ||||
| - [ ] Refactor code | ||||
| - [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check | ||||
| - [ ] Create actual list of contributors and projects that currently using this package | ||||
| - [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues) | ||||
| - [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions) | ||||
| - [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new | ||||
| - [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc | ||||
| - [ ] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224) | ||||
| - [ ] Implement fuzzing testing | ||||
| - [ ] Implement some struct/map/array utilities | ||||
| - [ ] Implement map/array validation | ||||
| - [ ] Implement benchmarking | ||||
| - [ ] Implement batch of examples | ||||
| - [ ] Look at forks for new features and fixes | ||||
| 
 | ||||
| #### Advice | ||||
| Feel free to create what you want, but keep in mind when you implement new features: | ||||
| - Code must be clear and readable, names of variables/constants clearly describes what they are doing | ||||
| - Public functions must be documented and described in source file and added to README.md to the list of available functions | ||||
| - There are must be unit-tests for any new functions and improvements | ||||
|  | @ -1,21 +0,0 @@ | |||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2014 Alex Saskevich | ||||
| 
 | ||||
| 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. | ||||
|  | @ -1,449 +0,0 @@ | |||
| govalidator | ||||
| =========== | ||||
| [](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://godoc.org/github.com/asaskevich/govalidator) [](https://coveralls.io/r/asaskevich/govalidator?branch=master) [](https://app.wercker.com/project/bykey/1ec990b09ea86c910d5f08b0e02c6043) | ||||
| [](https://travis-ci.org/asaskevich/govalidator) [](https://goreportcard.com/report/github.com/asaskevich/govalidator) [](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) | ||||
| 
 | ||||
| A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js). | ||||
| 
 | ||||
| #### Installation | ||||
| Make sure that Go is installed on your computer. | ||||
| Type the following command in your terminal: | ||||
| 
 | ||||
| 	go get github.com/asaskevich/govalidator | ||||
| 
 | ||||
| or you can get specified release of the package with `gopkg.in`: | ||||
| 
 | ||||
| 	go get gopkg.in/asaskevich/govalidator.v4 | ||||
| 
 | ||||
| After it the package is ready to use. | ||||
| 
 | ||||
| 
 | ||||
| #### Import package in your project | ||||
| Add following line in your `*.go` file: | ||||
| ```go | ||||
| import "github.com/asaskevich/govalidator" | ||||
| ``` | ||||
| If you are unhappy to use long `govalidator`, you can do something like this: | ||||
| ```go | ||||
| import ( | ||||
|   valid "github.com/asaskevich/govalidator" | ||||
| ) | ||||
| ``` | ||||
| 
 | ||||
| #### Activate behavior to require all fields have a validation tag by default | ||||
| `SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function. | ||||
| 
 | ||||
| ```go | ||||
| import "github.com/asaskevich/govalidator" | ||||
| 
 | ||||
| func init() { | ||||
|   govalidator.SetFieldsRequiredByDefault(true) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Here's some code to explain it: | ||||
| ```go | ||||
| // this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter): | ||||
| type exampleStruct struct { | ||||
|   Name  string `` | ||||
|   Email string `valid:"email"` | ||||
| } | ||||
| 
 | ||||
| // this, however, will only fail when Email is empty or an invalid email address: | ||||
| type exampleStruct2 struct { | ||||
|   Name  string `valid:"-"` | ||||
|   Email string `valid:"email"` | ||||
| } | ||||
| 
 | ||||
| // lastly, this will only fail when Email is an invalid email address but not when it's empty: | ||||
| type exampleStruct2 struct { | ||||
|   Name  string `valid:"-"` | ||||
|   Email string `valid:"email,optional"` | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| #### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123)) | ||||
| ##### Custom validator function signature | ||||
| A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible. | ||||
| ```go | ||||
| import "github.com/asaskevich/govalidator" | ||||
| 
 | ||||
| // old signature | ||||
| func(i interface{}) bool | ||||
| 
 | ||||
| // new signature | ||||
| func(i interface{}, o interface{}) bool | ||||
| ``` | ||||
| 
 | ||||
| ##### Adding a custom validator | ||||
| This was changed to prevent data races when accessing custom validators. | ||||
| ```go | ||||
| import "github.com/asaskevich/govalidator" | ||||
| 
 | ||||
| // before | ||||
| govalidator.CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool { | ||||
|   // ... | ||||
| }) | ||||
| 
 | ||||
| // after | ||||
| govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { | ||||
|   // ... | ||||
| })) | ||||
| ``` | ||||
| 
 | ||||
| #### List of functions: | ||||
| ```go | ||||
| func Abs(value float64) float64 | ||||
| func BlackList(str, chars string) string | ||||
| func ByteLength(str string, params ...string) bool | ||||
| func CamelCaseToUnderscore(str string) string | ||||
| func Contains(str, substring string) bool | ||||
| func Count(array []interface{}, iterator ConditionIterator) int | ||||
| func Each(array []interface{}, iterator Iterator) | ||||
| func ErrorByField(e error, field string) string | ||||
| func ErrorsByField(e error) map[string]string | ||||
| func Filter(array []interface{}, iterator ConditionIterator) []interface{} | ||||
| func Find(array []interface{}, iterator ConditionIterator) interface{} | ||||
| func GetLine(s string, index int) (string, error) | ||||
| func GetLines(s string) []string | ||||
| func InRange(value, left, right float64) bool | ||||
| func IsASCII(str string) bool | ||||
| func IsAlpha(str string) bool | ||||
| func IsAlphanumeric(str string) bool | ||||
| func IsBase64(str string) bool | ||||
| func IsByteLength(str string, min, max int) bool | ||||
| func IsCIDR(str string) 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(str 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 IsHost(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 IsISO693Alpha2(str string) bool | ||||
| func IsISO693Alpha3b(str string) bool | ||||
| func IsISO4217(str string) bool | ||||
| func IsIn(str string, params ...string) 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 IsMongoID(str string) bool | ||||
| func IsMultibyte(str 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(str string) bool | ||||
| func IsPort(str string) bool | ||||
| func IsPositive(value float64) bool | ||||
| func IsPrintableASCII(str string) bool | ||||
| func IsRFC3339(str string) bool | ||||
| func IsRFC3339WithoutZone(str 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 IsTime(str string, format string) bool | ||||
| func IsURL(str string) bool | ||||
| func IsUTFDigit(str string) bool | ||||
| func IsUTFLetter(str string) bool | ||||
| func IsUTFLetterNumeric(str string) bool | ||||
| func IsUTFNumeric(str 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 | ||||
| func LeftTrim(str, chars string) string | ||||
| func Map(array []interface{}, iterator ResultIterator) []interface{} | ||||
| func Matches(str, pattern string) bool | ||||
| func NormalizeEmail(str string) (string, error) | ||||
| func PadBoth(str string, padStr string, padLen int) string | ||||
| func PadLeft(str string, padStr string, padLen int) string | ||||
| func PadRight(str string, padStr string, padLen int) string | ||||
| func Range(str string, params ...string) bool | ||||
| func RemoveTags(s string) string | ||||
| func ReplacePattern(str, pattern, replace string) string | ||||
| func Reverse(s string) string | ||||
| func RightTrim(str, chars string) string | ||||
| func RuneLength(str string, params ...string) bool | ||||
| func SafeFileName(str string) string | ||||
| func SetFieldsRequiredByDefault(value bool) | ||||
| func Sign(value float64) float64 | ||||
| func StringLength(str string, params ...string) bool | ||||
| func StringMatches(s string, params ...string) bool | ||||
| func StripLow(str string, keepNewLines bool) string | ||||
| func ToBoolean(str string) (bool, error) | ||||
| func ToFloat(str string) (float64, error) | ||||
| func ToInt(str string) (int64, error) | ||||
| func ToJSON(obj interface{}) (string, error) | ||||
| func ToString(obj interface{}) string | ||||
| func Trim(str, chars string) string | ||||
| func Truncate(str string, length int, ending string) string | ||||
| func UnderscoreToCamelCase(s string) string | ||||
| func ValidateStruct(s interface{}) (bool, error) | ||||
| func WhiteList(str, chars string) string | ||||
| type ConditionIterator | ||||
| type CustomTypeValidator | ||||
| type Error | ||||
| func (e Error) Error() string | ||||
| type Errors | ||||
| func (es Errors) Error() string | ||||
| func (es Errors) Errors() []error | ||||
| type ISO3166Entry | ||||
| type Iterator | ||||
| type ParamValidator | ||||
| type ResultIterator | ||||
| type UnsupportedTypeError | ||||
| func (e *UnsupportedTypeError) Error() string | ||||
| type Validator | ||||
| ``` | ||||
| 
 | ||||
| #### Examples | ||||
| ###### IsURL | ||||
| ```go | ||||
| println(govalidator.IsURL(`http://user@pass:domain.com/path/page`)) | ||||
| ``` | ||||
| ###### ToString | ||||
| ```go | ||||
| type User struct { | ||||
| 	FirstName string | ||||
| 	LastName string | ||||
| } | ||||
| 
 | ||||
| str := govalidator.ToString(&User{"John", "Juan"}) | ||||
| println(str) | ||||
| ``` | ||||
| ###### Each, Map, Filter, Count for slices | ||||
| Each iterates over the slice/array and calls Iterator for every item | ||||
| ```go | ||||
| data := []interface{}{1, 2, 3, 4, 5} | ||||
| var fn govalidator.Iterator = func(value interface{}, index int) { | ||||
| 	println(value.(int)) | ||||
| } | ||||
| govalidator.Each(data, fn) | ||||
| ``` | ||||
| ```go | ||||
| data := []interface{}{1, 2, 3, 4, 5} | ||||
| var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} { | ||||
| 	return value.(int) * 3 | ||||
| } | ||||
| _ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15} | ||||
| ``` | ||||
| ```go | ||||
| data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||||
| var fn govalidator.ConditionIterator = func(value interface{}, index int) bool { | ||||
| 	return value.(int)%2 == 0 | ||||
| } | ||||
| _ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10} | ||||
| _ = govalidator.Count(data, fn) // result = 5 | ||||
| ``` | ||||
| ###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2) | ||||
| If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this: | ||||
| ```go | ||||
| govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { | ||||
| 	return str == "duck" | ||||
| }) | ||||
| ``` | ||||
| For completely custom validators (interface-based), see below. | ||||
| 
 | ||||
| Here is a list of available validators for struct fields (validator - used function): | ||||
| ```go | ||||
| "email":              IsEmail, | ||||
| "url":                IsURL, | ||||
| "dialstring":         IsDialString, | ||||
| "requrl":             IsRequestURL, | ||||
| "requri":             IsRequestURI, | ||||
| "alpha":              IsAlpha, | ||||
| "utfletter":          IsUTFLetter, | ||||
| "alphanum":           IsAlphanumeric, | ||||
| "utfletternum":       IsUTFLetterNumeric, | ||||
| "numeric":            IsNumeric, | ||||
| "utfnumeric":         IsUTFNumeric, | ||||
| "utfdigit":           IsUTFDigit, | ||||
| "hexadecimal":        IsHexadecimal, | ||||
| "hexcolor":           IsHexcolor, | ||||
| "rgbcolor":           IsRGBcolor, | ||||
| "lowercase":          IsLowerCase, | ||||
| "uppercase":          IsUpperCase, | ||||
| "int":                IsInt, | ||||
| "float":              IsFloat, | ||||
| "null":               IsNull, | ||||
| "uuid":               IsUUID, | ||||
| "uuidv3":             IsUUIDv3, | ||||
| "uuidv4":             IsUUIDv4, | ||||
| "uuidv5":             IsUUIDv5, | ||||
| "creditcard":         IsCreditCard, | ||||
| "isbn10":             IsISBN10, | ||||
| "isbn13":             IsISBN13, | ||||
| "json":               IsJSON, | ||||
| "multibyte":          IsMultibyte, | ||||
| "ascii":              IsASCII, | ||||
| "printableascii":     IsPrintableASCII, | ||||
| "fullwidth":          IsFullWidth, | ||||
| "halfwidth":          IsHalfWidth, | ||||
| "variablewidth":      IsVariableWidth, | ||||
| "base64":             IsBase64, | ||||
| "datauri":            IsDataURI, | ||||
| "ip":                 IsIP, | ||||
| "port":               IsPort, | ||||
| "ipv4":               IsIPv4, | ||||
| "ipv6":               IsIPv6, | ||||
| "dns":                IsDNSName, | ||||
| "host":               IsHost, | ||||
| "mac":                IsMAC, | ||||
| "latitude":           IsLatitude, | ||||
| "longitude":          IsLongitude, | ||||
| "ssn":                IsSSN, | ||||
| "semver":             IsSemver, | ||||
| "rfc3339":            IsRFC3339, | ||||
| "rfc3339WithoutZone": IsRFC3339WithoutZone, | ||||
| "ISO3166Alpha2":      IsISO3166Alpha2, | ||||
| "ISO3166Alpha3":      IsISO3166Alpha3, | ||||
| ``` | ||||
| Validators with parameters | ||||
| 
 | ||||
| ```go | ||||
| "range(min|max)": Range, | ||||
| "length(min|max)": ByteLength, | ||||
| "runelength(min|max)": RuneLength, | ||||
| "matches(pattern)": StringMatches, | ||||
| "in(string1|string2|...|stringN)": IsIn, | ||||
| ``` | ||||
| 
 | ||||
| And here is small example of usage: | ||||
| ```go | ||||
| type Post struct { | ||||
| 	Title    string `valid:"alphanum,required"` | ||||
| 	Message  string `valid:"duck,ascii"` | ||||
| 	AuthorIP string `valid:"ipv4"` | ||||
| 	Date     string `valid:"-"` | ||||
| } | ||||
| post := &Post{ | ||||
| 	Title:   "My Example Post", | ||||
| 	Message: "duck", | ||||
| 	AuthorIP: "123.234.54.3", | ||||
| } | ||||
| 
 | ||||
| // Add your own struct validation tags | ||||
| govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { | ||||
| 	return str == "duck" | ||||
| }) | ||||
| 
 | ||||
| result, err := govalidator.ValidateStruct(post) | ||||
| if err != nil { | ||||
| 	println("error: " + err.Error()) | ||||
| } | ||||
| println(result) | ||||
| ``` | ||||
| ###### WhiteList | ||||
| ```go | ||||
| // Remove all characters from string ignoring characters between "a" and "z" | ||||
| println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa") | ||||
| ``` | ||||
| 
 | ||||
| ###### Custom validation functions | ||||
| Custom validation using your own domain specific validators is also available - here's an example of how to use it: | ||||
| ```go | ||||
| import "github.com/asaskevich/govalidator" | ||||
| 
 | ||||
| type CustomByteArray [6]byte // custom types are supported and can be validated | ||||
| 
 | ||||
| type StructWithCustomByteArray struct { | ||||
|   ID              CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence | ||||
|   Email           string          `valid:"email"` | ||||
|   CustomMinLength int             `valid:"-"` | ||||
| } | ||||
| 
 | ||||
| govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool { | ||||
|   switch v := context.(type) { // you can type switch on the context interface being validated | ||||
|   case StructWithCustomByteArray: | ||||
|     // you can check and validate against some other field in the context, | ||||
|     // return early or not validate against the context at all – your choice | ||||
|   case SomeOtherType: | ||||
|     // ... | ||||
|   default: | ||||
|     // expecting some other type? Throw/panic here or continue | ||||
|   } | ||||
| 
 | ||||
|   switch v := i.(type) { // type switch on the struct field being validated | ||||
|   case CustomByteArray: | ||||
|     for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes | ||||
|       if e != 0 { | ||||
|         return true | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return false | ||||
| })) | ||||
| govalidator.CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool { | ||||
|   switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation | ||||
|   case StructWithCustomByteArray: | ||||
|     return len(v.ID) >= v.CustomMinLength | ||||
|   } | ||||
|   return false | ||||
| })) | ||||
| ``` | ||||
| 
 | ||||
| #### Notes | ||||
| Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator). | ||||
| Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator). | ||||
| 
 | ||||
| #### Support | ||||
| If you do have a contribution to the package, feel free to create a Pull Request or an Issue. | ||||
| 
 | ||||
| #### What to contribute | ||||
| If you don't know what to do, there are some features and functions that need to be done | ||||
| 
 | ||||
| - [ ] Refactor code | ||||
| - [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check | ||||
| - [ ] Create actual list of contributors and projects that currently using this package | ||||
| - [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues) | ||||
| - [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions) | ||||
| - [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new | ||||
| - [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc | ||||
| - [ ] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224) | ||||
| - [ ] Implement fuzzing testing | ||||
| - [ ] Implement some struct/map/array utilities | ||||
| - [ ] Implement map/array validation | ||||
| - [ ] Implement benchmarking | ||||
| - [ ] Implement batch of examples | ||||
| - [ ] Look at forks for new features and fixes | ||||
| 
 | ||||
| #### Advice | ||||
| Feel free to create what you want, but keep in mind when you implement new features: | ||||
| - Code must be clear and readable, names of variables/constants clearly describes what they are doing | ||||
| - Public functions must be documented and described in source file and added to README.md to the list of available functions | ||||
| - There are must be unit-tests for any new functions and improvements | ||||
| 
 | ||||
| #### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors) | ||||
| * [Daniel Lohse](https://github.com/annismckenzie) | ||||
| * [Attila Oláh](https://github.com/attilaolah) | ||||
| * [Daniel Korner](https://github.com/Dadie) | ||||
| * [Steven Wilkin](https://github.com/stevenwilkin) | ||||
| * [Deiwin Sarjas](https://github.com/deiwin) | ||||
| * [Noah Shibley](https://github.com/slugmobile) | ||||
| * [Nathan Davies](https://github.com/nathj07) | ||||
| * [Matt Sanford](https://github.com/mzsanford) | ||||
| * [Simon ccl1115](https://github.com/ccl1115) | ||||
|  | @ -1,58 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| // Iterator is the function that accepts element of slice/array and its index
 | ||||
| type Iterator func(interface{}, int) | ||||
| 
 | ||||
| // ResultIterator is the function that accepts element of slice/array and its index and returns any result
 | ||||
| type ResultIterator func(interface{}, int) interface{} | ||||
| 
 | ||||
| // ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
 | ||||
| type ConditionIterator func(interface{}, int) bool | ||||
| 
 | ||||
| // Each iterates over the slice and apply Iterator to every item
 | ||||
| func Each(array []interface{}, iterator Iterator) { | ||||
| 	for index, data := range array { | ||||
| 		iterator(data, index) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
 | ||||
| func Map(array []interface{}, iterator ResultIterator) []interface{} { | ||||
| 	var result = make([]interface{}, len(array)) | ||||
| 	for index, data := range array { | ||||
| 		result[index] = iterator(data, index) | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| // Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
 | ||||
| func Find(array []interface{}, iterator ConditionIterator) interface{} { | ||||
| 	for index, data := range array { | ||||
| 		if iterator(data, index) { | ||||
| 			return data | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
 | ||||
| func Filter(array []interface{}, iterator ConditionIterator) []interface{} { | ||||
| 	var result = make([]interface{}, 0) | ||||
| 	for index, data := range array { | ||||
| 		if iterator(data, index) { | ||||
| 			result = append(result, data) | ||||
| 		} | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| // Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
 | ||||
| func Count(array []interface{}, iterator ConditionIterator) int { | ||||
| 	count := 0 | ||||
| 	for index, data := range array { | ||||
| 		if iterator(data, index) { | ||||
| 			count = count + 1 | ||||
| 		} | ||||
| 	} | ||||
| 	return count | ||||
| } | ||||
|  | @ -1,116 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import "testing" | ||||
| 
 | ||||
| func TestEach(t *testing.T) { | ||||
| 	// TODO Maybe refactor?
 | ||||
| 	t.Parallel() | ||||
| 	acc := 0 | ||||
| 	data := []interface{}{1, 2, 3, 4, 5} | ||||
| 	var fn Iterator = func(value interface{}, index int) { | ||||
| 		acc = acc + value.(int) | ||||
| 	} | ||||
| 	Each(data, fn) | ||||
| 	if acc != 15 { | ||||
| 		t.Errorf("Expected Each(..) to be %v, got %v", 15, acc) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ExampleEach() { | ||||
| 	data := []interface{}{1, 2, 3, 4, 5} | ||||
| 	var fn Iterator = func(value interface{}, index int) { | ||||
| 		println(value.(int)) | ||||
| 	} | ||||
| 	Each(data, fn) | ||||
| } | ||||
| 
 | ||||
| func TestMap(t *testing.T) { | ||||
| 	// TODO Maybe refactor?
 | ||||
| 	t.Parallel() | ||||
| 	data := []interface{}{1, 2, 3, 4, 5} | ||||
| 	var fn ResultIterator = func(value interface{}, index int) interface{} { | ||||
| 		return value.(int) * 3 | ||||
| 	} | ||||
| 	result := Map(data, fn) | ||||
| 	for i, d := range result { | ||||
| 		if d != fn(data[i], i) { | ||||
| 			t.Errorf("Expected Map(..) to be %v, got %v", fn(data[i], i), d) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ExampleMap() { | ||||
| 	data := []interface{}{1, 2, 3, 4, 5} | ||||
| 	var fn ResultIterator = func(value interface{}, index int) interface{} { | ||||
| 		return value.(int) * 3 | ||||
| 	} | ||||
| 	_ = Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
 | ||||
| } | ||||
| 
 | ||||
| func TestFind(t *testing.T) { | ||||
| 	// TODO Maybe refactor?
 | ||||
| 	t.Parallel() | ||||
| 	findElement := 96 | ||||
| 	data := []interface{}{1, 2, 3, 4, findElement, 5} | ||||
| 	var fn1 ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		return value.(int) == findElement | ||||
| 	} | ||||
| 	var fn2 ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		value, _ = value.(string) | ||||
| 		return value == "govalidator" | ||||
| 	} | ||||
| 	val1 := Find(data, fn1) | ||||
| 	val2 := Find(data, fn2) | ||||
| 	if val1 != findElement { | ||||
| 		t.Errorf("Expected Find(..) to be %v, got %v", findElement, val1) | ||||
| 	} | ||||
| 	if val2 != nil { | ||||
| 		t.Errorf("Expected Find(..) to be %v, got %v", nil, val2) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFilter(t *testing.T) { | ||||
| 	// TODO Maybe refactor?
 | ||||
| 	t.Parallel() | ||||
| 	data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||||
| 	answer := []interface{}{2, 4, 6, 8, 10} | ||||
| 	var fn ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		return value.(int)%2 == 0 | ||||
| 	} | ||||
| 	result := Filter(data, fn) | ||||
| 	for i := range result { | ||||
| 		if result[i] != answer[i] { | ||||
| 			t.Errorf("Expected Filter(..) to be %v, got %v", answer[i], result[i]) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ExampleFilter() { | ||||
| 	data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||||
| 	var fn ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		return value.(int)%2 == 0 | ||||
| 	} | ||||
| 	_ = Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
 | ||||
| } | ||||
| 
 | ||||
| func TestCount(t *testing.T) { | ||||
| 	// TODO Maybe refactor?
 | ||||
| 	t.Parallel() | ||||
| 	data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||||
| 	count := 5 | ||||
| 	var fn ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		return value.(int)%2 == 0 | ||||
| 	} | ||||
| 	result := Count(data, fn) | ||||
| 	if result != count { | ||||
| 		t.Errorf("Expected Count(..) to be %v, got %v", count, result) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ExampleCount() { | ||||
| 	data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||||
| 	var fn ConditionIterator = func(value interface{}, index int) bool { | ||||
| 		return value.(int)%2 == 0 | ||||
| 	} | ||||
| 	_ = Count(data, fn) // result = 5
 | ||||
| } | ||||
|  | @ -1,45 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // ToString convert the input to a string.
 | ||||
| func ToString(obj interface{}) string { | ||||
| 	res := fmt.Sprintf("%v", obj) | ||||
| 	return string(res) | ||||
| } | ||||
| 
 | ||||
| // ToJSON convert the input to a valid JSON string
 | ||||
| func ToJSON(obj interface{}) (string, error) { | ||||
| 	res, err := json.Marshal(obj) | ||||
| 	if err != nil { | ||||
| 		res = []byte("") | ||||
| 	} | ||||
| 	return string(res), err | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
| 
 | ||||
| // ToBoolean convert the input string to a boolean.
 | ||||
| func ToBoolean(str string) (bool, error) { | ||||
| 	return strconv.ParseBool(str) | ||||
| } | ||||
|  | @ -1,78 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestToInt(t *testing.T) { | ||||
| 	tests := []string{"1000", "-123", "abcdef", "100000000000000000000000000000000000000000000"} | ||||
| 	expected := []int64{1000, -123, 0, 0} | ||||
| 	for i := 0; i < len(tests); i++ { | ||||
| 		result, _ := ToInt(tests[i]) | ||||
| 		if result != expected[i] { | ||||
| 			t.Log("Case ", i, ": expected ", expected[i], " when result is ", result) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestToBoolean(t *testing.T) { | ||||
| 	tests := []string{"true", "1", "True", "false", "0", "abcdef"} | ||||
| 	expected := []bool{true, true, true, false, false, false} | ||||
| 	for i := 0; i < len(tests); i++ { | ||||
| 		res, _ := ToBoolean(tests[i]) | ||||
| 		if res != expected[i] { | ||||
| 			t.Log("Case ", i, ": expected ", expected[i], " when result is ", res) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func toString(t *testing.T, test interface{}, expected string) { | ||||
| 	res := ToString(test) | ||||
| 	if res != expected { | ||||
| 		t.Log("Case ToString: expected ", expected, " when result is ", res) | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestToString(t *testing.T) { | ||||
| 	toString(t, "str123", "str123") | ||||
| 	toString(t, 123, "123") | ||||
| 	toString(t, 12.3, "12.3") | ||||
| 	toString(t, true, "true") | ||||
| 	toString(t, 1.5+10i, "(1.5+10i)") | ||||
| 	// Sprintf function not guarantee that maps with equal keys always will be equal in string  representation
 | ||||
| 	//toString(t, struct{ Keys map[int]int }{Keys: map[int]int{1: 2, 3: 4}}, "{map[1:2 3:4]}")
 | ||||
| } | ||||
| 
 | ||||
| func TestToFloat(t *testing.T) { | ||||
| 	tests := []string{"", "123", "-.01", "10.", "string", "1.23e3", ".23e10"} | ||||
| 	expected := []float64{0, 123, -0.01, 10.0, 0, 1230, 0.23e10} | ||||
| 	for i := 0; i < len(tests); i++ { | ||||
| 		res, _ := ToFloat(tests[i]) | ||||
| 		if res != expected[i] { | ||||
| 			t.Log("Case ", i, ": expected ", expected[i], " when result is ", res) | ||||
| 			t.FailNow() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestToJSON(t *testing.T) { | ||||
| 	tests := []interface{}{"test", map[string]string{"a": "b", "b": "c"}, func() error { return fmt.Errorf("Error") }} | ||||
| 	expected := [][]string{ | ||||
| 		{"\"test\"", "<nil>"}, | ||||
| 		{"{\"a\":\"b\",\"b\":\"c\"}", "<nil>"}, | ||||
| 		{"", "json: unsupported type: func() error"}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		actual, err := ToJSON(test) | ||||
| 		if actual != expected[i][0] { | ||||
| 			t.Errorf("Expected toJSON(%v) to return '%v', got '%v'", test, expected[i][0], actual) | ||||
| 		} | ||||
| 		if fmt.Sprintf("%v", err) != expected[i][1] { | ||||
| 			t.Errorf("Expected error returned from toJSON(%v) to return '%v', got '%v'", test, expected[i][1], fmt.Sprintf("%v", err)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,36 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| // Errors is an array of multiple errors and conforms to the error interface.
 | ||||
| type Errors []error | ||||
| 
 | ||||
| // Errors returns itself.
 | ||||
| func (es Errors) Errors() []error { | ||||
| 	return es | ||||
| } | ||||
| 
 | ||||
| func (es Errors) Error() string { | ||||
| 	var errs []string | ||||
| 	for _, e := range es { | ||||
| 		errs = append(errs, e.Error()) | ||||
| 	} | ||||
| 	return strings.Join(errs, ";") | ||||
| } | ||||
| 
 | ||||
| // Error encapsulates a name, an error and whether there's a custom error message or not.
 | ||||
| type Error struct { | ||||
| 	Name                     string | ||||
| 	Err                      error | ||||
| 	CustomErrorMessageExists bool | ||||
| 
 | ||||
| 	// Validator indicates the name of the validator that failed
 | ||||
| 	Validator string | ||||
| } | ||||
| 
 | ||||
| func (e Error) Error() string { | ||||
| 	if e.CustomErrorMessageExists { | ||||
| 		return e.Err.Error() | ||||
| 	} | ||||
| 	return e.Name + ": " + e.Err.Error() | ||||
| } | ||||
|  | @ -1,29 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestErrorsToString(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	customErr := &Error{Name: "Custom Error Name", Err: fmt.Errorf("stdlib error")} | ||||
| 	customErrWithCustomErrorMessage := &Error{Name: "Custom Error Name 2", Err: fmt.Errorf("Bad stuff happened"), CustomErrorMessageExists: true} | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   Errors | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{Errors{}, ""}, | ||||
| 		{Errors{fmt.Errorf("Error 1")}, "Error 1"}, | ||||
| 		{Errors{fmt.Errorf("Error 1"), fmt.Errorf("Error 2")}, "Error 1;Error 2"}, | ||||
| 		{Errors{customErr, fmt.Errorf("Error 2")}, "Custom Error Name: stdlib error;Error 2"}, | ||||
| 		{Errors{fmt.Errorf("Error 123"), customErrWithCustomErrorMessage}, "Error 123;Bad stuff happened"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := test.param1.Error() | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Error() to return '%v', got '%v'", test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,94 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| ) | ||||
| 
 | ||||
| // Abs returns absolute value of number
 | ||||
| func Abs(value float64) float64 { | ||||
| 	return math.Abs(value) | ||||
| } | ||||
| 
 | ||||
| // Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise
 | ||||
| func Sign(value float64) float64 { | ||||
| 	if value > 0 { | ||||
| 		return 1 | ||||
| 	} else if value < 0 { | ||||
| 		return -1 | ||||
| 	} else { | ||||
| 		return 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // IsNegative returns true if value < 0
 | ||||
| func IsNegative(value float64) bool { | ||||
| 	return value < 0 | ||||
| } | ||||
| 
 | ||||
| // IsPositive returns true if value > 0
 | ||||
| func IsPositive(value float64) bool { | ||||
| 	return value > 0 | ||||
| } | ||||
| 
 | ||||
| // IsNonNegative returns true if value >= 0
 | ||||
| func IsNonNegative(value float64) bool { | ||||
| 	return value >= 0 | ||||
| } | ||||
| 
 | ||||
| // IsNonPositive returns true if value <= 0
 | ||||
| func IsNonPositive(value float64) bool { | ||||
| 	return value <= 0 | ||||
| } | ||||
| 
 | ||||
| // InRange returns true if value lies between left and right border
 | ||||
| func InRangeInt(value, left, right int) bool { | ||||
| 	if left > right { | ||||
| 		left, right = right, left | ||||
| 	} | ||||
| 	return value >= left && value <= right | ||||
| } | ||||
| 
 | ||||
| // InRange returns true if value lies between left and right border
 | ||||
| func InRangeFloat32(value, left, right float32) bool { | ||||
| 	if left > right { | ||||
| 		left, right = right, left | ||||
| 	} | ||||
| 	return value >= left && value <= right | ||||
| } | ||||
| 
 | ||||
| // InRange returns true if value lies between left and right border
 | ||||
| func InRangeFloat64(value, left, right float64) bool { | ||||
| 	if left > right { | ||||
| 		left, right = right, left | ||||
| 	} | ||||
| 	return value >= left && value <= right | ||||
| } | ||||
| 
 | ||||
| // InRange returns true if value lies between left and right border, generic type to handle int, float32 or float64, all types must the same type
 | ||||
| func InRange(value interface{}, left interface{}, right interface{}) bool { | ||||
| 
 | ||||
| 	reflectValue := reflect.TypeOf(value).Kind() | ||||
| 	reflectLeft := reflect.TypeOf(left).Kind() | ||||
| 	reflectRight := reflect.TypeOf(right).Kind() | ||||
| 
 | ||||
| 	if reflectValue == reflect.Int && reflectLeft == reflect.Int && reflectRight == reflect.Int { | ||||
| 		return InRangeInt(value.(int), left.(int), right.(int)) | ||||
| 	} else if reflectValue == reflect.Float32 && reflectLeft == reflect.Float32 && reflectRight == reflect.Float32 { | ||||
| 		return InRangeFloat32(value.(float32), left.(float32), right.(float32)) | ||||
| 	} else if reflectValue == reflect.Float64 && reflectLeft == reflect.Float64 && reflectRight == reflect.Float64 { | ||||
| 		return InRangeFloat64(value.(float64), left.(float64), right.(float64)) | ||||
| 	} else { | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // IsWhole returns true if value is whole number
 | ||||
| func IsWhole(value float64) bool { | ||||
| 	return math.Remainder(value, 1) == 0 | ||||
| } | ||||
| 
 | ||||
| // IsNatural returns true if value is natural number (positive and whole)
 | ||||
| func IsNatural(value float64) bool { | ||||
| 	return IsWhole(value) && IsPositive(value) | ||||
| } | ||||
|  | @ -1,349 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import "testing" | ||||
| 
 | ||||
| func TestAbs(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    float64 | ||||
| 		expected float64 | ||||
| 	}{ | ||||
| 		{0, 0}, | ||||
| 		{-1, 1}, | ||||
| 		{10, 10}, | ||||
| 		{3.14, 3.14}, | ||||
| 		{-96, 96}, | ||||
| 		{-10e-12, 10e-12}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Abs(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Abs(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestSign(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    float64 | ||||
| 		expected float64 | ||||
| 	}{ | ||||
| 		{0, 0}, | ||||
| 		{-1, -1}, | ||||
| 		{10, 1}, | ||||
| 		{3.14, 1}, | ||||
| 		{-96, -1}, | ||||
| 		{-10e-12, -1}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Sign(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Sign(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsNegative(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 := IsNegative(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsNegative(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsNonNegative(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 := IsNonNegative(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsNonNegative(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsPositive(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 := IsPositive(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsPositive(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsNonPositive(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 := IsNonPositive(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsNonPositive(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsWhole(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 := IsWhole(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsWhole(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestIsNatural(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 := IsNatural(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected IsNatural(%v) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestInRangeInt(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    int | ||||
| 		left     int | ||||
| 		right    int | ||||
| 		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 := InRangeInt(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestInRangeFloat32(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    float32 | ||||
| 		left     float32 | ||||
| 		right    float32 | ||||
| 		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 := InRangeFloat32(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRangeFloat32(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestInRangeFloat64(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 := InRangeFloat64(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRangeFloat64(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestInRange(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var testsInt = []struct { | ||||
| 		param    int | ||||
| 		left     int | ||||
| 		right    int | ||||
| 		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 testsInt { | ||||
| 		actual := InRange(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var testsFloat32 = []struct { | ||||
| 		param    float32 | ||||
| 		left     float32 | ||||
| 		right    float32 | ||||
| 		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 testsFloat32 { | ||||
| 		actual := InRange(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var testsFloat64 = []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 testsFloat64 { | ||||
| 		actual := InRange(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var testsTypeMix = []struct { | ||||
| 		param    int | ||||
| 		left     float64 | ||||
| 		right    float64 | ||||
| 		expected bool | ||||
| 	}{ | ||||
| 		{0, 0, 0, false}, | ||||
| 		{1, 0, 0, false}, | ||||
| 		{-1, 0, 0, false}, | ||||
| 		{0, -1, 1, false}, | ||||
| 		{0, 0, 1, false}, | ||||
| 		{0, -1, 0, false}, | ||||
| 		{0, 0, -1, false}, | ||||
| 		{0, 10, 5, false}, | ||||
| 	} | ||||
| 	for _, test := range testsTypeMix { | ||||
| 		actual := InRange(test.param, test.left, test.right) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,90 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import "regexp" | ||||
| 
 | ||||
| // Basic regular expressions for validating strings
 | ||||
| const ( | ||||
| 	Email          string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" | ||||
| 	CreditCard     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})$" | ||||
| 	ISBN10         string = "^(?:[0-9]{9}X|[0-9]{10})$" | ||||
| 	ISBN13         string = "^(?:[0-9]{13})$" | ||||
| 	UUID3          string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" | ||||
| 	UUID4          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}$" | ||||
| 	UUID           string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" | ||||
| 	Alpha          string = "^[a-zA-Z]+$" | ||||
| 	Alphanumeric   string = "^[a-zA-Z0-9]+$" | ||||
| 	Numeric        string = "^[0-9]+$" | ||||
| 	Int            string = "^(?:[-+]?(?:0|[1-9][0-9]*))$" | ||||
| 	Float          string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$" | ||||
| 	Hexadecimal    string = "^[0-9a-fA-F]+$" | ||||
| 	Hexcolor       string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$" | ||||
| 	RGBcolor       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*\\)$" | ||||
| 	ASCII          string = "^[\x00-\x7F]+$" | ||||
| 	Multibyte      string = "[^\x00-\x7F]" | ||||
| 	FullWidth      string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" | ||||
| 	HalfWidth      string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" | ||||
| 	Base64         string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" | ||||
| 	PrintableASCII string = "^[\x20-\x7E]+$" | ||||
| 	DataURI        string = "^data:.+\\/(.+);base64$" | ||||
| 	Latitude       string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" | ||||
| 	Longitude      string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" | ||||
| 	DNSName        string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$` | ||||
| 	IP             string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))` | ||||
| 	URLSchema      string = `((ftp|tcp|udp|wss?|https?):\/\/)` | ||||
| 	URLUsername    string = `(\S+(:\S*)?@)` | ||||
| 	URLPath        string = `((\/|\?|#)[^\s]*)` | ||||
| 	URLPort        string = `(:(\d{1,5}))` | ||||
| 	URLIP          string = `([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]))` | ||||
| 	URLSubdomain   string = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))` | ||||
| 	URL            string = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$` | ||||
| 	SSN            string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` | ||||
| 	WinPath        string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` | ||||
| 	UnixPath       string = `^(/[^/\x00]*)+/?$` | ||||
| 	Semver         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-]+)*)?$" | ||||
| 	tagName        string = "valid" | ||||
| ) | ||||
| 
 | ||||
| // Used by IsFilePath func
 | ||||
| const ( | ||||
| 	// Unknown is unresolved OS type
 | ||||
| 	Unknown = iota | ||||
| 	// Win is Windows type
 | ||||
| 	Win | ||||
| 	// Unix is *nix OS types
 | ||||
| 	Unix | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	rxEmail          = regexp.MustCompile(Email) | ||||
| 	rxCreditCard     = regexp.MustCompile(CreditCard) | ||||
| 	rxISBN10         = regexp.MustCompile(ISBN10) | ||||
| 	rxISBN13         = regexp.MustCompile(ISBN13) | ||||
| 	rxUUID3          = regexp.MustCompile(UUID3) | ||||
| 	rxUUID4          = regexp.MustCompile(UUID4) | ||||
| 	rxUUID5          = regexp.MustCompile(UUID5) | ||||
| 	rxUUID           = regexp.MustCompile(UUID) | ||||
| 	rxAlpha          = regexp.MustCompile(Alpha) | ||||
| 	rxAlphanumeric   = regexp.MustCompile(Alphanumeric) | ||||
| 	rxNumeric        = regexp.MustCompile(Numeric) | ||||
| 	rxInt            = regexp.MustCompile(Int) | ||||
| 	rxFloat          = regexp.MustCompile(Float) | ||||
| 	rxHexadecimal    = regexp.MustCompile(Hexadecimal) | ||||
| 	rxHexcolor       = regexp.MustCompile(Hexcolor) | ||||
| 	rxRGBcolor       = regexp.MustCompile(RGBcolor) | ||||
| 	rxASCII          = regexp.MustCompile(ASCII) | ||||
| 	rxPrintableASCII = regexp.MustCompile(PrintableASCII) | ||||
| 	rxMultibyte      = regexp.MustCompile(Multibyte) | ||||
| 	rxFullWidth      = regexp.MustCompile(FullWidth) | ||||
| 	rxHalfWidth      = regexp.MustCompile(HalfWidth) | ||||
| 	rxBase64         = regexp.MustCompile(Base64) | ||||
| 	rxDataURI        = regexp.MustCompile(DataURI) | ||||
| 	rxLatitude       = regexp.MustCompile(Latitude) | ||||
| 	rxLongitude      = regexp.MustCompile(Longitude) | ||||
| 	rxDNSName        = regexp.MustCompile(DNSName) | ||||
| 	rxURL            = regexp.MustCompile(URL) | ||||
| 	rxSSN            = regexp.MustCompile(SSN) | ||||
| 	rxWinPath        = regexp.MustCompile(WinPath) | ||||
| 	rxUnixPath       = regexp.MustCompile(UnixPath) | ||||
| 	rxSemver         = regexp.MustCompile(Semver) | ||||
| ) | ||||
|  | @ -1,616 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"regexp" | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| // Validator is a wrapper for a validator function that returns bool and accepts string.
 | ||||
| type Validator func(str string) bool | ||||
| 
 | ||||
| // CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type.
 | ||||
| // The second parameter should be the context (in the case of validating a struct: the whole object being validated).
 | ||||
| type CustomTypeValidator func(i interface{}, o interface{}) bool | ||||
| 
 | ||||
| // ParamValidator is a wrapper for validator functions that accepts additional parameters.
 | ||||
| type ParamValidator func(str string, params ...string) bool | ||||
| type tagOptionsMap map[string]string | ||||
| 
 | ||||
| // UnsupportedTypeError is a wrapper for reflect.Type
 | ||||
| type UnsupportedTypeError struct { | ||||
| 	Type reflect.Type | ||||
| } | ||||
| 
 | ||||
| // stringValues is a slice of reflect.Value holding *reflect.StringValue.
 | ||||
| // It implements the methods to sort by string.
 | ||||
| type stringValues []reflect.Value | ||||
| 
 | ||||
| // ParamTagMap is a map of functions accept variants parameters
 | ||||
| var ParamTagMap = map[string]ParamValidator{ | ||||
| 	"length":       ByteLength, | ||||
| 	"range":        Range, | ||||
| 	"runelength":   RuneLength, | ||||
| 	"stringlength": StringLength, | ||||
| 	"matches":      StringMatches, | ||||
| 	"in":           isInRaw, | ||||
| 	"rsapub":       IsRsaPub, | ||||
| } | ||||
| 
 | ||||
| // ParamTagRegexMap maps param tags to their respective regexes.
 | ||||
| var ParamTagRegexMap = map[string]*regexp.Regexp{ | ||||
| 	"range":        regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"), | ||||
| 	"length":       regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"), | ||||
| 	"runelength":   regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"), | ||||
| 	"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"), | ||||
| 	"in":           regexp.MustCompile(`^in\((.*)\)`), | ||||
| 	"matches":      regexp.MustCompile(`^matches\((.+)\)$`), | ||||
| 	"rsapub":       regexp.MustCompile("^rsapub\\((\\d+)\\)$"), | ||||
| } | ||||
| 
 | ||||
| type customTypeTagMap struct { | ||||
| 	validators map[string]CustomTypeValidator | ||||
| 
 | ||||
| 	sync.RWMutex | ||||
| } | ||||
| 
 | ||||
| func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) { | ||||
| 	tm.RLock() | ||||
| 	defer tm.RUnlock() | ||||
| 	v, ok := tm.validators[name] | ||||
| 	return v, ok | ||||
| } | ||||
| 
 | ||||
| func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) { | ||||
| 	tm.Lock() | ||||
| 	defer tm.Unlock() | ||||
| 	tm.validators[name] = ctv | ||||
| } | ||||
| 
 | ||||
| // CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function.
 | ||||
| // Use this to validate compound or custom types that need to be handled as a whole, e.g.
 | ||||
| // `type UUID [16]byte` (this would be handled as an array of bytes).
 | ||||
| var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)} | ||||
| 
 | ||||
| // TagMap is a map of functions, that can be used as tags for ValidateStruct function.
 | ||||
| var TagMap = map[string]Validator{ | ||||
| 	"email":              IsEmail, | ||||
| 	"url":                IsURL, | ||||
| 	"dialstring":         IsDialString, | ||||
| 	"requrl":             IsRequestURL, | ||||
| 	"requri":             IsRequestURI, | ||||
| 	"alpha":              IsAlpha, | ||||
| 	"utfletter":          IsUTFLetter, | ||||
| 	"alphanum":           IsAlphanumeric, | ||||
| 	"utfletternum":       IsUTFLetterNumeric, | ||||
| 	"numeric":            IsNumeric, | ||||
| 	"utfnumeric":         IsUTFNumeric, | ||||
| 	"utfdigit":           IsUTFDigit, | ||||
| 	"hexadecimal":        IsHexadecimal, | ||||
| 	"hexcolor":           IsHexcolor, | ||||
| 	"rgbcolor":           IsRGBcolor, | ||||
| 	"lowercase":          IsLowerCase, | ||||
| 	"uppercase":          IsUpperCase, | ||||
| 	"int":                IsInt, | ||||
| 	"float":              IsFloat, | ||||
| 	"null":               IsNull, | ||||
| 	"uuid":               IsUUID, | ||||
| 	"uuidv3":             IsUUIDv3, | ||||
| 	"uuidv4":             IsUUIDv4, | ||||
| 	"uuidv5":             IsUUIDv5, | ||||
| 	"creditcard":         IsCreditCard, | ||||
| 	"isbn10":             IsISBN10, | ||||
| 	"isbn13":             IsISBN13, | ||||
| 	"json":               IsJSON, | ||||
| 	"multibyte":          IsMultibyte, | ||||
| 	"ascii":              IsASCII, | ||||
| 	"printableascii":     IsPrintableASCII, | ||||
| 	"fullwidth":          IsFullWidth, | ||||
| 	"halfwidth":          IsHalfWidth, | ||||
| 	"variablewidth":      IsVariableWidth, | ||||
| 	"base64":             IsBase64, | ||||
| 	"datauri":            IsDataURI, | ||||
| 	"ip":                 IsIP, | ||||
| 	"port":               IsPort, | ||||
| 	"ipv4":               IsIPv4, | ||||
| 	"ipv6":               IsIPv6, | ||||
| 	"dns":                IsDNSName, | ||||
| 	"host":               IsHost, | ||||
| 	"mac":                IsMAC, | ||||
| 	"latitude":           IsLatitude, | ||||
| 	"longitude":          IsLongitude, | ||||
| 	"ssn":                IsSSN, | ||||
| 	"semver":             IsSemver, | ||||
| 	"rfc3339":            IsRFC3339, | ||||
| 	"rfc3339WithoutZone": IsRFC3339WithoutZone, | ||||
| 	"ISO3166Alpha2":      IsISO3166Alpha2, | ||||
| 	"ISO3166Alpha3":      IsISO3166Alpha3, | ||||
| 	"ISO4217":            IsISO4217, | ||||
| } | ||||
| 
 | ||||
| // 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"}, | ||||
| } | ||||
| 
 | ||||
| // ISO4217List is the list of ISO currency codes
 | ||||
| var ISO4217List = []string{ | ||||
| 	"AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", | ||||
| 	"BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", | ||||
| 	"CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK", | ||||
| 	"DJF", "DKK", "DOP", "DZD", | ||||
| 	"EGP", "ERN", "ETB", "EUR", | ||||
| 	"FJD", "FKP", | ||||
| 	"GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", | ||||
| 	"HKD", "HNL", "HRK", "HTG", "HUF", | ||||
| 	"IDR", "ILS", "INR", "IQD", "IRR", "ISK", | ||||
| 	"JMD", "JOD", "JPY", | ||||
| 	"KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", | ||||
| 	"LAK", "LBP", "LKR", "LRD", "LSL", "LYD", | ||||
| 	"MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", | ||||
| 	"NAD", "NGN", "NIO", "NOK", "NPR", "NZD", | ||||
| 	"OMR", | ||||
| 	"PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", | ||||
| 	"QAR", | ||||
| 	"RON", "RSD", "RUB", "RWF", | ||||
| 	"SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SVC", "SYP", "SZL", | ||||
| 	"THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", | ||||
| 	"UAH", "UGX", "USD", "USN", "UYI", "UYU", "UZS", | ||||
| 	"VEF", "VND", "VUV", | ||||
| 	"WST", | ||||
| 	"XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", | ||||
| 	"YER", | ||||
| 	"ZAR", "ZMW", "ZWL", | ||||
| } | ||||
| 
 | ||||
| // ISO693Entry stores ISO language codes
 | ||||
| type ISO693Entry struct { | ||||
| 	Alpha3bCode string | ||||
| 	Alpha2Code  string | ||||
| 	English     string | ||||
| } | ||||
| 
 | ||||
| //ISO693List based on http://data.okfn.org/data/core/language-codes/r/language-codes-3b2.json
 | ||||
| var ISO693List = []ISO693Entry{ | ||||
| 	{Alpha3bCode: "aar", Alpha2Code: "aa", English: "Afar"}, | ||||
| 	{Alpha3bCode: "abk", Alpha2Code: "ab", English: "Abkhazian"}, | ||||
| 	{Alpha3bCode: "afr", Alpha2Code: "af", English: "Afrikaans"}, | ||||
| 	{Alpha3bCode: "aka", Alpha2Code: "ak", English: "Akan"}, | ||||
| 	{Alpha3bCode: "alb", Alpha2Code: "sq", English: "Albanian"}, | ||||
| 	{Alpha3bCode: "amh", Alpha2Code: "am", English: "Amharic"}, | ||||
| 	{Alpha3bCode: "ara", Alpha2Code: "ar", English: "Arabic"}, | ||||
| 	{Alpha3bCode: "arg", Alpha2Code: "an", English: "Aragonese"}, | ||||
| 	{Alpha3bCode: "arm", Alpha2Code: "hy", English: "Armenian"}, | ||||
| 	{Alpha3bCode: "asm", Alpha2Code: "as", English: "Assamese"}, | ||||
| 	{Alpha3bCode: "ava", Alpha2Code: "av", English: "Avaric"}, | ||||
| 	{Alpha3bCode: "ave", Alpha2Code: "ae", English: "Avestan"}, | ||||
| 	{Alpha3bCode: "aym", Alpha2Code: "ay", English: "Aymara"}, | ||||
| 	{Alpha3bCode: "aze", Alpha2Code: "az", English: "Azerbaijani"}, | ||||
| 	{Alpha3bCode: "bak", Alpha2Code: "ba", English: "Bashkir"}, | ||||
| 	{Alpha3bCode: "bam", Alpha2Code: "bm", English: "Bambara"}, | ||||
| 	{Alpha3bCode: "baq", Alpha2Code: "eu", English: "Basque"}, | ||||
| 	{Alpha3bCode: "bel", Alpha2Code: "be", English: "Belarusian"}, | ||||
| 	{Alpha3bCode: "ben", Alpha2Code: "bn", English: "Bengali"}, | ||||
| 	{Alpha3bCode: "bih", Alpha2Code: "bh", English: "Bihari languages"}, | ||||
| 	{Alpha3bCode: "bis", Alpha2Code: "bi", English: "Bislama"}, | ||||
| 	{Alpha3bCode: "bos", Alpha2Code: "bs", English: "Bosnian"}, | ||||
| 	{Alpha3bCode: "bre", Alpha2Code: "br", English: "Breton"}, | ||||
| 	{Alpha3bCode: "bul", Alpha2Code: "bg", English: "Bulgarian"}, | ||||
| 	{Alpha3bCode: "bur", Alpha2Code: "my", English: "Burmese"}, | ||||
| 	{Alpha3bCode: "cat", Alpha2Code: "ca", English: "Catalan; Valencian"}, | ||||
| 	{Alpha3bCode: "cha", Alpha2Code: "ch", English: "Chamorro"}, | ||||
| 	{Alpha3bCode: "che", Alpha2Code: "ce", English: "Chechen"}, | ||||
| 	{Alpha3bCode: "chi", Alpha2Code: "zh", English: "Chinese"}, | ||||
| 	{Alpha3bCode: "chu", Alpha2Code: "cu", English: "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic"}, | ||||
| 	{Alpha3bCode: "chv", Alpha2Code: "cv", English: "Chuvash"}, | ||||
| 	{Alpha3bCode: "cor", Alpha2Code: "kw", English: "Cornish"}, | ||||
| 	{Alpha3bCode: "cos", Alpha2Code: "co", English: "Corsican"}, | ||||
| 	{Alpha3bCode: "cre", Alpha2Code: "cr", English: "Cree"}, | ||||
| 	{Alpha3bCode: "cze", Alpha2Code: "cs", English: "Czech"}, | ||||
| 	{Alpha3bCode: "dan", Alpha2Code: "da", English: "Danish"}, | ||||
| 	{Alpha3bCode: "div", Alpha2Code: "dv", English: "Divehi; Dhivehi; Maldivian"}, | ||||
| 	{Alpha3bCode: "dut", Alpha2Code: "nl", English: "Dutch; Flemish"}, | ||||
| 	{Alpha3bCode: "dzo", Alpha2Code: "dz", English: "Dzongkha"}, | ||||
| 	{Alpha3bCode: "eng", Alpha2Code: "en", English: "English"}, | ||||
| 	{Alpha3bCode: "epo", Alpha2Code: "eo", English: "Esperanto"}, | ||||
| 	{Alpha3bCode: "est", Alpha2Code: "et", English: "Estonian"}, | ||||
| 	{Alpha3bCode: "ewe", Alpha2Code: "ee", English: "Ewe"}, | ||||
| 	{Alpha3bCode: "fao", Alpha2Code: "fo", English: "Faroese"}, | ||||
| 	{Alpha3bCode: "fij", Alpha2Code: "fj", English: "Fijian"}, | ||||
| 	{Alpha3bCode: "fin", Alpha2Code: "fi", English: "Finnish"}, | ||||
| 	{Alpha3bCode: "fre", Alpha2Code: "fr", English: "French"}, | ||||
| 	{Alpha3bCode: "fry", Alpha2Code: "fy", English: "Western Frisian"}, | ||||
| 	{Alpha3bCode: "ful", Alpha2Code: "ff", English: "Fulah"}, | ||||
| 	{Alpha3bCode: "geo", Alpha2Code: "ka", English: "Georgian"}, | ||||
| 	{Alpha3bCode: "ger", Alpha2Code: "de", English: "German"}, | ||||
| 	{Alpha3bCode: "gla", Alpha2Code: "gd", English: "Gaelic; Scottish Gaelic"}, | ||||
| 	{Alpha3bCode: "gle", Alpha2Code: "ga", English: "Irish"}, | ||||
| 	{Alpha3bCode: "glg", Alpha2Code: "gl", English: "Galician"}, | ||||
| 	{Alpha3bCode: "glv", Alpha2Code: "gv", English: "Manx"}, | ||||
| 	{Alpha3bCode: "gre", Alpha2Code: "el", English: "Greek, Modern (1453-)"}, | ||||
| 	{Alpha3bCode: "grn", Alpha2Code: "gn", English: "Guarani"}, | ||||
| 	{Alpha3bCode: "guj", Alpha2Code: "gu", English: "Gujarati"}, | ||||
| 	{Alpha3bCode: "hat", Alpha2Code: "ht", English: "Haitian; Haitian Creole"}, | ||||
| 	{Alpha3bCode: "hau", Alpha2Code: "ha", English: "Hausa"}, | ||||
| 	{Alpha3bCode: "heb", Alpha2Code: "he", English: "Hebrew"}, | ||||
| 	{Alpha3bCode: "her", Alpha2Code: "hz", English: "Herero"}, | ||||
| 	{Alpha3bCode: "hin", Alpha2Code: "hi", English: "Hindi"}, | ||||
| 	{Alpha3bCode: "hmo", Alpha2Code: "ho", English: "Hiri Motu"}, | ||||
| 	{Alpha3bCode: "hrv", Alpha2Code: "hr", English: "Croatian"}, | ||||
| 	{Alpha3bCode: "hun", Alpha2Code: "hu", English: "Hungarian"}, | ||||
| 	{Alpha3bCode: "ibo", Alpha2Code: "ig", English: "Igbo"}, | ||||
| 	{Alpha3bCode: "ice", Alpha2Code: "is", English: "Icelandic"}, | ||||
| 	{Alpha3bCode: "ido", Alpha2Code: "io", English: "Ido"}, | ||||
| 	{Alpha3bCode: "iii", Alpha2Code: "ii", English: "Sichuan Yi; Nuosu"}, | ||||
| 	{Alpha3bCode: "iku", Alpha2Code: "iu", English: "Inuktitut"}, | ||||
| 	{Alpha3bCode: "ile", Alpha2Code: "ie", English: "Interlingue; Occidental"}, | ||||
| 	{Alpha3bCode: "ina", Alpha2Code: "ia", English: "Interlingua (International Auxiliary Language Association)"}, | ||||
| 	{Alpha3bCode: "ind", Alpha2Code: "id", English: "Indonesian"}, | ||||
| 	{Alpha3bCode: "ipk", Alpha2Code: "ik", English: "Inupiaq"}, | ||||
| 	{Alpha3bCode: "ita", Alpha2Code: "it", English: "Italian"}, | ||||
| 	{Alpha3bCode: "jav", Alpha2Code: "jv", English: "Javanese"}, | ||||
| 	{Alpha3bCode: "jpn", Alpha2Code: "ja", English: "Japanese"}, | ||||
| 	{Alpha3bCode: "kal", Alpha2Code: "kl", English: "Kalaallisut; Greenlandic"}, | ||||
| 	{Alpha3bCode: "kan", Alpha2Code: "kn", English: "Kannada"}, | ||||
| 	{Alpha3bCode: "kas", Alpha2Code: "ks", English: "Kashmiri"}, | ||||
| 	{Alpha3bCode: "kau", Alpha2Code: "kr", English: "Kanuri"}, | ||||
| 	{Alpha3bCode: "kaz", Alpha2Code: "kk", English: "Kazakh"}, | ||||
| 	{Alpha3bCode: "khm", Alpha2Code: "km", English: "Central Khmer"}, | ||||
| 	{Alpha3bCode: "kik", Alpha2Code: "ki", English: "Kikuyu; Gikuyu"}, | ||||
| 	{Alpha3bCode: "kin", Alpha2Code: "rw", English: "Kinyarwanda"}, | ||||
| 	{Alpha3bCode: "kir", Alpha2Code: "ky", English: "Kirghiz; Kyrgyz"}, | ||||
| 	{Alpha3bCode: "kom", Alpha2Code: "kv", English: "Komi"}, | ||||
| 	{Alpha3bCode: "kon", Alpha2Code: "kg", English: "Kongo"}, | ||||
| 	{Alpha3bCode: "kor", Alpha2Code: "ko", English: "Korean"}, | ||||
| 	{Alpha3bCode: "kua", Alpha2Code: "kj", English: "Kuanyama; Kwanyama"}, | ||||
| 	{Alpha3bCode: "kur", Alpha2Code: "ku", English: "Kurdish"}, | ||||
| 	{Alpha3bCode: "lao", Alpha2Code: "lo", English: "Lao"}, | ||||
| 	{Alpha3bCode: "lat", Alpha2Code: "la", English: "Latin"}, | ||||
| 	{Alpha3bCode: "lav", Alpha2Code: "lv", English: "Latvian"}, | ||||
| 	{Alpha3bCode: "lim", Alpha2Code: "li", English: "Limburgan; Limburger; Limburgish"}, | ||||
| 	{Alpha3bCode: "lin", Alpha2Code: "ln", English: "Lingala"}, | ||||
| 	{Alpha3bCode: "lit", Alpha2Code: "lt", English: "Lithuanian"}, | ||||
| 	{Alpha3bCode: "ltz", Alpha2Code: "lb", English: "Luxembourgish; Letzeburgesch"}, | ||||
| 	{Alpha3bCode: "lub", Alpha2Code: "lu", English: "Luba-Katanga"}, | ||||
| 	{Alpha3bCode: "lug", Alpha2Code: "lg", English: "Ganda"}, | ||||
| 	{Alpha3bCode: "mac", Alpha2Code: "mk", English: "Macedonian"}, | ||||
| 	{Alpha3bCode: "mah", Alpha2Code: "mh", English: "Marshallese"}, | ||||
| 	{Alpha3bCode: "mal", Alpha2Code: "ml", English: "Malayalam"}, | ||||
| 	{Alpha3bCode: "mao", Alpha2Code: "mi", English: "Maori"}, | ||||
| 	{Alpha3bCode: "mar", Alpha2Code: "mr", English: "Marathi"}, | ||||
| 	{Alpha3bCode: "may", Alpha2Code: "ms", English: "Malay"}, | ||||
| 	{Alpha3bCode: "mlg", Alpha2Code: "mg", English: "Malagasy"}, | ||||
| 	{Alpha3bCode: "mlt", Alpha2Code: "mt", English: "Maltese"}, | ||||
| 	{Alpha3bCode: "mon", Alpha2Code: "mn", English: "Mongolian"}, | ||||
| 	{Alpha3bCode: "nau", Alpha2Code: "na", English: "Nauru"}, | ||||
| 	{Alpha3bCode: "nav", Alpha2Code: "nv", English: "Navajo; Navaho"}, | ||||
| 	{Alpha3bCode: "nbl", Alpha2Code: "nr", English: "Ndebele, South; South Ndebele"}, | ||||
| 	{Alpha3bCode: "nde", Alpha2Code: "nd", English: "Ndebele, North; North Ndebele"}, | ||||
| 	{Alpha3bCode: "ndo", Alpha2Code: "ng", English: "Ndonga"}, | ||||
| 	{Alpha3bCode: "nep", Alpha2Code: "ne", English: "Nepali"}, | ||||
| 	{Alpha3bCode: "nno", Alpha2Code: "nn", English: "Norwegian Nynorsk; Nynorsk, Norwegian"}, | ||||
| 	{Alpha3bCode: "nob", Alpha2Code: "nb", English: "Bokmål, Norwegian; Norwegian Bokmål"}, | ||||
| 	{Alpha3bCode: "nor", Alpha2Code: "no", English: "Norwegian"}, | ||||
| 	{Alpha3bCode: "nya", Alpha2Code: "ny", English: "Chichewa; Chewa; Nyanja"}, | ||||
| 	{Alpha3bCode: "oci", Alpha2Code: "oc", English: "Occitan (post 1500); Provençal"}, | ||||
| 	{Alpha3bCode: "oji", Alpha2Code: "oj", English: "Ojibwa"}, | ||||
| 	{Alpha3bCode: "ori", Alpha2Code: "or", English: "Oriya"}, | ||||
| 	{Alpha3bCode: "orm", Alpha2Code: "om", English: "Oromo"}, | ||||
| 	{Alpha3bCode: "oss", Alpha2Code: "os", English: "Ossetian; Ossetic"}, | ||||
| 	{Alpha3bCode: "pan", Alpha2Code: "pa", English: "Panjabi; Punjabi"}, | ||||
| 	{Alpha3bCode: "per", Alpha2Code: "fa", English: "Persian"}, | ||||
| 	{Alpha3bCode: "pli", Alpha2Code: "pi", English: "Pali"}, | ||||
| 	{Alpha3bCode: "pol", Alpha2Code: "pl", English: "Polish"}, | ||||
| 	{Alpha3bCode: "por", Alpha2Code: "pt", English: "Portuguese"}, | ||||
| 	{Alpha3bCode: "pus", Alpha2Code: "ps", English: "Pushto; Pashto"}, | ||||
| 	{Alpha3bCode: "que", Alpha2Code: "qu", English: "Quechua"}, | ||||
| 	{Alpha3bCode: "roh", Alpha2Code: "rm", English: "Romansh"}, | ||||
| 	{Alpha3bCode: "rum", Alpha2Code: "ro", English: "Romanian; Moldavian; Moldovan"}, | ||||
| 	{Alpha3bCode: "run", Alpha2Code: "rn", English: "Rundi"}, | ||||
| 	{Alpha3bCode: "rus", Alpha2Code: "ru", English: "Russian"}, | ||||
| 	{Alpha3bCode: "sag", Alpha2Code: "sg", English: "Sango"}, | ||||
| 	{Alpha3bCode: "san", Alpha2Code: "sa", English: "Sanskrit"}, | ||||
| 	{Alpha3bCode: "sin", Alpha2Code: "si", English: "Sinhala; Sinhalese"}, | ||||
| 	{Alpha3bCode: "slo", Alpha2Code: "sk", English: "Slovak"}, | ||||
| 	{Alpha3bCode: "slv", Alpha2Code: "sl", English: "Slovenian"}, | ||||
| 	{Alpha3bCode: "sme", Alpha2Code: "se", English: "Northern Sami"}, | ||||
| 	{Alpha3bCode: "smo", Alpha2Code: "sm", English: "Samoan"}, | ||||
| 	{Alpha3bCode: "sna", Alpha2Code: "sn", English: "Shona"}, | ||||
| 	{Alpha3bCode: "snd", Alpha2Code: "sd", English: "Sindhi"}, | ||||
| 	{Alpha3bCode: "som", Alpha2Code: "so", English: "Somali"}, | ||||
| 	{Alpha3bCode: "sot", Alpha2Code: "st", English: "Sotho, Southern"}, | ||||
| 	{Alpha3bCode: "spa", Alpha2Code: "es", English: "Spanish; Castilian"}, | ||||
| 	{Alpha3bCode: "srd", Alpha2Code: "sc", English: "Sardinian"}, | ||||
| 	{Alpha3bCode: "srp", Alpha2Code: "sr", English: "Serbian"}, | ||||
| 	{Alpha3bCode: "ssw", Alpha2Code: "ss", English: "Swati"}, | ||||
| 	{Alpha3bCode: "sun", Alpha2Code: "su", English: "Sundanese"}, | ||||
| 	{Alpha3bCode: "swa", Alpha2Code: "sw", English: "Swahili"}, | ||||
| 	{Alpha3bCode: "swe", Alpha2Code: "sv", English: "Swedish"}, | ||||
| 	{Alpha3bCode: "tah", Alpha2Code: "ty", English: "Tahitian"}, | ||||
| 	{Alpha3bCode: "tam", Alpha2Code: "ta", English: "Tamil"}, | ||||
| 	{Alpha3bCode: "tat", Alpha2Code: "tt", English: "Tatar"}, | ||||
| 	{Alpha3bCode: "tel", Alpha2Code: "te", English: "Telugu"}, | ||||
| 	{Alpha3bCode: "tgk", Alpha2Code: "tg", English: "Tajik"}, | ||||
| 	{Alpha3bCode: "tgl", Alpha2Code: "tl", English: "Tagalog"}, | ||||
| 	{Alpha3bCode: "tha", Alpha2Code: "th", English: "Thai"}, | ||||
| 	{Alpha3bCode: "tib", Alpha2Code: "bo", English: "Tibetan"}, | ||||
| 	{Alpha3bCode: "tir", Alpha2Code: "ti", English: "Tigrinya"}, | ||||
| 	{Alpha3bCode: "ton", Alpha2Code: "to", English: "Tonga (Tonga Islands)"}, | ||||
| 	{Alpha3bCode: "tsn", Alpha2Code: "tn", English: "Tswana"}, | ||||
| 	{Alpha3bCode: "tso", Alpha2Code: "ts", English: "Tsonga"}, | ||||
| 	{Alpha3bCode: "tuk", Alpha2Code: "tk", English: "Turkmen"}, | ||||
| 	{Alpha3bCode: "tur", Alpha2Code: "tr", English: "Turkish"}, | ||||
| 	{Alpha3bCode: "twi", Alpha2Code: "tw", English: "Twi"}, | ||||
| 	{Alpha3bCode: "uig", Alpha2Code: "ug", English: "Uighur; Uyghur"}, | ||||
| 	{Alpha3bCode: "ukr", Alpha2Code: "uk", English: "Ukrainian"}, | ||||
| 	{Alpha3bCode: "urd", Alpha2Code: "ur", English: "Urdu"}, | ||||
| 	{Alpha3bCode: "uzb", Alpha2Code: "uz", English: "Uzbek"}, | ||||
| 	{Alpha3bCode: "ven", Alpha2Code: "ve", English: "Venda"}, | ||||
| 	{Alpha3bCode: "vie", Alpha2Code: "vi", English: "Vietnamese"}, | ||||
| 	{Alpha3bCode: "vol", Alpha2Code: "vo", English: "Volapük"}, | ||||
| 	{Alpha3bCode: "wel", Alpha2Code: "cy", English: "Welsh"}, | ||||
| 	{Alpha3bCode: "wln", Alpha2Code: "wa", English: "Walloon"}, | ||||
| 	{Alpha3bCode: "wol", Alpha2Code: "wo", English: "Wolof"}, | ||||
| 	{Alpha3bCode: "xho", Alpha2Code: "xh", English: "Xhosa"}, | ||||
| 	{Alpha3bCode: "yid", Alpha2Code: "yi", English: "Yiddish"}, | ||||
| 	{Alpha3bCode: "yor", Alpha2Code: "yo", English: "Yoruba"}, | ||||
| 	{Alpha3bCode: "zha", Alpha2Code: "za", English: "Zhuang; Chuang"}, | ||||
| 	{Alpha3bCode: "zul", Alpha2Code: "zu", English: "Zulu"}, | ||||
| } | ||||
|  | @ -1,262 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"html" | ||||
| 	"math" | ||||
| 	"path" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
| 
 | ||||
| // Contains check if the string contains the substring.
 | ||||
| func Contains(str, substring string) bool { | ||||
| 	return strings.Contains(str, substring) | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
| 
 | ||||
| // LeftTrim trim characters from the left-side of the input.
 | ||||
| // If second argument is empty, it's will be remove leading spaces.
 | ||||
| func LeftTrim(str, chars string) string { | ||||
| 	if chars == "" { | ||||
| 		return strings.TrimLeftFunc(str, unicode.IsSpace) | ||||
| 	} | ||||
| 	r, _ := regexp.Compile("^[" + chars + "]+") | ||||
| 	return r.ReplaceAllString(str, "") | ||||
| } | ||||
| 
 | ||||
| // RightTrim trim characters from the right-side of the input.
 | ||||
| // If second argument is empty, it's will be remove spaces.
 | ||||
| func RightTrim(str, chars string) string { | ||||
| 	if chars == "" { | ||||
| 		return strings.TrimRightFunc(str, unicode.IsSpace) | ||||
| 	} | ||||
| 	r, _ := regexp.Compile("[" + chars + "]+$") | ||||
| 	return r.ReplaceAllString(str, "") | ||||
| } | ||||
| 
 | ||||
| // Trim trim characters from both sides of the input.
 | ||||
| // If second argument is empty, it's will be remove spaces.
 | ||||
| func Trim(str, chars string) string { | ||||
| 	return LeftTrim(RightTrim(str, chars), chars) | ||||
| } | ||||
| 
 | ||||
| // WhiteList remove characters that do not appear in the whitelist.
 | ||||
| func WhiteList(str, chars string) string { | ||||
| 	pattern := "[^" + chars + "]+" | ||||
| 	r, _ := regexp.Compile(pattern) | ||||
| 	return r.ReplaceAllString(str, "") | ||||
| } | ||||
| 
 | ||||
| // BlackList remove characters that appear in the blacklist.
 | ||||
| func BlackList(str, chars string) string { | ||||
| 	pattern := "[" + chars + "]+" | ||||
| 	r, _ := regexp.Compile(pattern) | ||||
| 	return r.ReplaceAllString(str, "") | ||||
| } | ||||
| 
 | ||||
| // StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
 | ||||
| // If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
 | ||||
| func StripLow(str string, keepNewLines bool) string { | ||||
| 	chars := "" | ||||
| 	if keepNewLines { | ||||
| 		chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F" | ||||
| 	} else { | ||||
| 		chars = "\x00-\x1F\x7F" | ||||
| 	} | ||||
| 	return BlackList(str, chars) | ||||
| } | ||||
| 
 | ||||
| // ReplacePattern replace regular expression pattern in string
 | ||||
| func ReplacePattern(str, pattern, replace string) string { | ||||
| 	r, _ := regexp.Compile(pattern) | ||||
| 	return r.ReplaceAllString(str, replace) | ||||
| } | ||||
| 
 | ||||
| // Escape replace <, >, & and " with HTML entities.
 | ||||
| var Escape = html.EscapeString | ||||
| 
 | ||||
| func addSegment(inrune, segment []rune) []rune { | ||||
| 	if len(segment) == 0 { | ||||
| 		return inrune | ||||
| 	} | ||||
| 	if len(inrune) != 0 { | ||||
| 		inrune = append(inrune, '_') | ||||
| 	} | ||||
| 	inrune = append(inrune, segment...) | ||||
| 	return inrune | ||||
| } | ||||
| 
 | ||||
| // UnderscoreToCamelCase converts from underscore separated form to camel case form.
 | ||||
| // Ex.: my_func => MyFunc
 | ||||
| func UnderscoreToCamelCase(s string) string { | ||||
| 	return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1) | ||||
| } | ||||
| 
 | ||||
| // CamelCaseToUnderscore converts from camel case form to underscore separated form.
 | ||||
| // Ex.: MyFunc => my_func
 | ||||
| func CamelCaseToUnderscore(str string) string { | ||||
| 	var output []rune | ||||
| 	var segment []rune | ||||
| 	for _, r := range str { | ||||
| 		if !unicode.IsLower(r) && string(r) != "_" { | ||||
| 			output = addSegment(output, segment) | ||||
| 			segment = nil | ||||
| 		} | ||||
| 		segment = append(segment, unicode.ToLower(r)) | ||||
| 	} | ||||
| 	output = addSegment(output, segment) | ||||
| 	return string(output) | ||||
| } | ||||
| 
 | ||||
| // Reverse return reversed string
 | ||||
| func Reverse(s string) string { | ||||
| 	r := []rune(s) | ||||
| 	for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { | ||||
| 		r[i], r[j] = r[j], r[i] | ||||
| 	} | ||||
| 	return string(r) | ||||
| } | ||||
| 
 | ||||
| // GetLines split string by "\n" and return array of lines
 | ||||
| func GetLines(s string) []string { | ||||
| 	return strings.Split(s, "\n") | ||||
| } | ||||
| 
 | ||||
| // GetLine return specified line of multiline string
 | ||||
| func GetLine(s string, index int) (string, error) { | ||||
| 	lines := GetLines(s) | ||||
| 	if index < 0 || index >= len(lines) { | ||||
| 		return "", errors.New("line index out of bounds") | ||||
| 	} | ||||
| 	return lines[index], nil | ||||
| } | ||||
| 
 | ||||
| // RemoveTags remove all tags from HTML string
 | ||||
| func RemoveTags(s string) string { | ||||
| 	return ReplacePattern(s, "<[^>]*>", "") | ||||
| } | ||||
| 
 | ||||
| // SafeFileName return safe string that can be used in file names
 | ||||
| func SafeFileName(str string) string { | ||||
| 	name := strings.ToLower(str) | ||||
| 	name = path.Clean(path.Base(name)) | ||||
| 	name = strings.Trim(name, " ") | ||||
| 	separators, err := regexp.Compile(`[ &_=+:]`) | ||||
| 	if err == nil { | ||||
| 		name = separators.ReplaceAllString(name, "-") | ||||
| 	} | ||||
| 	legal, err := regexp.Compile(`[^[:alnum:]-.]`) | ||||
| 	if err == nil { | ||||
| 		name = legal.ReplaceAllString(name, "") | ||||
| 	} | ||||
| 	for strings.Contains(name, "--") { | ||||
| 		name = strings.Replace(name, "--", "-", -1) | ||||
| 	} | ||||
| 	return name | ||||
| } | ||||
| 
 | ||||
| // NormalizeEmail canonicalize an email address.
 | ||||
| // The local part of the email address is lowercased for all domains; the hostname is always lowercased and
 | ||||
| // the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
 | ||||
| // Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
 | ||||
| // are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
 | ||||
| // normalized to @gmail.com.
 | ||||
| func NormalizeEmail(str string) (string, error) { | ||||
| 	if !IsEmail(str) { | ||||
| 		return "", fmt.Errorf("%s is not an email", str) | ||||
| 	} | ||||
| 	parts := strings.Split(str, "@") | ||||
| 	parts[0] = strings.ToLower(parts[0]) | ||||
| 	parts[1] = strings.ToLower(parts[1]) | ||||
| 	if parts[1] == "gmail.com" || parts[1] == "googlemail.com" { | ||||
| 		parts[1] = "gmail.com" | ||||
| 		parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0] | ||||
| 	} | ||||
| 	return strings.Join(parts, "@"), nil | ||||
| } | ||||
| 
 | ||||
| // Truncate a string to the closest length without breaking words.
 | ||||
| func Truncate(str string, length int, ending string) string { | ||||
| 	var aftstr, befstr string | ||||
| 	if len(str) > length { | ||||
| 		words := strings.Fields(str) | ||||
| 		before, present := 0, 0 | ||||
| 		for i := range words { | ||||
| 			befstr = aftstr | ||||
| 			before = present | ||||
| 			aftstr = aftstr + words[i] + " " | ||||
| 			present = len(aftstr) | ||||
| 			if present > length && i != 0 { | ||||
| 				if (length - before) < (present - length) { | ||||
| 					return Trim(befstr, " /\\.,\"'#!?&@+-") + ending | ||||
| 				} | ||||
| 				return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return str | ||||
| } | ||||
| 
 | ||||
| // PadLeft pad left side of string if size of string is less then indicated pad length
 | ||||
| func PadLeft(str string, padStr string, padLen int) string { | ||||
| 	return buildPadStr(str, padStr, padLen, true, false) | ||||
| } | ||||
| 
 | ||||
| // PadRight pad right side of string if size of string is less then indicated pad length
 | ||||
| func PadRight(str string, padStr string, padLen int) string { | ||||
| 	return buildPadStr(str, padStr, padLen, false, true) | ||||
| } | ||||
| 
 | ||||
| // PadBoth pad sides of string if size of string is less then indicated pad length
 | ||||
| func PadBoth(str string, padStr string, padLen int) string { | ||||
| 	return buildPadStr(str, padStr, padLen, true, true) | ||||
| } | ||||
| 
 | ||||
| // PadString either left, right or both sides, not the padding string can be unicode and more then one
 | ||||
| // character
 | ||||
| func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string { | ||||
| 
 | ||||
| 	// When padded length is less then the current string size
 | ||||
| 	if padLen < utf8.RuneCountInString(str) { | ||||
| 		return str | ||||
| 	} | ||||
| 
 | ||||
| 	padLen -= utf8.RuneCountInString(str) | ||||
| 
 | ||||
| 	targetLen := padLen | ||||
| 
 | ||||
| 	targetLenLeft := targetLen | ||||
| 	targetLenRight := targetLen | ||||
| 	if padLeft && padRight { | ||||
| 		targetLenLeft = padLen / 2 | ||||
| 		targetLenRight = padLen - targetLenLeft | ||||
| 	} | ||||
| 
 | ||||
| 	strToRepeatLen := utf8.RuneCountInString(padStr) | ||||
| 
 | ||||
| 	repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen))) | ||||
| 	repeatedString := strings.Repeat(padStr, repeatTimes) | ||||
| 
 | ||||
| 	leftSide := "" | ||||
| 	if padLeft { | ||||
| 		leftSide = repeatedString[0:targetLenLeft] | ||||
| 	} | ||||
| 
 | ||||
| 	rightSide := "" | ||||
| 	if padRight { | ||||
| 		rightSide = repeatedString[0:targetLenRight] | ||||
| 	} | ||||
| 
 | ||||
| 	return leftSide + str + rightSide | ||||
| } | ||||
|  | @ -1,501 +0,0 @@ | |||
| package govalidator | ||||
| 
 | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| func TestContains(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected bool | ||||
| 	}{ | ||||
| 		{"abacada", "", true}, | ||||
| 		{"abacada", "ritir", false}, | ||||
| 		{"abacada", "a", true}, | ||||
| 		{"abacada", "aca", true}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Contains(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Contains(%q,%q) to be %v, got %v", test.param1, test.param2, 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 TestLeftTrim(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"  \r\n\tfoo  \r\n\t   ", "", "foo  \r\n\t   "}, | ||||
| 		{"010100201000", "01", "201000"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := LeftTrim(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected LeftTrim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestRightTrim(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"  \r\n\tfoo  \r\n\t   ", "", "  \r\n\tfoo"}, | ||||
| 		{"010100201000", "01", "0101002"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := RightTrim(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected RightTrim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTrim(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"  \r\n\tfoo  \r\n\t   ", "", "foo"}, | ||||
| 		{"010100201000", "01", "2"}, | ||||
| 		{"1234567890987654321", "1-8", "909"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Trim(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Trim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // This small example illustrate how to work with Trim function.
 | ||||
| func ExampleTrim() { | ||||
| 	// Remove from left and right spaces and "\r", "\n", "\t" characters
 | ||||
| 	println(Trim("   \r\r\ntext\r   \t\n", "") == "text") | ||||
| 	// Remove from left and right characters that are between "1" and "8".
 | ||||
| 	// "1-8" is like full list "12345678".
 | ||||
| 	println(Trim("1234567890987654321", "1-8") == "909") | ||||
| } | ||||
| 
 | ||||
| func TestWhiteList(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abcdef", "abc", "abc"}, | ||||
| 		{"aaaaaaaaaabbbbbbbbbb", "abc", "aaaaaaaaaabbbbbbbbbb"}, | ||||
| 		{"a1b2c3", "abc", "abc"}, | ||||
| 		{"   ", "abc", ""}, | ||||
| 		{"a3a43a5a4a3a2a23a4a5a4a3a4", "a-z", "aaaaaaaaaaaa"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := WhiteList(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected WhiteList(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // This small example illustrate how to work with WhiteList function.
 | ||||
| func ExampleWhiteList() { | ||||
| 	// Remove all characters from string ignoring characters between "a" and "z"
 | ||||
| 	println(WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa") | ||||
| } | ||||
| 
 | ||||
| func TestBlackList(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abcdef", "abc", "def"}, | ||||
| 		{"aaaaaaaaaabbbbbbbbbb", "abc", ""}, | ||||
| 		{"a1b2c3", "abc", "123"}, | ||||
| 		{"   ", "abc", "   "}, | ||||
| 		{"a3a43a5a4a3a2a23a4a5a4a3a4", "a-z", "34354322345434"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := BlackList(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected BlackList(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestStripLow(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   bool | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"foo\x00", false, "foo"}, | ||||
| 		{"\x7Ffoo\x02", false, "foo"}, | ||||
| 		{"\x01\x09", false, ""}, | ||||
| 		{"foo\x0A\x0D", false, "foo"}, | ||||
| 		{"perch\u00e9", false, "perch\u00e9"}, | ||||
| 		{"\u20ac", false, "\u20ac"}, | ||||
| 		{"\u2206\x0A", false, "\u2206"}, | ||||
| 		{"foo\x0A\x0D", true, "foo\x0A\x0D"}, | ||||
| 		{"\x03foo\x0A\x0D", true, "foo\x0A\x0D"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := StripLow(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected StripLow(%q,%t) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestReplacePattern(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		param3   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"ab123ba", "[0-9]+", "aca", "abacaba"}, | ||||
| 		{"abacaba", "[0-9]+", "aca", "abacaba"}, | ||||
| 		{"httpftp://github.comio", "(ftp|io)", "", "http://github.com"}, | ||||
| 		{"aaaaaaaaaa", "a", "", ""}, | ||||
| 		{"http123123ftp://git534543hub.comio", "(ftp|io|[0-9]+)", "", "http://github.com"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := ReplacePattern(test.param1, test.param2, test.param3) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected ReplacePattern(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // This small example illustrate how to work with ReplacePattern function.
 | ||||
| func ExampleReplacePattern() { | ||||
| 	// Replace in "http123123ftp://git534543hub.comio" following (pattern "(ftp|io|[0-9]+)"):
 | ||||
| 	// - Sequence "ftp".
 | ||||
| 	// - Sequence "io".
 | ||||
| 	// - Sequence of digits.
 | ||||
| 	// with empty string.
 | ||||
| 	println(ReplacePattern("http123123ftp://git534543hub.comio", "(ftp|io|[0-9]+)", "") == "http://github.com") | ||||
| } | ||||
| 
 | ||||
| func TestEscape(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{`<img alt="foo&bar">`, "<img alt="foo&bar">"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Escape(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Escape(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestUnderscoreToCamelCase(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"a_b_c", "ABC"}, | ||||
| 		{"my_func", "MyFunc"}, | ||||
| 		{"1ab_cd", "1abCd"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := UnderscoreToCamelCase(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected UnderscoreToCamelCase(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestCamelCaseToUnderscore(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"MyFunc", "my_func"}, | ||||
| 		{"ABC", "a_b_c"}, | ||||
| 		{"1B", "1_b"}, | ||||
| 		{"foo_bar", "foo_bar"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := CamelCaseToUnderscore(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected CamelCaseToUnderscore(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestReverse(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abc", "cba"}, | ||||
| 		{"カタカナ", "ナカタカ"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Reverse(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Reverse(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestGetLines(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected []string | ||||
| 	}{ | ||||
| 		{"abc", []string{"abc"}}, | ||||
| 		{"a\nb\nc", []string{"a", "b", "c"}}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := GetLines(test.param) | ||||
| 		if !reflect.DeepEqual(actual, test.expected) { | ||||
| 			t.Errorf("Expected GetLines(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestGetLine(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   int | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abc", 0, "abc"}, | ||||
| 		{"a\nb\nc", 0, "a"}, | ||||
| 		{"abc", -1, ""}, | ||||
| 		{"abacaba\n", 1, ""}, | ||||
| 		{"abc", 3, ""}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual, _ := GetLine(test.param1, test.param2) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected GetLine(%q, %d) to be %v, got %v", test.param1, test.param2, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestRemoveTags(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abc", "abc"}, | ||||
| 		{"<!-- Test -->", ""}, | ||||
| 		{"<div><div><p><a>Text</a></p></div></div>", "Text"}, | ||||
| 		{`<a href="#">Link</a>`, "Link"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := RemoveTags(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected RemoveTags(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestSafeFileName(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"abc", "abc"}, | ||||
| 		{"123456789     '_-?ASDF@£$%£%^é.html", "123456789-asdf.html"}, | ||||
| 		{"ReadMe.md", "readme.md"}, | ||||
| 		{"file:///c:/test.go", "test.go"}, | ||||
| 		{"../../../Hello World!.txt", "hello-world.txt"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := SafeFileName(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected SafeFileName(%q) to be %v, got %v", test.param, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestNormalizeEmail(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param    string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{`test@me.com`, `test@me.com`}, | ||||
| 		{`some.name@gmail.com`, `somename@gmail.com`}, | ||||
| 		{`some.name@googlemail.com`, `somename@gmail.com`}, | ||||
| 		{`some.name+extension@gmail.com`, `somename@gmail.com`}, | ||||
| 		{`some.name+extension@googlemail.com`, `somename@gmail.com`}, | ||||
| 		{`some.name.middlename+extension@gmail.com`, `somenamemiddlename@gmail.com`}, | ||||
| 		{`some.name.middlename+extension@googlemail.com`, `somenamemiddlename@gmail.com`}, | ||||
| 		{`some.name.midd.lena.me.+extension@gmail.com`, `somenamemiddlename@gmail.com`}, | ||||
| 		{`some.name.midd.lena.me.+extension@googlemail.com`, `somenamemiddlename@gmail.com`}, | ||||
| 		{`some.name+extension@unknown.com`, `some.name+extension@unknown.com`}, | ||||
| 		{`hans@m端ller.com`, `hans@m端ller.com`}, | ||||
| 		{`hans`, ``}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual, err := NormalizeEmail(test.param) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected NormalizeEmail(%q) to be %v, got %v, err %v", test.param, test.expected, actual, err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestTruncate(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   int | ||||
| 		param3   string | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{`Lorem ipsum dolor sit amet, consectetur adipiscing elit.`, 25, `...`, `Lorem ipsum dolor sit amet...`}, | ||||
| 		{`Measuring programming progress by lines of code is like measuring aircraft building progress by weight.`, 35, ` new born babies!`, `Measuring programming progress by new born babies!`}, | ||||
| 		{`Testestestestestestestestestest testestestestestestestestest`, 7, `...`, `Testestestestestestestestestest...`}, | ||||
| 		{`Testing`, 7, `...`, `Testing`}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := Truncate(test.param1, test.param2, test.param3) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected Truncate(%q, %d, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPadLeft(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		param3   int | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"こんにちは", "xyz", 12, "xyzxyzxこんにちは"}, | ||||
| 		{"こんにちは", "xyz", 11, "xyzxyzこんにちは"}, | ||||
| 		{"abc", "x", 5, "xxabc"}, | ||||
| 		{"abc", "xyz", 5, "xyabc"}, | ||||
| 		{"abcde", "xyz", 5, "abcde"}, | ||||
| 		{"abcde", "xyz", 4, "abcde"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := PadLeft(test.param1, test.param2, test.param3) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected PadLeft(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPadRight(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		param3   int | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"こんにちは", "xyz", 12, "こんにちはxyzxyzx"}, | ||||
| 		{"こんにちは", "xyz", 11, "こんにちはxyzxyz"}, | ||||
| 		{"abc", "x", 5, "abcxx"}, | ||||
| 		{"abc", "xyz", 5, "abcxy"}, | ||||
| 		{"abcde", "xyz", 5, "abcde"}, | ||||
| 		{"abcde", "xyz", 4, "abcde"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := PadRight(test.param1, test.param2, test.param3) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected PadRight(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPadBoth(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var tests = []struct { | ||||
| 		param1   string | ||||
| 		param2   string | ||||
| 		param3   int | ||||
| 		expected string | ||||
| 	}{ | ||||
| 		{"こんにちは", "xyz", 12, "xyzこんにちはxyzx"}, | ||||
| 		{"こんにちは", "xyz", 11, "xyzこんにちはxyz"}, | ||||
| 		{"abc", "x", 5, "xabcx"}, | ||||
| 		{"abc", "xyz", 5, "xabcx"}, | ||||
| 		{"abcde", "xyz", 5, "abcde"}, | ||||
| 		{"abcde", "xyz", 4, "abcde"}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		actual := PadBoth(test.param1, test.param2, test.param3) | ||||
| 		if actual != test.expected { | ||||
| 			t.Errorf("Expected PadBoth(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,15 +0,0 @@ | |||
| box: golang | ||||
| build: | ||||
|   steps: | ||||
|     - setup-go-workspace | ||||
| 
 | ||||
|     - script: | ||||
|         name: go get | ||||
|         code: | | ||||
|           go version | ||||
|           go get -t ./... | ||||
| 
 | ||||
|     - script: | ||||
|         name: go test | ||||
|         code: | | ||||
|           go test -race ./... | ||||
		Loading…
	
		Reference in New Issue