pax_global_header 0000666 0000000 0000000 00000000064 15124100770 0014507 g ustar 00root root 0000000 0000000 52 comment=f418fa915fd144ba0d1d7d4f61e6f4882949a2d8
golang-github-go-playground-validator-v10-10.30.1/ 0000775 0000000 0000000 00000000000 15124100770 0021554 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/.github/ 0000775 0000000 0000000 00000000000 15124100770 0023114 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/.github/CODEOWNERS 0000664 0000000 0000000 00000000046 15124100770 0024507 0 ustar 00root root 0000000 0000000 * @go-playground/validator-maintainers golang-github-go-playground-validator-v10-10.30.1/.github/CONTRIBUTING.md 0000664 0000000 0000000 00000001033 15124100770 0025342 0 ustar 00root root 0000000 0000000 # Contribution Guidelines
## Quality Standard
To ensure the continued stability of this package, tests are required that cover the change in order for a pull request to be merged.
## Reporting issues
Please open an issue or join the gitter chat [](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) for any issues, questions or possible enhancements to the package.
golang-github-go-playground-validator-v10-10.30.1/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15124100770 0025277 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/.github/ISSUE_TEMPLATE/bug_report.yml 0000664 0000000 0000000 00000001376 15124100770 0030201 0 ustar 00root root 0000000 0000000 name: Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: What version of validator are you running?
validations:
required: true
- type: textarea
id: code
attributes:
label: Example Code
description: Please provide a code example that demonstrates the issue
render: go
validations:
required: true golang-github-go-playground-validator-v10-10.30.1/.github/PULL_REQUEST_TEMPLATE.md 0000664 0000000 0000000 00000000316 15124100770 0026715 0 ustar 00root root 0000000 0000000 ## Fixes Or Enhances
**Make sure that you've checked the boxes below before you submit PR:**
- [ ] Tests exist or have been written that cover this particular change.
@go-playground/validator-maintainers golang-github-go-playground-validator-v10-10.30.1/.github/dependabot.yml 0000664 0000000 0000000 00000000405 15124100770 0025743 0 ustar 00root root 0000000 0000000 version: 2
updates:
# Maintain dependencies for Golang
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
# Maintain dependencies for GitHub Actions
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
golang-github-go-playground-validator-v10-10.30.1/.github/workflows/ 0000775 0000000 0000000 00000000000 15124100770 0025151 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/.github/workflows/go.yml 0000664 0000000 0000000 00000000665 15124100770 0026310 0 ustar 00root root 0000000 0000000 on:
push:
branches:
- master
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.24.x, 1.25.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}
- name: Test
run: go test -race ./...
golang-github-go-playground-validator-v10-10.30.1/.github/workflows/workflow.yml 0000664 0000000 0000000 00000001775 15124100770 0027560 0 ustar 00root root 0000000 0000000 on:
push:
branches:
- master
pull_request:
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.24.x, 1.25.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}
- name: Test
run: go test -race -covermode=atomic -coverprofile="profile.cov" ./...
- name: Send Coverage
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.24.x'
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: 1.24.x
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: latest golang-github-go-playground-validator-v10-10.30.1/.gitignore 0000664 0000000 0000000 00000000515 15124100770 0023545 0 ustar 00root root 0000000 0000000 # Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
bin
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
*.test
*.out
*.txt
/**/*.DS_Store
cover.html
README.html
.idea
golang-github-go-playground-validator-v10-10.30.1/.golangci.yaml 0000664 0000000 0000000 00000001500 15124100770 0024275 0 ustar 00root root 0000000 0000000 version: "2"
linters:
default: all
disable:
- noinlineerr
- wsl_v5
- copyloopvar
- cyclop
- depguard
- dogsled
- dupl
- dupword
- err113
- errorlint
- exhaustive
- exhaustruct
- forbidigo
- forcetypeassert
- funlen
- gochecknoglobals
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- gosec
- gosmopolitan
- interfacebloat
- intrange
- ireturn
- lll
- maintidx
- misspell
- mnd
- modernize
- nakedret
- nestif
- nilnil
- nlreturn
- nonamedreturns
- paralleltest
- perfsprint
- prealloc
- recvcheck
- revive
- staticcheck
- tagalign
- tagliatelle
- testpackage
- thelper
- tparallel
- unparam
- varnamelen
- wrapcheck
- wsl
golang-github-go-playground-validator-v10-10.30.1/LICENSE 0000664 0000000 0000000 00000002065 15124100770 0022564 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2015 Dean Karn
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.
golang-github-go-playground-validator-v10-10.30.1/MAINTAINERS.md 0000664 0000000 0000000 00000000702 15124100770 0023647 0 ustar 00root root 0000000 0000000 ## Maintainers Guide
### Semantic Versioning
Semantic versioning as defined [here](https://semver.org) must be strictly adhered to.
### External Dependencies
Any new external dependencies MUST:
- Have a compatible LICENSE present.
- Be actively maintained.
- Be approved by @go-playground/admins
### PR Merge Requirements
- Up-to-date branch.
- Passing tests and linting.
- CODEOWNERS approval.
- Tests that cover both the Happy and Unhappy paths. golang-github-go-playground-validator-v10-10.30.1/Makefile 0000664 0000000 0000000 00000000617 15124100770 0023220 0 ustar 00root root 0000000 0000000 GOCMD=go
linters-install:
@golangci-lint --version >/dev/null 2>&1 || { \
echo "installing linting tools..."; \
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v2.0.2; \
}
lint: linters-install
golangci-lint run
test:
$(GOCMD) test -cover -race ./...
bench:
$(GOCMD) test -run=NONE -bench=. -benchmem ./...
.PHONY: test lint linters-install
golang-github-go-playground-validator-v10-10.30.1/README.md 0000664 0000000 0000000 00000053300 15124100770 0023034 0 ustar 00root root 0000000 0000000 Package validator
=================
[](https://github.com/go-playground/validator/releases)
[](https://github.com/go-playground/validator/actions)
[](https://coveralls.io/github/go-playground/validator?branch=master)
[](https://goreportcard.com/report/github.com/go-playground/validator)
[](https://pkg.go.dev/github.com/go-playground/validator/v10)

Package validator implements value validations for structs and individual fields based on tags.
It has the following **unique** features:
- Cross Field and Cross Struct validations by using validation tags or custom validators.
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
- Ability to dive into both map keys and values for validation
- Handles type interface by determining it's underlying type prior to validation.
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)
- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs
- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError
- Customizable i18n aware error messages.
- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/master/_examples/gin-upgrading-overriding)
A Call for Maintainers
----------------------
Please read the discussiong started [here](https://github.com/go-playground/validator/discussions/1330) if you are interested in contributing/helping maintain this package.
Installation
------------
Use go get.
go get github.com/go-playground/validator/v10
Then import the validator package into your own code.
import "github.com/go-playground/validator/v10"
Error Return Value
-------
Validation functions return type error
They return type error to avoid the issue discussed in the following, where err is always != nil:
* http://stackoverflow.com/a/29138676/3158232
* https://github.com/go-playground/validator/issues/134
Validator returns only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so:
```go
err := validate.Struct(mystruct)
validationErrors := err.(validator.ValidationErrors)
```
Usage and documentation
------
Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs.
##### Examples:
- [Simple](https://github.com/go-playground/validator/blob/master/_examples/simple/main.go)
- [Custom Field Types](https://github.com/go-playground/validator/blob/master/_examples/custom/main.go)
- [Struct Level](https://github.com/go-playground/validator/blob/master/_examples/struct-level/main.go)
- [Translations & Custom Errors](https://github.com/go-playground/validator/blob/master/_examples/translations/main.go)
- [Gin upgrade and/or override validator](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding)
- [wash - an example application putting it all together](https://github.com/bluesuncorp/wash)
Baked-in Validations
------
### Special Notes:
- If new to using validator it is highly recommended to initialize it using the `WithRequiredStructEnabled` option which is opt-in to new behaviour that will become the default behaviour in v11+. See documentation for more details.
```go
validate := validator.New(validator.WithRequiredStructEnabled())
```
### Fields:
| Tag | Description |
| - | - |
| eqcsfield | Field Equals Another Field (relative)|
| eqfield | Field Equals Another Field |
| fieldcontains | Check the indicated characters are present in the Field |
| fieldexcludes | Check the indicated characters are not present in the field |
| gtcsfield | Field Greater Than Another Relative Field |
| gtecsfield | Field Greater Than or Equal To Another Relative Field |
| gtefield | Field Greater Than or Equal To Another Field |
| gtfield | Field Greater Than Another Field |
| ltcsfield | Less Than Another Relative Field |
| ltecsfield | Less Than or Equal To Another Relative Field |
| ltefield | Less Than or Equal To Another Field |
| ltfield | Less Than Another Field |
| necsfield | Field Does Not Equal Another Field (relative) |
| nefield | Field Does Not Equal Another Field |
### Network:
| Tag | Description |
| - | - |
| cidr | Classless Inter-Domain Routing CIDR |
| cidrv4 | Classless Inter-Domain Routing CIDRv4 |
| cidrv6 | Classless Inter-Domain Routing CIDRv6 |
| datauri | Data URL |
| fqdn | Full Qualified Domain Name (FQDN) |
| hostname | Hostname RFC 952 |
| hostname_rfc1123 | Hostname RFC 1123 |
| hostname_port | HostPort |
| port | Port number |
| ip | Internet Protocol Address IP |
| ip4_addr | Internet Protocol Address IPv4 |
| ip6_addr | Internet Protocol Address IPv6 |
| ip_addr | Internet Protocol Address IP |
| ipv4 | Internet Protocol Address IPv4 |
| ipv6 | Internet Protocol Address IPv6 |
| mac | Media Access Control Address MAC |
| tcp4_addr | Transmission Control Protocol Address TCPv4 |
| tcp6_addr | Transmission Control Protocol Address TCPv6 |
| tcp_addr | Transmission Control Protocol Address TCP |
| udp4_addr | User Datagram Protocol Address UDPv4 |
| udp6_addr | User Datagram Protocol Address UDPv6 |
| udp_addr | User Datagram Protocol Address UDP |
| unix_addr | Unix domain socket end point Address |
| uds_exists | Unix domain socket exists (checks filesystem sockets and Linux abstract sockets) |
| uri | URI String |
| url | URL String |
| http_url | HTTP(s) URL String |
| https_url | HTTPS-only URL String |
| url_encoded | URL Encoded |
| urn_rfc2141 | Urn RFC 2141 String |
### Strings:
| Tag | Description |
| - | - |
| alpha | Alpha Only |
| alphaspace | Alpha Space |
| alphanum | Alphanumeric |
| alphanumspace | Alphanumeric Space |
| alphanumunicode | Alphanumeric Unicode |
| alphaunicode | Alpha Unicode |
| ascii | ASCII |
| boolean | Boolean |
| contains | Contains |
| containsany | Contains Any |
| containsrune | Contains Rune |
| endsnotwith | Ends Not With |
| endswith | Ends With |
| excludes | Excludes |
| excludesall | Excludes All |
| excludesrune | Excludes Rune |
| lowercase | Lowercase |
| multibyte | Multi-Byte Characters |
| number | Number |
| numeric | Numeric |
| printascii | Printable ASCII |
| startsnotwith | Starts Not With |
| startswith | Starts With |
| uppercase | Uppercase |
### Format:
| Tag | Description |
| - | - |
| base64 | Base64 String |
| base64url | Base64URL String |
| base64rawurl | Base64RawURL String |
| bic_iso_9362_2014 | Business Identifier Code (ISO 9362:2014) |
| bic | Business Identifier Code (ISO 9362:2022) |
| bcp47_language_tag | Language tag (BCP 47) |
| btc_addr | Bitcoin Address |
| btc_addr_bech32 | Bitcoin Bech32 Address (segwit) |
| credit_card | Credit Card Number |
| mongodb | MongoDB ObjectID |
| mongodb_connection_string | MongoDB Connection String |
| cron | Cron |
| spicedb | SpiceDb ObjectID/Permission/Type |
| datetime | Datetime |
| e164 | e164 formatted phone number |
| ein | U.S. Employeer Identification Number |
| email | E-mail String
| eth_addr | Ethereum Address |
| hexadecimal | Hexadecimal String |
| hexcolor | Hexcolor String |
| hsl | HSL String |
| hsla | HSLA String |
| html | HTML Tags |
| html_encoded | HTML Encoded |
| isbn | International Standard Book Number |
| isbn10 | International Standard Book Number 10 |
| isbn13 | International Standard Book Number 13 |
| issn | International Standard Serial Number |
| iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) |
| iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) |
| iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) |
| iso3166_2 | Country subdivision code (ISO 3166-2) |
| iso4217 | Currency code (ISO 4217) |
| json | JSON |
| jwt | JSON Web Token (JWT) |
| latitude | Latitude |
| longitude | Longitude |
| luhn_checksum | Luhn Algorithm Checksum (for strings and (u)int) |
| postcode_iso3166_alpha2 | Postcode |
| postcode_iso3166_alpha2_field | Postcode |
| rgb | RGB String |
| rgba | RGBA String |
| ssn | Social Security Number SSN |
| timezone | Timezone |
| uuid | Universally Unique Identifier UUID |
| uuid3 | Universally Unique Identifier UUID v3 |
| uuid3_rfc4122 | Universally Unique Identifier UUID v3 RFC4122 |
| uuid4 | Universally Unique Identifier UUID v4 |
| uuid4_rfc4122 | Universally Unique Identifier UUID v4 RFC4122 |
| uuid5 | Universally Unique Identifier UUID v5 |
| uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 |
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |
| md4 | MD4 hash |
| md5 | MD5 hash |
| sha256 | SHA256 hash |
| sha384 | SHA384 hash |
| sha512 | SHA512 hash |
| ripemd128 | RIPEMD-128 hash |
| ripemd128 | RIPEMD-160 hash |
| tiger128 | TIGER128 hash |
| tiger160 | TIGER160 hash |
| tiger192 | TIGER192 hash |
| semver | Semantic Versioning 2.0.0 |
| ulid | Universally Unique Lexicographically Sortable Identifier ULID |
| cve | Common Vulnerabilities and Exposures Identifier (CVE id) |
### Comparisons:
| Tag | Description |
| - | - |
| eq | Equals |
| eq_ignore_case | Equals ignoring case |
| gt | Greater than|
| gte | Greater than or equal |
| lt | Less Than |
| lte | Less Than or Equal |
| ne | Not Equal |
| ne_ignore_case | Not Equal ignoring case |
### Other:
| Tag | Description |
| - | - |
| dir | Existing Directory |
| dirpath | Directory Path |
| file | Existing File |
| filepath | File Path |
| image | Image |
| isdefault | Is Default |
| len | Length |
| max | Maximum |
| min | Minimum |
| oneof | One Of |
| required | Required |
| required_if | Required If |
| required_unless | Required Unless |
| required_with | Required With |
| required_with_all | Required With All |
| required_without | Required Without |
| required_without_all | Required Without All |
| excluded_if | Excluded If |
| excluded_unless | Excluded Unless |
| excluded_with | Excluded With |
| excluded_with_all | Excluded With All |
| excluded_without | Excluded Without |
| excluded_without_all | Excluded Without All |
| unique | Unique |
| validateFn | Verify if the method `Validate() error` does not return an error (or any specified method) |
#### Aliases:
| Tag | Description |
| - | - |
| iscolor | hexcolor\|rgb\|rgba\|hsl\|hsla |
| country_code | iso3166_1_alpha2\|iso3166_1_alpha3\|iso3166_1_alpha_numeric |
Benchmarks
------
###### Run on MacBook Pro Max M3
```go
go version go1.23.3 darwin/arm64
goos: darwin
goarch: arm64
cpu: Apple M3 Max
pkg: github.com/go-playground/validator/v10
BenchmarkFieldSuccess-16 42461943 27.88 ns/op 0 B/op 0 allocs/op
BenchmarkFieldSuccessParallel-16 486632887 2.289 ns/op 0 B/op 0 allocs/op
BenchmarkFieldFailure-16 9566167 121.3 ns/op 200 B/op 4 allocs/op
BenchmarkFieldFailureParallel-16 17551471 83.68 ns/op 200 B/op 4 allocs/op
BenchmarkFieldArrayDiveSuccess-16 7602306 155.6 ns/op 97 B/op 5 allocs/op
BenchmarkFieldArrayDiveSuccessParallel-16 20664610 59.80 ns/op 97 B/op 5 allocs/op
BenchmarkFieldArrayDiveFailure-16 4659756 252.9 ns/op 301 B/op 10 allocs/op
BenchmarkFieldArrayDiveFailureParallel-16 8010116 152.9 ns/op 301 B/op 10 allocs/op
BenchmarkFieldMapDiveSuccess-16 2834575 421.2 ns/op 288 B/op 14 allocs/op
BenchmarkFieldMapDiveSuccessParallel-16 7179700 171.8 ns/op 288 B/op 14 allocs/op
BenchmarkFieldMapDiveFailure-16 3081728 384.4 ns/op 376 B/op 13 allocs/op
BenchmarkFieldMapDiveFailureParallel-16 6058137 204.0 ns/op 377 B/op 13 allocs/op
BenchmarkFieldMapDiveWithKeysSuccess-16 2544975 464.8 ns/op 288 B/op 14 allocs/op
BenchmarkFieldMapDiveWithKeysSuccessParallel-16 6661954 181.4 ns/op 288 B/op 14 allocs/op
BenchmarkFieldMapDiveWithKeysFailure-16 2435484 490.7 ns/op 553 B/op 16 allocs/op
BenchmarkFieldMapDiveWithKeysFailureParallel-16 4249617 282.0 ns/op 554 B/op 16 allocs/op
BenchmarkFieldCustomTypeSuccess-16 14943525 77.35 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeSuccessParallel-16 64051954 20.61 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeFailure-16 10721384 107.1 ns/op 184 B/op 3 allocs/op
BenchmarkFieldCustomTypeFailureParallel-16 18714495 69.77 ns/op 184 B/op 3 allocs/op
BenchmarkFieldOrTagSuccess-16 4063124 294.3 ns/op 16 B/op 1 allocs/op
BenchmarkFieldOrTagSuccessParallel-16 31903756 41.22 ns/op 18 B/op 1 allocs/op
BenchmarkFieldOrTagFailure-16 7748558 146.8 ns/op 216 B/op 5 allocs/op
BenchmarkFieldOrTagFailureParallel-16 13139854 92.05 ns/op 216 B/op 5 allocs/op
BenchmarkStructLevelValidationSuccess-16 16808389 70.25 ns/op 16 B/op 1 allocs/op
BenchmarkStructLevelValidationSuccessParallel-16 90686955 14.47 ns/op 16 B/op 1 allocs/op
BenchmarkStructLevelValidationFailure-16 5818791 200.2 ns/op 264 B/op 7 allocs/op
BenchmarkStructLevelValidationFailureParallel-16 11115874 107.5 ns/op 264 B/op 7 allocs/op
BenchmarkStructSimpleCustomTypeSuccess-16 7764956 151.9 ns/op 32 B/op 2 allocs/op
BenchmarkStructSimpleCustomTypeSuccessParallel-16 52316265 30.37 ns/op 32 B/op 2 allocs/op
BenchmarkStructSimpleCustomTypeFailure-16 4195429 277.2 ns/op 416 B/op 9 allocs/op
BenchmarkStructSimpleCustomTypeFailureParallel-16 7305661 164.6 ns/op 432 B/op 10 allocs/op
BenchmarkStructFilteredSuccess-16 6312625 186.1 ns/op 216 B/op 5 allocs/op
BenchmarkStructFilteredSuccessParallel-16 13684459 93.42 ns/op 216 B/op 5 allocs/op
BenchmarkStructFilteredFailure-16 6751482 171.2 ns/op 216 B/op 5 allocs/op
BenchmarkStructFilteredFailureParallel-16 14146070 86.93 ns/op 216 B/op 5 allocs/op
BenchmarkStructPartialSuccess-16 6544448 177.3 ns/op 224 B/op 4 allocs/op
BenchmarkStructPartialSuccessParallel-16 13951946 88.73 ns/op 224 B/op 4 allocs/op
BenchmarkStructPartialFailure-16 4075833 287.5 ns/op 440 B/op 9 allocs/op
BenchmarkStructPartialFailureParallel-16 7490805 161.3 ns/op 440 B/op 9 allocs/op
BenchmarkStructExceptSuccess-16 4107187 281.4 ns/op 424 B/op 8 allocs/op
BenchmarkStructExceptSuccessParallel-16 15979173 80.86 ns/op 208 B/op 3 allocs/op
BenchmarkStructExceptFailure-16 4434372 264.3 ns/op 424 B/op 8 allocs/op
BenchmarkStructExceptFailureParallel-16 8081367 154.1 ns/op 424 B/op 8 allocs/op
BenchmarkStructSimpleCrossFieldSuccess-16 6459542 183.4 ns/op 56 B/op 3 allocs/op
BenchmarkStructSimpleCrossFieldSuccessParallel-16 41013781 37.95 ns/op 56 B/op 3 allocs/op
BenchmarkStructSimpleCrossFieldFailure-16 4034998 292.1 ns/op 272 B/op 8 allocs/op
BenchmarkStructSimpleCrossFieldFailureParallel-16 11348446 115.3 ns/op 272 B/op 8 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldSuccess-16 4448528 267.7 ns/op 64 B/op 4 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-16 26813619 48.33 ns/op 64 B/op 4 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldFailure-16 3090646 384.5 ns/op 288 B/op 9 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-16 9870906 129.5 ns/op 288 B/op 9 allocs/op
BenchmarkStructSimpleSuccess-16 10675562 109.5 ns/op 0 B/op 0 allocs/op
BenchmarkStructSimpleSuccessParallel-16 131159784 8.932 ns/op 0 B/op 0 allocs/op
BenchmarkStructSimpleFailure-16 4094979 286.6 ns/op 416 B/op 9 allocs/op
BenchmarkStructSimpleFailureParallel-16 7606663 157.9 ns/op 416 B/op 9 allocs/op
BenchmarkStructComplexSuccess-16 2073470 576.0 ns/op 224 B/op 5 allocs/op
BenchmarkStructComplexSuccessParallel-16 7821831 161.3 ns/op 224 B/op 5 allocs/op
BenchmarkStructComplexFailure-16 576358 2001 ns/op 3042 B/op 48 allocs/op
BenchmarkStructComplexFailureParallel-16 1000000 1171 ns/op 3041 B/op 48 allocs/op
BenchmarkOneof-16 22503973 52.82 ns/op 0 B/op 0 allocs/op
BenchmarkOneofParallel-16 8538474 140.4 ns/op 0 B/op 0 allocs/op
```
Complementary Software
----------------------
Here is a list of software that complements using this library either pre or post validation.
* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
* [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects
How to Contribute
------
Make a pull request...
Maintenance and support for SDK major versions
----------------------------------------------
See prior discussion [here](https://github.com/go-playground/validator/discussions/1342) for more details.
This package is aligned with the [Go release policy](https://go.dev/doc/devel/release) in that support is guaranteed for
the two most recent major versions.
This does not mean the package will not work with older versions of Go, only that we reserve the right to increase the
MSGV(Minimum Supported Go Version) when the need arises to address Security issues/patches, OS issues & support or newly
introduced functionality that would greatly benefit the maintenance and/or usage of this package.
If and when the MSGV is increased it will be done so in a minimum of a `Minor` release bump.
License
-------
Distributed under MIT License, please see license file within the code for more details.
Maintainers
-----------
This project has grown large enough that more than one person is required to properly support the community.
If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn
golang-github-go-playground-validator-v10-10.30.1/_examples/ 0000775 0000000 0000000 00000000000 15124100770 0023531 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/custom-validation/ 0000775 0000000 0000000 00000000000 15124100770 0027173 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/custom-validation/main.go 0000664 0000000 0000000 00000001317 15124100770 0030450 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// MyStruct ..
type MyStruct struct {
String string `validate:"is-awesome"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
validate.RegisterValidation("is-awesome", ValidateMyVal)
s := MyStruct{String: "awesome"}
err := validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
s.String = "not awesome"
err = validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateMyVal implements validator.Func
func ValidateMyVal(fl validator.FieldLevel) bool {
return fl.Field().String() == "awesome"
}
golang-github-go-playground-validator-v10-10.30.1/_examples/custom/ 0000775 0000000 0000000 00000000000 15124100770 0025043 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/custom/main.go 0000664 0000000 0000000 00000002137 15124100770 0026321 0 ustar 00root root 0000000 0000000 package main
import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
"github.com/go-playground/validator/v10"
)
// DbBackedUser User struct
type DbBackedUser struct {
Name sql.NullString `validate:"required"`
Age sql.NullInt64 `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// register all sql.Null* types to use the ValidateValuer CustomTypeFunc
validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
// build object for validation
x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
err := validate.Struct(x)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateValuer implements validator.CustomTypeFunc
func ValidateValuer(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(driver.Valuer); ok {
val, err := valuer.Value()
if err == nil {
return val
}
// handle the error how you want
}
return nil
}
golang-github-go-playground-validator-v10-10.30.1/_examples/dive/ 0000775 0000000 0000000 00000000000 15124100770 0024460 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/dive/main.go 0000664 0000000 0000000 00000001400 15124100770 0025726 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// Test ...
type Test struct {
Array []string `validate:"required,gt=0,dive,required"`
Map map[string]string `validate:"required,gt=0,dive,keys,keymax,endkeys,required,max=1000"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// registering alias so we can see the differences between
// map key, value validation errors
validate.RegisterAlias("keymax", "max=10")
var test Test
val(test)
test.Array = []string{""}
test.Map = map[string]string{"test > than 10": ""}
val(test)
}
func val(test Test) {
fmt.Println("testing")
err := validate.Struct(test)
fmt.Println(err)
}
golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/ 0000775 0000000 0000000 00000000000 15124100770 0030432 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/main.go 0000664 0000000 0000000 00000000214 15124100770 0031702 0 ustar 00root root 0000000 0000000 package main
import "github.com/gin-gonic/gin/binding"
func main() {
binding.Validator = new(defaultValidator)
// regular gin logic
}
golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/v8_to_v9.go 0000664 0000000 0000000 00000001644 15124100770 0032443 0 ustar 00root root 0000000 0000000 package main
import (
"reflect"
"sync"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type defaultValidator struct {
once sync.Once
validate *validator.Validate
}
var _ binding.StructValidator = &defaultValidator{}
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if kindOfData(obj) == reflect.Struct {
v.lazyinit()
if err := v.validate.Struct(obj); err != nil {
return err
}
}
return nil
}
func (v *defaultValidator) Engine() interface{} {
v.lazyinit()
return v.validate
}
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
v.validate.SetTagName("binding")
// add any custom validations etc. here
})
}
func kindOfData(data interface{}) reflect.Kind {
value := reflect.ValueOf(data)
valueType := value.Kind()
if valueType == reflect.Ptr {
valueType = value.Elem().Kind()
}
return valueType
}
golang-github-go-playground-validator-v10-10.30.1/_examples/http-transalations/ 0000775 0000000 0000000 00000000000 15124100770 0027370 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/http-transalations/main.go 0000664 0000000 0000000 00000004372 15124100770 0030651 0 ustar 00root root 0000000 0000000 package main
import (
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
"github.com/go-playground/locales/zh_Hant_TW"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
zh_tw_translations "github.com/go-playground/validator/v10/translations/zh_tw"
)
var uni *ut.UniversalTranslator
// This example showcases how to use the Validator and UniversalTranslator with both Simplified and Traditional Chinese languages.
// To run the example:
// Step 1: go run _examples/http-transalations/main.go
// Step 2 - Simplified Chinese: curl -d '{"first_name":"foo"}' -H "Accept-Language: zh" -H "Content-Type: application/json" -X POST http://localhost:8081/users
// Step 3 - Traditional Chinese: curl -d '{"first_name":"foo"}' -H "Accept-Language: zh-Hant-TW" -H "Content-Type: application/json" -X POST http://localhost:8081/users
func main() {
validate := validator.New()
en := en.New()
uni = ut.New(en, en, zh.New(), zh_Hant_TW.New())
validate = validator.New()
enTrans, _ := uni.GetTranslator("en")
en_translations.RegisterDefaultTranslations(validate, enTrans)
zhTrans, _ := uni.GetTranslator("zh")
zh_translations.RegisterDefaultTranslations(validate, zhTrans)
zhHantTrans, _ := uni.GetTranslator("zh_Hant_TW")
zh_tw_translations.RegisterDefaultTranslations(validate, zhHantTrans)
type User struct {
FirstName string `json:"first_name" validate:"required"`
LastName string `json:"last_name" validate:"required"`
}
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
// ... fill user value
var user User
// Header Accept-Language value is en or zh
trans, _ := uni.GetTranslator(strings.Replace(r.Header.Get("Accept-Language"), "-", "_", -1))
if err := validate.Struct(&user); err != nil {
var errs validator.ValidationErrors
var httpErrors []validator.ValidationErrorsTranslations
if errors.As(err, &errs) {
httpErrors = append(httpErrors, errs.Translate(trans))
}
r, _ := json.Marshal(httpErrors)
w.Write(r)
}
})
http.ListenAndServe(":8081", nil)
}
golang-github-go-playground-validator-v10-10.30.1/_examples/map-validation/ 0000775 0000000 0000000 00000000000 15124100770 0026436 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/map-validation/main.go 0000664 0000000 0000000 00000004310 15124100770 0027707 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
var validate *validator.Validate
func main() {
validate = validator.New()
validateMap()
validateNestedMap()
}
func validateMap() {
user := map[string]interface{}{"name": "Arshiya Kiani", "email": "zytel3301@gmail.com"}
// Every rule will be applied to the item of the data that the offset of rule is pointing to.
// So if you have a field "email": "omitempty,required,email", the validator will apply these
// rules to offset of email in user data
rules := map[string]interface{}{"name": "required,min=8,max=32", "email": "omitempty,required,email"}
// ValidateMap will return map[string]error.
// The offset of every item in errs is the name of invalid field and the value
// is the message of error. If there was no error, ValidateMap method will
// return an EMPTY map of errors, not nil. If you want to check that
// if there was an error or not, you must check the length of the return value
errs := validate.ValidateMap(user, rules)
if len(errs) > 0 {
fmt.Println(errs)
// The user is invalid
}
// The user is valid
}
func validateNestedMap() {
data := map[string]interface{}{
"name": "Arshiya Kiani",
"email": "zytel3301@gmail.com",
"details": map[string]interface{}{
"family_members": map[string]interface{}{
"father_name": "Micheal",
"mother_name": "Hannah",
},
"salary": "1000",
"phones": []map[string]interface{}{
{
"number": "11-111-1111",
"remark": "home",
},
{
"number": "22-222-2222",
"remark": "work",
},
},
},
}
// Rules must be set as the structure as the data itself. If you want to dive into the
// map, just declare its rules as a map
rules := map[string]interface{}{
"name": "min=4,max=32",
"email": "required,email",
"details": map[string]interface{}{
"family_members": map[string]interface{}{
"father_name": "required,min=4,max=32",
"mother_name": "required,min=4,max=32",
},
"salary": "number",
"phones": map[string]interface{}{
"number": "required,min=4,max=32",
"remark": "required,min=1,max=32",
},
},
}
if len(validate.ValidateMap(data, rules)) == 0 {
// Data is valid
}
// Data is invalid
}
golang-github-go-playground-validator-v10-10.30.1/_examples/simple/ 0000775 0000000 0000000 00000000000 15124100770 0025022 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/simple/main.go 0000664 0000000 0000000 00000005177 15124100770 0026307 0 ustar 00root root 0000000 0000000 package main
import (
"errors"
"fmt"
"github.com/go-playground/validator/v10"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
Gender string `validate:"oneof=male female prefer_not_to"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New(validator.WithRequiredStructEnabled())
validateStruct()
validateVariable()
}
func validateStruct() {
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
}
user := &User{
FirstName: "Badger",
LastName: "Smith",
Age: 135,
Gender: "male",
Email: "Badger.Smith@gmail.com",
FavouriteColor: "#000-",
Addresses: []*Address{address},
}
// returns nil or ValidationErrors ( []FieldError )
err := validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
var invalidValidationError *validator.InvalidValidationError
if errors.As(err, &invalidValidationError) {
fmt.Println(err)
return
}
var validateErrs validator.ValidationErrors
if errors.As(err, &validateErrs) {
for _, e := range validateErrs {
fmt.Println(e.Namespace())
fmt.Println(e.Field())
fmt.Println(e.StructNamespace())
fmt.Println(e.StructField())
fmt.Println(e.Tag())
fmt.Println(e.ActualTag())
fmt.Println(e.Kind())
fmt.Println(e.Type())
fmt.Println(e.Value())
fmt.Println(e.Param())
fmt.Println()
}
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
func validateVariable() {
myEmail := "joeybloggs.gmail.com"
errs := validate.Var(myEmail, "required,email")
if errs != nil {
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
return
}
// email ok, move on
}
golang-github-go-playground-validator-v10-10.30.1/_examples/struct-level/ 0000775 0000000 0000000 00000000000 15124100770 0026162 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/struct-level/main.go 0000664 0000000 0000000 00000012403 15124100770 0027435 0 ustar 00root root 0000000 0000000 package main
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
"github.com/go-playground/validator/v10"
)
type validationError struct {
Namespace string `json:"namespace"` // can differ when a custom TagNameFunc is registered or
Field string `json:"field"` // by passing alt name to ReportError like below
StructNamespace string `json:"structNamespace"`
StructField string `json:"structField"`
Tag string `json:"tag"`
ActualTag string `json:"actualTag"`
Kind string `json:"kind"`
Type string `json:"type"`
Value string `json:"value"`
Param string `json:"param"`
Message string `json:"message"`
}
type Gender uint
const (
Male Gender = iota + 1
Female
Intersex
)
func (gender Gender) String() string {
terms := []string{"Male", "Female", "Intersex"}
if gender < Male || gender > Intersex {
return "unknown"
}
return terms[gender]
}
// User contains user information
type User struct {
FirstName string `json:"fname"`
LastName string `json:"lname"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `json:"e-mail" validate:"required,email"`
FavouriteColor string `validate:"hexcolor|rgb|rgba"`
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
Gender Gender `json:"gender" validate:"required,gender_custom_validation"`
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// register function to get tag name from json tags.
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// register validation for 'User'
// NOTE: only have to register a non-pointer type for 'User', validator
// internally dereferences during it's type checks.
validate.RegisterStructValidation(UserStructLevelValidation, User{})
// register a custom validation for user genre on a line
// validates that an enum is within the interval
err := validate.RegisterValidation("gender_custom_validation", func(fl validator.FieldLevel) bool {
value := fl.Field().Interface().(Gender)
return value.String() != "unknown"
})
if err != nil {
fmt.Println(err)
return
}
// build 'User' info, normally posted data etc...
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
City: "Unknown",
}
user := &User{
FirstName: "",
LastName: "",
Age: 45,
Email: "Badger.Smith@gmail",
FavouriteColor: "#000",
Addresses: []*Address{address},
}
// returns InvalidValidationError for bad validation input, nil or ValidationErrors ( []FieldError )
err = validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
var invalidValidationError *validator.InvalidValidationError
if errors.As(err, &invalidValidationError) {
fmt.Println(err)
return
}
var validateErrs validator.ValidationErrors
if errors.As(err, &validateErrs) {
for _, err := range validateErrs {
e := validationError{
Namespace: err.Namespace(),
Field: err.Field(),
StructNamespace: err.StructNamespace(),
StructField: err.StructField(),
Tag: err.Tag(),
ActualTag: err.ActualTag(),
Kind: fmt.Sprintf("%v", err.Kind()),
Type: fmt.Sprintf("%v", err.Type()),
Value: fmt.Sprintf("%v", err.Value()),
Param: err.Param(),
Message: err.Error(),
}
indent, err := json.MarshalIndent(e, "", " ")
if err != nil {
fmt.Println(err)
panic(err)
}
fmt.Println(string(indent))
}
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
// UserStructLevelValidation contains custom struct level validations that don't always
// make sense at the field validation level. For example, this function validates that either
// FirstName or LastName exist; could have done that with a custom field validation but then
// would have had to add it to both fields duplicating the logic + overhead, this way it's
// only validated once.
//
// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way
// hooks right into validator and you can combine with validation tags and still have a
// common error output format.
func UserStructLevelValidation(sl validator.StructLevel) {
user := sl.Current().Interface().(User)
if len(user.FirstName) == 0 && len(user.LastName) == 0 {
sl.ReportError(user.FirstName, "fname", "FirstName", "fnameorlname", "")
sl.ReportError(user.LastName, "lname", "LastName", "fnameorlname", "")
}
// plus can do more, even with different tag than "fnameorlname"
}
golang-github-go-playground-validator-v10-10.30.1/_examples/struct-map-rules-validation/ 0000775 0000000 0000000 00000000000 15124100770 0031110 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/struct-map-rules-validation/main.go 0000664 0000000 0000000 00000003412 15124100770 0032363 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Data struct {
Name string
Email string
Details *Details
}
type Details struct {
FamilyMembers *FamilyMembers
Salary string
}
type FamilyMembers struct {
FatherName string
MotherName string
}
type Data2 struct {
Name string
Age uint32
}
var validate = validator.New()
func main() {
validateStruct()
// output
// Key: 'Data2.Name' Error:Field validation for 'Name' failed on the 'min' tag
// Key: 'Data2.Age' Error:Field validation for 'Age' failed on the 'max' tag
validateStructNested()
// output
// Key: 'Data.Name' Error:Field validation for 'Name' failed on the 'max' tag
// Key: 'Data.Details.FamilyMembers' Error:Field validation for 'FamilyMembers' failed on the 'required' tag
}
func validateStruct() {
data := Data2{
Name: "leo",
Age: 1000,
}
rules := map[string]string{
"Name": "min=4,max=6",
"Age": "min=4,max=6",
}
validate.RegisterStructValidationMapRules(rules, Data2{})
err := validate.Struct(data)
fmt.Println(err)
fmt.Println()
}
func validateStructNested() {
data := Data{
Name: "11sdfddd111",
Email: "zytel3301@mail.com",
Details: &Details{
Salary: "1000",
},
}
rules1 := map[string]string{
"Name": "min=4,max=6",
"Email": "required,email",
"Details": "required",
}
rules2 := map[string]string{
"Salary": "number",
"FamilyMembers": "required",
}
rules3 := map[string]string{
"FatherName": "required,min=4,max=32",
"MotherName": "required,min=4,max=32",
}
validate.RegisterStructValidationMapRules(rules1, Data{})
validate.RegisterStructValidationMapRules(rules2, Details{})
validate.RegisterStructValidationMapRules(rules3, FamilyMembers{})
err := validate.Struct(data)
fmt.Println(err)
}
golang-github-go-playground-validator-v10-10.30.1/_examples/translations/ 0000775 0000000 0000000 00000000000 15124100770 0026252 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/translations/main.go 0000664 0000000 0000000 00000006204 15124100770 0027527 0 ustar 00root root 0000000 0000000 package main
import (
"fmt"
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance, it caches struct info
var (
uni *ut.UniversalTranslator
validate *validator.Validate
)
func main() {
// NOTE: omitting allot of error checking for brevity
en := en.New()
uni = ut.New(en, en)
// this is usually know or extracted from http 'Accept-Language' header
// also see uni.FindTranslator(...)
trans, _ := uni.GetTranslator("en")
validate = validator.New()
en_translations.RegisterDefaultTranslations(validate, trans)
translateAll(trans)
translateIndividual(trans)
translateOverride(trans) // yep you can specify your own in whatever locale you want!
}
func translateAll(trans ut.Translator) {
type User struct {
Username string `validate:"required"`
Tagline string `validate:"required,lt=10"`
Tagline2 string `validate:"required,gt=1"`
}
user := User{
Username: "Joeybloggs",
Tagline: "This tagline is way too long.",
Tagline2: "1",
}
err := validate.Struct(user)
if err != nil {
// translate all error at once
errs := err.(validator.ValidationErrors)
// returns a map with key = namespace & value = translated error
// NOTICE: 2 errors are returned and you'll see something surprising
// translations are i18n aware!!!!
// eg. '10 characters' vs '1 character'
fmt.Println(errs.Translate(trans))
}
}
func translateIndividual(trans ut.Translator) {
type User struct {
Username string `validate:"required"`
}
var user User
err := validate.Struct(user)
if err != nil {
errs := err.(validator.ValidationErrors)
for _, e := range errs {
// can translate each error one at a time.
fmt.Println(e.Translate(trans))
}
}
}
func translateOverride(trans ut.Translator) {
validate.RegisterTranslation("required", trans, func(ut ut.Translator) error {
return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("required", fe.Field())
return t
})
type User struct {
Username string `validate:"required"`
}
var user User
err := validate.Struct(user)
if err != nil {
errs := err.(validator.ValidationErrors)
for _, e := range errs {
// can translate each error one at a time.
fmt.Println(e.Translate(trans))
}
}
}
golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/ 0000775 0000000 0000000 00000000000 15124100770 0026005 5 ustar 00root root 0000000 0000000 golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/enum_enumer.go 0000664 0000000 0000000 00000003620 15124100770 0030654 0 ustar 00root root 0000000 0000000 // Code generated by "enumer -type=Enum"; DO NOT EDIT.
package main
import (
"fmt"
"strings"
)
const _EnumName = "ZeroOneTwoThree"
var _EnumIndex = [...]uint8{0, 4, 7, 10, 15}
const _EnumLowerName = "zeroonetwothree"
func (i Enum) String() string {
if i >= Enum(len(_EnumIndex)-1) {
return fmt.Sprintf("Enum(%d)", i)
}
return _EnumName[_EnumIndex[i]:_EnumIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _EnumNoOp() {
var x [1]struct{}
_ = x[Zero-(0)]
_ = x[One-(1)]
_ = x[Two-(2)]
_ = x[Three-(3)]
}
var _EnumValues = []Enum{Zero, One, Two, Three}
var _EnumNameToValueMap = map[string]Enum{
_EnumName[0:4]: Zero,
_EnumLowerName[0:4]: Zero,
_EnumName[4:7]: One,
_EnumLowerName[4:7]: One,
_EnumName[7:10]: Two,
_EnumLowerName[7:10]: Two,
_EnumName[10:15]: Three,
_EnumLowerName[10:15]: Three,
}
var _EnumNames = []string{
_EnumName[0:4],
_EnumName[4:7],
_EnumName[7:10],
_EnumName[10:15],
}
// EnumString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func EnumString(s string) (Enum, error) {
if val, ok := _EnumNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _EnumNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Enum values", s)
}
// EnumValues returns all values of the enum
func EnumValues() []Enum {
return _EnumValues
}
// EnumStrings returns a slice of all String values of the enum
func EnumStrings() []string {
strs := make([]string, len(_EnumNames))
copy(strs, _EnumNames)
return strs
}
// IsAEnum returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Enum) IsAEnum() bool {
for _, v := range _EnumValues {
if i == v {
return true
}
}
return false
}
golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/go.mod 0000664 0000000 0000000 00000001140 15124100770 0027107 0 ustar 00root root 0000000 0000000 module github.com/peczenyj/validator/_examples/validate_fn
go 1.23.0
toolchain go1.24.4
replace github.com/go-playground/validator/v10 => ../../../validator
require github.com/go-playground/validator/v10 v10.26.0
require (
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
)
golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/go.sum 0000664 0000000 0000000 00000005003 15124100770 0027136 0 ustar 00root root 0000000 0000000 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/main.go 0000664 0000000 0000000 00000001423 15124100770 0027260 0 ustar 00root root 0000000 0000000 package main
import (
"errors"
"fmt"
"github.com/go-playground/validator/v10"
)
//go:generate enumer -type=Enum
type Enum uint8
const (
Zero Enum = iota
One
Two
Three
)
func (e *Enum) Validate() error {
if e == nil {
return errors.New("can't be nil")
}
return nil
}
type Struct struct {
Foo *Enum `validate:"validateFn"` // uses Validate() error by default
Bar Enum `validate:"validateFn=IsAEnum"` // uses IsAEnum() bool provided by enumer
}
func main() {
validate := validator.New()
var x Struct
x.Bar = Enum(64)
if err := validate.Struct(x); err != nil {
fmt.Printf("Expected Err(s):\n%+v\n", err)
}
x = Struct{
Foo: new(Enum),
Bar: One,
}
if err := validate.Struct(x); err != nil {
fmt.Printf("Unexpected Err(s):\n%+v\n", err)
}
}
golang-github-go-playground-validator-v10-10.30.1/baked_in.go 0000664 0000000 0000000 00000274005 15124100770 0023647 0 ustar 00root root 0000000 0000000 package validator
import (
"bufio"
"bytes"
"cmp"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/fs"
"net"
"net/mail"
"net/url"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"time"
"unicode/utf8"
"golang.org/x/crypto/sha3"
"golang.org/x/text/language"
"github.com/gabriel-vasile/mimetype"
urn "github.com/leodido/go-urn"
)
// Func accepts a FieldLevel interface for all validation needs. The return
// value should be true when validation succeeds.
type Func func(fl FieldLevel) bool
// FuncCtx accepts a context.Context and FieldLevel interface for all
// validation needs. The return value should be true when validation succeeds.
type FuncCtx func(ctx context.Context, fl FieldLevel) bool
// wrapFunc wraps normal Func makes it compatible with FuncCtx
func wrapFunc(fn Func) FuncCtx {
if fn == nil {
return nil // be sure not to wrap a bad function.
}
return func(ctx context.Context, fl FieldLevel) bool {
return fn(fl)
}
}
var (
restrictedTags = map[string]struct{}{
diveTag: {},
keysTag: {},
endKeysTag: {},
structOnlyTag: {},
omitzero: {},
omitempty: {},
omitnil: {},
skipValidationTag: {},
utf8HexComma: {},
utf8Pipe: {},
noStructLevelTag: {},
requiredTag: {},
isdefault: {},
}
// bakedInAliases is a default mapping of a single validation tag that
// defines a common or complex set of validation(s) to simplify
// adding validation to structs.
bakedInAliases = map[string]string{
"iscolor": "hexcolor|rgb|rgba|hsl|hsla",
"country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric",
"eu_country_code": "iso3166_1_alpha2_eu|iso3166_1_alpha3_eu|iso3166_1_alpha_numeric_eu",
}
// bakedInValidators is the default map of ValidationFunc
// you can add, remove or even replace items to suite your needs,
// or even disregard and use your own map if so desired.
bakedInValidators = map[string]Func{
"required": hasValue,
"required_if": requiredIf,
"required_unless": requiredUnless,
"skip_unless": skipUnless,
"required_with": requiredWith,
"required_with_all": requiredWithAll,
"required_without": requiredWithout,
"required_without_all": requiredWithoutAll,
"excluded_if": excludedIf,
"excluded_unless": excludedUnless,
"excluded_with": excludedWith,
"excluded_with_all": excludedWithAll,
"excluded_without": excludedWithout,
"excluded_without_all": excludedWithoutAll,
"isdefault": isDefault,
"len": hasLengthOf,
"min": hasMinOf,
"max": hasMaxOf,
"eq": isEq,
"eq_ignore_case": isEqIgnoreCase,
"ne": isNe,
"ne_ignore_case": isNeIgnoreCase,
"lt": isLt,
"lte": isLte,
"gt": isGt,
"gte": isGte,
"eqfield": isEqField,
"eqcsfield": isEqCrossStructField,
"necsfield": isNeCrossStructField,
"gtcsfield": isGtCrossStructField,
"gtecsfield": isGteCrossStructField,
"ltcsfield": isLtCrossStructField,
"ltecsfield": isLteCrossStructField,
"nefield": isNeField,
"gtefield": isGteField,
"gtfield": isGtField,
"ltefield": isLteField,
"ltfield": isLtField,
"fieldcontains": fieldContains,
"fieldexcludes": fieldExcludes,
"alpha": isAlpha,
"alphaspace": isAlphaSpace,
"alphanum": isAlphanum,
"alphanumspace": isAlphaNumericSpace,
"alphaunicode": isAlphaUnicode,
"alphanumunicode": isAlphanumUnicode,
"boolean": isBoolean,
"numeric": isNumeric,
"number": isNumber,
"hexadecimal": isHexadecimal,
"hexcolor": isHEXColor,
"rgb": isRGB,
"rgba": isRGBA,
"hsl": isHSL,
"hsla": isHSLA,
"e164": isE164,
"email": isEmail,
"url": isURL,
"http_url": isHttpURL,
"https_url": isHttpsURL,
"uri": isURI,
"urn_rfc2141": isUrnRFC2141, // RFC 2141
"file": isFile,
"filepath": isFilePath,
"base32": isBase32,
"base64": isBase64,
"base64url": isBase64URL,
"base64rawurl": isBase64RawURL,
"contains": contains,
"containsany": containsAny,
"containsrune": containsRune,
"excludes": excludes,
"excludesall": excludesAll,
"excludesrune": excludesRune,
"startswith": startsWith,
"endswith": endsWith,
"startsnotwith": startsNotWith,
"endsnotwith": endsNotWith,
"image": isImage,
"isbn": isISBN,
"isbn10": isISBN10,
"isbn13": isISBN13,
"issn": isISSN,
"eth_addr": isEthereumAddress,
"eth_addr_checksum": isEthereumAddressChecksum,
"btc_addr": isBitcoinAddress,
"btc_addr_bech32": isBitcoinBech32Address,
"uuid": isUUID,
"uuid3": isUUID3,
"uuid4": isUUID4,
"uuid5": isUUID5,
"uuid_rfc4122": isUUIDRFC4122,
"uuid3_rfc4122": isUUID3RFC4122,
"uuid4_rfc4122": isUUID4RFC4122,
"uuid5_rfc4122": isUUID5RFC4122,
"ulid": isULID,
"md4": isMD4,
"md5": isMD5,
"sha256": isSHA256,
"sha384": isSHA384,
"sha512": isSHA512,
"ripemd128": isRIPEMD128,
"ripemd160": isRIPEMD160,
"tiger128": isTIGER128,
"tiger160": isTIGER160,
"tiger192": isTIGER192,
"ascii": isASCII,
"printascii": isPrintableASCII,
"multibyte": hasMultiByteCharacter,
"datauri": isDataURI,
"latitude": isLatitude,
"longitude": isLongitude,
"ssn": isSSN,
"ipv4": isIPv4,
"ipv6": isIPv6,
"ip": isIP,
"cidrv4": isCIDRv4,
"cidrv6": isCIDRv6,
"cidr": isCIDR,
"tcp4_addr": isTCP4AddrResolvable,
"tcp6_addr": isTCP6AddrResolvable,
"tcp_addr": isTCPAddrResolvable,
"udp4_addr": isUDP4AddrResolvable,
"udp6_addr": isUDP6AddrResolvable,
"udp_addr": isUDPAddrResolvable,
"ip4_addr": isIP4AddrResolvable,
"ip6_addr": isIP6AddrResolvable,
"ip_addr": isIPAddrResolvable,
"unix_addr": isUnixAddrResolvable,
"uds_exists": isUnixDomainSocketExists,
"mac": isMAC,
"hostname": isHostnameRFC952, // RFC 952
"hostname_rfc1123": isHostnameRFC1123, // RFC 1123
"fqdn": isFQDN,
"unique": isUnique,
"oneof": isOneOf,
"oneofci": isOneOfCI,
"html": isHTML,
"html_encoded": isHTMLEncoded,
"url_encoded": isURLEncoded,
"dir": isDir,
"dirpath": isDirPath,
"json": isJSON,
"jwt": isJWT,
"hostname_port": isHostnamePort,
"port": isPort,
"lowercase": isLowercase,
"uppercase": isUppercase,
"datetime": isDatetime,
"timezone": isTimeZone,
"iso3166_1_alpha2": isIso3166Alpha2,
"iso3166_1_alpha2_eu": isIso3166Alpha2EU,
"iso3166_1_alpha3": isIso3166Alpha3,
"iso3166_1_alpha3_eu": isIso3166Alpha3EU,
"iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
"iso3166_1_alpha_numeric_eu": isIso3166AlphaNumericEU,
"iso3166_2": isIso31662,
"iso4217": isIso4217,
"iso4217_numeric": isIso4217Numeric,
"bcp47_language_tag": isBCP47LanguageTag,
"postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
"bic_iso_9362_2014": isIsoBic2014Format,
"bic": isIsoBic2022Format,
"semver": isSemverFormat,
"dns_rfc1035_label": isDnsRFC1035LabelFormat,
"credit_card": isCreditCard,
"cve": isCveFormat,
"luhn_checksum": hasLuhnChecksum,
"mongodb": isMongoDBObjectId,
"mongodb_connection_string": isMongoDBConnectionString,
"cron": isCron,
"spicedb": isSpiceDB,
"ein": isEIN,
"validateFn": isValidateFn,
}
)
var (
oneofValsCache = map[string][]string{}
oneofValsCacheRWLock = sync.RWMutex{}
)
func parseOneOfParam2(s string) []string {
oneofValsCacheRWLock.RLock()
vals, ok := oneofValsCache[s]
oneofValsCacheRWLock.RUnlock()
if !ok {
oneofValsCacheRWLock.Lock()
vals = splitParamsRegex().FindAllString(s, -1)
for i := 0; i < len(vals); i++ {
vals[i] = strings.ReplaceAll(vals[i], "'", "")
}
oneofValsCache[s] = vals
oneofValsCacheRWLock.Unlock()
}
return vals
}
func isURLEncoded(fl FieldLevel) bool {
return uRLEncodedRegex().MatchString(fl.Field().String())
}
func isHTMLEncoded(fl FieldLevel) bool {
return hTMLEncodedRegex().MatchString(fl.Field().String())
}
func isHTML(fl FieldLevel) bool {
return hTMLRegex().MatchString(fl.Field().String())
}
func isOneOf(fl FieldLevel) bool {
vals := parseOneOfParam2(fl.Param())
field := fl.Field()
var v string
switch field.Kind() {
case reflect.String:
v = field.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v = strconv.FormatInt(field.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v = strconv.FormatUint(field.Uint(), 10)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
for i := 0; i < len(vals); i++ {
if vals[i] == v {
return true
}
}
return false
}
// isOneOfCI is the validation function for validating if the current field's value is one of the provided string values (case insensitive).
func isOneOfCI(fl FieldLevel) bool {
vals := parseOneOfParam2(fl.Param())
field := fl.Field()
if field.Kind() != reflect.String {
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
v := field.String()
for _, val := range vals {
if strings.EqualFold(val, v) {
return true
}
}
return false
}
// isUnique is the validation function for validating if each array|slice|map value is unique
func isUnique(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
v := reflect.ValueOf(struct{}{})
switch field.Kind() {
case reflect.Slice, reflect.Array:
elem := field.Type().Elem()
if elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if param == "" {
m := reflect.MakeMap(reflect.MapOf(elem, v.Type()))
for i := 0; i < field.Len(); i++ {
m.SetMapIndex(reflect.Indirect(field.Index(i)), v)
}
return field.Len() == m.Len()
}
sf, ok := elem.FieldByName(param)
if !ok {
panic(fmt.Sprintf("Bad field name %s", param))
}
sfTyp := sf.Type
if sfTyp.Kind() == reflect.Ptr {
sfTyp = sfTyp.Elem()
}
m := reflect.MakeMap(reflect.MapOf(sfTyp, v.Type()))
var fieldlen int
for i := 0; i < field.Len(); i++ {
key := reflect.Indirect(reflect.Indirect(field.Index(i)).FieldByName(param))
if key.IsValid() {
fieldlen++
m.SetMapIndex(key, v)
}
}
return fieldlen == m.Len()
case reflect.Map:
var m reflect.Value
if field.Type().Elem().Kind() == reflect.Ptr {
m = reflect.MakeMap(reflect.MapOf(field.Type().Elem().Elem(), v.Type()))
} else {
m = reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
}
for _, k := range field.MapKeys() {
m.SetMapIndex(reflect.Indirect(field.MapIndex(k)), v)
}
return field.Len() == m.Len()
default:
if parent := fl.Parent(); parent.Kind() == reflect.Struct {
uniqueField := parent.FieldByName(param)
if uniqueField == reflect.ValueOf(nil) {
panic(fmt.Sprintf("Bad field name provided %s", param))
}
if uniqueField.Kind() != field.Kind() {
panic(fmt.Sprintf("Bad field type %s:%s", field.Type(), uniqueField.Type()))
}
return getValue(field) != getValue(uniqueField)
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
}
// isMAC is the validation function for validating if the field's value is a valid MAC address.
func isMAC(fl FieldLevel) bool {
_, err := net.ParseMAC(fl.Field().String())
return err == nil
}
// isCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
func isCIDRv4(fl FieldLevel) bool {
ip, net, err := net.ParseCIDR(fl.Field().String())
return err == nil && ip.To4() != nil && net.IP.Equal(ip)
}
// isCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
func isCIDRv6(fl FieldLevel) bool {
ip, _, err := net.ParseCIDR(fl.Field().String())
return err == nil && ip.To4() == nil
}
// isCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
func isCIDR(fl FieldLevel) bool {
_, _, err := net.ParseCIDR(fl.Field().String())
return err == nil
}
// isIPv4 is the validation function for validating if a value is a valid v4 IP address.
func isIPv4(fl FieldLevel) bool {
ip := net.ParseIP(fl.Field().String())
return ip != nil && ip.To4() != nil
}
// isIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
func isIPv6(fl FieldLevel) bool {
ip := net.ParseIP(fl.Field().String())
return ip != nil && ip.To4() == nil
}
// isIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
func isIP(fl FieldLevel) bool {
ip := net.ParseIP(fl.Field().String())
return ip != nil
}
// isSSN is the validation function for validating if the field's value is a valid SSN.
func isSSN(fl FieldLevel) bool {
field := fl.Field()
if field.Len() != 11 {
return false
}
return sSNRegex().MatchString(field.String())
}
// isLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
func isLongitude(fl FieldLevel) bool {
field := fl.Field()
var v string
switch field.Kind() {
case reflect.String:
v = field.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v = strconv.FormatInt(field.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v = strconv.FormatUint(field.Uint(), 10)
case reflect.Float32:
v = strconv.FormatFloat(field.Float(), 'f', -1, 32)
case reflect.Float64:
v = strconv.FormatFloat(field.Float(), 'f', -1, 64)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
return longitudeRegex().MatchString(v)
}
// isLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
func isLatitude(fl FieldLevel) bool {
field := fl.Field()
var v string
switch field.Kind() {
case reflect.String:
v = field.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v = strconv.FormatInt(field.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v = strconv.FormatUint(field.Uint(), 10)
case reflect.Float32:
v = strconv.FormatFloat(field.Float(), 'f', -1, 32)
case reflect.Float64:
v = strconv.FormatFloat(field.Float(), 'f', -1, 64)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
return latitudeRegex().MatchString(v)
}
// isDataURI is the validation function for validating if the field's value is a valid data URI.
func isDataURI(fl FieldLevel) bool {
uri := strings.SplitN(fl.Field().String(), ",", 2)
if len(uri) != 2 {
return false
}
if !dataURIRegex().MatchString(uri[0]) {
return false
}
return base64Regex().MatchString(uri[1])
}
// hasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
func hasMultiByteCharacter(fl FieldLevel) bool {
field := fl.Field()
if field.Len() == 0 {
return true
}
return multibyteRegex().MatchString(field.String())
}
// isPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
func isPrintableASCII(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
return printableASCIIRegex().MatchString(field.String())
}
return false
}
// isASCII is the validation function for validating if the field's value is a valid ASCII character.
func isASCII(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
return aSCIIRegex().MatchString(field.String())
}
return false
}
// isUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
func isUUID5(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID5Regex, fl)
}
// isUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
func isUUID4(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID4Regex, fl)
}
// isUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
func isUUID3(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID3Regex, fl)
}
// isUUID is the validation function for validating if the field's value is a valid UUID of any version.
func isUUID(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUIDRegex, fl)
}
// isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID.
func isUUID5RFC4122(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID5RFC4122Regex, fl)
}
// isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID.
func isUUID4RFC4122(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID4RFC4122Regex, fl)
}
// isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID.
func isUUID3RFC4122(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUID3RFC4122Regex, fl)
}
// isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version.
func isUUIDRFC4122(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uUIDRFC4122Regex, fl)
}
// isULID is the validation function for validating if the field's value is a valid ULID.
func isULID(fl FieldLevel) bool {
return fieldMatchesRegexByStringerValOrString(uLIDRegex, fl)
}
// isMD4 is the validation function for validating if the field's value is a valid MD4.
func isMD4(fl FieldLevel) bool {
return md4Regex().MatchString(fl.Field().String())
}
// isMD5 is the validation function for validating if the field's value is a valid MD5.
func isMD5(fl FieldLevel) bool {
return md5Regex().MatchString(fl.Field().String())
}
// isSHA256 is the validation function for validating if the field's value is a valid SHA256.
func isSHA256(fl FieldLevel) bool {
return sha256Regex().MatchString(fl.Field().String())
}
// isSHA384 is the validation function for validating if the field's value is a valid SHA384.
func isSHA384(fl FieldLevel) bool {
return sha384Regex().MatchString(fl.Field().String())
}
// isSHA512 is the validation function for validating if the field's value is a valid SHA512.
func isSHA512(fl FieldLevel) bool {
return sha512Regex().MatchString(fl.Field().String())
}
// isRIPEMD128 is the validation function for validating if the field's value is a valid PIPEMD128.
func isRIPEMD128(fl FieldLevel) bool {
return ripemd128Regex().MatchString(fl.Field().String())
}
// isRIPEMD160 is the validation function for validating if the field's value is a valid PIPEMD160.
func isRIPEMD160(fl FieldLevel) bool {
return ripemd160Regex().MatchString(fl.Field().String())
}
// isTIGER128 is the validation function for validating if the field's value is a valid TIGER128.
func isTIGER128(fl FieldLevel) bool {
return tiger128Regex().MatchString(fl.Field().String())
}
// isTIGER160 is the validation function for validating if the field's value is a valid TIGER160.
func isTIGER160(fl FieldLevel) bool {
return tiger160Regex().MatchString(fl.Field().String())
}
// isTIGER192 is the validation function for validating if the field's value is a valid isTIGER192.
func isTIGER192(fl FieldLevel) bool {
return tiger192Regex().MatchString(fl.Field().String())
}
// isISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
func isISBN(fl FieldLevel) bool {
return isISBN10(fl) || isISBN13(fl)
}
// isISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
func isISBN13(fl FieldLevel) bool {
s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 4), " ", "", 4)
if !iSBN13Regex().MatchString(s) {
return false
}
var checksum int32
var i int32
factor := []int32{1, 3}
for i = 0; i < 12; i++ {
checksum += factor[i%2] * int32(s[i]-'0')
}
return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0
}
// isISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
func isISBN10(fl FieldLevel) bool {
s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 3), " ", "", 3)
if !iSBN10Regex().MatchString(s) {
return false
}
var checksum int32
var i int32
for i = 0; i < 9; i++ {
checksum += (i + 1) * int32(s[i]-'0')
}
if s[9] == 'X' {
checksum += 10 * 10
} else {
checksum += 10 * int32(s[9]-'0')
}
return checksum%11 == 0
}
// isISSN is the validation function for validating if the field's value is a valid ISSN.
func isISSN(fl FieldLevel) bool {
s := fl.Field().String()
if !iSSNRegex().MatchString(s) {
return false
}
s = strings.ReplaceAll(s, "-", "")
pos := 8
checksum := 0
for i := 0; i < 7; i++ {
checksum += pos * int(s[i]-'0')
pos--
}
if s[7] == 'X' {
checksum += 10
} else {
checksum += int(s[7] - '0')
}
return checksum%11 == 0
}
// isEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address.
func isEthereumAddress(fl FieldLevel) bool {
address := fl.Field().String()
return ethAddressRegex().MatchString(address)
}
// isEthereumAddressChecksum is the validation function for validating if the field's value is a valid checksummed Ethereum address.
func isEthereumAddressChecksum(fl FieldLevel) bool {
address := fl.Field().String()
if !ethAddressRegex().MatchString(address) {
return false
}
// Checksum validation. Reference: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
address = address[2:] // Skip "0x" prefix.
h := sha3.NewLegacyKeccak256()
// hash.Hash's io.Writer implementation says it never returns an error. https://golang.org/pkg/hash/#Hash
_, _ = h.Write([]byte(strings.ToLower(address)))
hash := hex.EncodeToString(h.Sum(nil))
for i := 0; i < len(address); i++ {
if address[i] <= '9' { // Skip 0-9 digits: they don't have upper/lower-case.
continue
}
if hash[i] > '7' && address[i] >= 'a' || hash[i] <= '7' && address[i] <= 'F' {
return false
}
}
return true
}
// isBitcoinAddress is the validation function for validating if the field's value is a valid btc address
func isBitcoinAddress(fl FieldLevel) bool {
address := fl.Field().String()
if !btcAddressRegex().MatchString(address) {
return false
}
alphabet := []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
decode := [25]byte{}
for _, n := range []byte(address) {
d := bytes.IndexByte(alphabet, n)
for i := 24; i >= 0; i-- {
d += 58 * int(decode[i])
decode[i] = byte(d % 256)
d /= 256
}
}
h := sha256.New()
_, _ = h.Write(decode[:21])
d := h.Sum([]byte{})
h = sha256.New()
_, _ = h.Write(d)
validchecksum := [4]byte{}
computedchecksum := [4]byte{}
copy(computedchecksum[:], h.Sum(d[:0]))
copy(validchecksum[:], decode[21:])
return validchecksum == computedchecksum
}
// isBitcoinBech32Address is the validation function for validating if the field's value is a valid bech32 btc address
func isBitcoinBech32Address(fl FieldLevel) bool {
address := fl.Field().String()
if !btcLowerAddressRegexBech32().MatchString(address) && !btcUpperAddressRegexBech32().MatchString(address) {
return false
}
am := len(address) % 8
if am == 0 || am == 3 || am == 5 {
return false
}
address = strings.ToLower(address)
alphabet := "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
hr := []int{3, 3, 0, 2, 3} // the human readable part will always be bc
addr := address[3:]
dp := make([]int, 0, len(addr))
for _, c := range addr {
dp = append(dp, strings.IndexRune(alphabet, c))
}
ver := dp[0]
if ver < 0 || ver > 16 {
return false
}
if ver == 0 {
if len(address) != 42 && len(address) != 62 {
return false
}
}
values := append(hr, dp...)
GEN := []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
p := 1
for _, v := range values {
b := p >> 25
p = (p&0x1ffffff)<<5 ^ v
for i := 0; i < 5; i++ {
if (b>>uint(i))&1 == 1 {
p ^= GEN[i]
}
}
}
if p != 1 {
return false
}
b := uint(0)
acc := 0
mv := (1 << 5) - 1
var sw []int
for _, v := range dp[1 : len(dp)-6] {
acc = (acc << 5) | v
b += 5
for b >= 8 {
b -= 8
sw = append(sw, (acc>>b)&mv)
}
}
if len(sw) < 2 || len(sw) > 40 {
return false
}
return true
}
// excludesRune is the validation function for validating that the field's value does not contain the rune specified within the param.
func excludesRune(fl FieldLevel) bool {
return !containsRune(fl)
}
// excludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param.
func excludesAll(fl FieldLevel) bool {
return !containsAny(fl)
}
// excludes is the validation function for validating that the field's value does not contain the text specified within the param.
func excludes(fl FieldLevel) bool {
return !contains(fl)
}
// containsRune is the validation function for validating that the field's value contains the rune specified within the param.
func containsRune(fl FieldLevel) bool {
r, _ := utf8.DecodeRuneInString(fl.Param())
return strings.ContainsRune(fl.Field().String(), r)
}
// containsAny is the validation function for validating that the field's value contains any of the characters specified within the param.
func containsAny(fl FieldLevel) bool {
return strings.ContainsAny(fl.Field().String(), fl.Param())
}
// contains is the validation function for validating that the field's value contains the text specified within the param.
func contains(fl FieldLevel) bool {
return strings.Contains(fl.Field().String(), fl.Param())
}
// startsWith is the validation function for validating that the field's value starts with the text specified within the param.
func startsWith(fl FieldLevel) bool {
return strings.HasPrefix(fl.Field().String(), fl.Param())
}
// endsWith is the validation function for validating that the field's value ends with the text specified within the param.
func endsWith(fl FieldLevel) bool {
return strings.HasSuffix(fl.Field().String(), fl.Param())
}
// startsNotWith is the validation function for validating that the field's value does not start with the text specified within the param.
func startsNotWith(fl FieldLevel) bool {
return !startsWith(fl)
}
// endsNotWith is the validation function for validating that the field's value does not end with the text specified within the param.
func endsNotWith(fl FieldLevel) bool {
return !endsWith(fl)
}
// fieldContains is the validation function for validating if the current field's value contains the field specified by the param's value.
func fieldContains(fl FieldLevel) bool {
field := fl.Field()
currentField, _, ok := fl.GetStructFieldOK()
if !ok {
return false
}
return strings.Contains(field.String(), currentField.String())
}
// fieldExcludes is the validation function for validating if the current field's value excludes the field specified by the param's value.
func fieldExcludes(fl FieldLevel) bool {
field := fl.Field()
currentField, _, ok := fl.GetStructFieldOK()
if !ok {
return true
}
return !strings.Contains(field.String(), currentField.String())
}
// isNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
func isNeField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return true
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() != currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() != currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() != currentField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) != int64(currentField.Len())
case reflect.Bool:
return field.Bool() != currentField.Bool()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField).(time.Time)
fieldTime := getValue(field).(time.Time)
return !fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return true
}
}
// default reflect.String:
return field.String() != currentField.String()
}
// isNe is the validation function for validating that the field's value does not equal the provided param value.
func isNe(fl FieldLevel) bool {
return !isEq(fl)
}
// isNeIgnoreCase is the validation function for validating that the field's string value does not equal the
// provided param value. The comparison is case-insensitive
func isNeIgnoreCase(fl FieldLevel) bool {
return !isEqIgnoreCase(fl)
}
// isLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
func isLteCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, topKind, ok := fl.GetStructFieldOK()
if !ok || topKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() <= topField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() <= topField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() <= topField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) <= int64(topField.Len())
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := getValue(field.Convert(timeType)).(time.Time)
topTime := getValue(topField.Convert(timeType)).(time.Time)
return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
}
// default reflect.String:
return field.String() <= topField.String()
}
// isLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
func isLtCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, topKind, ok := fl.GetStructFieldOK()
if !ok || topKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() < topField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() < topField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() < topField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) < int64(topField.Len())
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := getValue(field.Convert(timeType)).(time.Time)
topTime := getValue(topField.Convert(timeType)).(time.Time)
return fieldTime.Before(topTime)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
}
// default reflect.String:
return field.String() < topField.String()
}
// isGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
func isGteCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, topKind, ok := fl.GetStructFieldOK()
if !ok || topKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() >= topField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() >= topField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() >= topField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) >= int64(topField.Len())
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := getValue(field.Convert(timeType)).(time.Time)
topTime := getValue(topField.Convert(timeType)).(time.Time)
return fieldTime.After(topTime) || fieldTime.Equal(topTime)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
}
// default reflect.String:
return field.String() >= topField.String()
}
// isGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
func isGtCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, topKind, ok := fl.GetStructFieldOK()
if !ok || topKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() > topField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() > topField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() > topField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) > int64(topField.Len())
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
fieldTime := getValue(field.Convert(timeType)).(time.Time)
topTime := getValue(topField.Convert(timeType)).(time.Time)
return fieldTime.After(topTime)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
}
// default reflect.String:
return field.String() > topField.String()
}
// isNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
func isNeCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return true
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return topField.Int() != field.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return topField.Uint() != field.Uint()
case reflect.Float32, reflect.Float64:
return topField.Float() != field.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(topField.Len()) != int64(field.Len())
case reflect.Bool:
return topField.Bool() != field.Bool()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
t := getValue(field.Convert(timeType)).(time.Time)
fieldTime := getValue(topField.Convert(timeType)).(time.Time)
return !fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return true
}
}
// default reflect.String:
return topField.String() != field.String()
}
// isEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
func isEqCrossStructField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
topField, topKind, ok := fl.GetStructFieldOK()
if !ok || topKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return topField.Int() == field.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return topField.Uint() == field.Uint()
case reflect.Float32, reflect.Float64:
return topField.Float() == field.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(topField.Len()) == int64(field.Len())
case reflect.Bool:
return topField.Bool() == field.Bool()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) {
t := getValue(field.Convert(timeType)).(time.Time)
fieldTime := getValue(topField.Convert(timeType)).(time.Time)
return fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
}
}
// default reflect.String:
return topField.String() == field.String()
}
// isEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
func isEqField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() == currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() == currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() == currentField.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(field.Len()) == int64(currentField.Len())
case reflect.Bool:
return field.Bool() == currentField.Bool()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField.Convert(timeType)).(time.Time)
fieldTime := getValue(field.Convert(timeType)).(time.Time)
return fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String:
return field.String() == currentField.String()
}
// isEq is the validation function for validating if the current field's value is equal to the param's value.
func isEq(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
return field.String() == param
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() == p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() == p
case reflect.Float32:
p := asFloat32(param)
return field.Float() == p
case reflect.Float64:
p := asFloat64(param)
return field.Float() == p
case reflect.Bool:
p := asBool(param)
return field.Bool() == p
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isEqIgnoreCase is the validation function for validating if the current field's string value is
// equal to the param's value.
// The comparison is case-insensitive.
func isEqIgnoreCase(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
return strings.EqualFold(field.String(), param)
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isPostcodeByIso3166Alpha2 validates by value which is country code in iso 3166 alpha 2
// example: `postcode_iso3166_alpha2=US`
func isPostcodeByIso3166Alpha2(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
postcodeRegexInit.Do(initPostcodes)
reg, found := postCodeRegexDict[param]
if !found {
return false
}
return reg.MatchString(field.String())
}
// isPostcodeByIso3166Alpha2Field validates by field which represents for a value of country code in iso 3166 alpha 2
// example: `postcode_iso3166_alpha2_field=CountryCode`
func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
field := fl.Field()
params := parseOneOfParam2(fl.Param())
if len(params) != 1 {
return false
}
currentField, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), params[0])
if !found {
return false
}
if kind != reflect.String {
panic(fmt.Sprintf("Bad field type %s", currentField.Type()))
}
postcodeRegexInit.Do(initPostcodes)
reg, found := postCodeRegexDict[currentField.String()]
if !found {
return false
}
return reg.MatchString(field.String())
}
// isBase32 is the validation function for validating if the current field's value is a valid base 32.
func isBase32(fl FieldLevel) bool {
return base32Regex().MatchString(fl.Field().String())
}
// isBase64 is the validation function for validating if the current field's value is a valid base 64.
func isBase64(fl FieldLevel) bool {
return base64Regex().MatchString(fl.Field().String())
}
// isBase64URL is the validation function for validating if the current field's value is a valid base64 URL safe string.
func isBase64URL(fl FieldLevel) bool {
return base64URLRegex().MatchString(fl.Field().String())
}
// isBase64RawURL is the validation function for validating if the current field's value is a valid base64 URL safe string without '=' padding.
func isBase64RawURL(fl FieldLevel) bool {
return base64RawURLRegex().MatchString(fl.Field().String())
}
// isURI is the validation function for validating if the current field's value is a valid URI.
func isURI(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
s := field.String()
// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
// emulate browser and strip the '#' suffix prior to validation. see issue-#237
if i := strings.Index(s, "#"); i > -1 {
s = s[:i]
}
if len(s) == 0 {
return false
}
_, err := url.ParseRequestURI(s)
return err == nil
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isURL is the validation function for validating if the current field's value is a valid URL.
func isURL(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
s := strings.ToLower(field.String())
if len(s) == 0 {
return false
}
url, err := url.Parse(s)
if err != nil || url.Scheme == "" {
return false
}
isFileScheme := url.Scheme == "file"
if (isFileScheme && (len(url.Path) == 0 || url.Path == "/")) || (!isFileScheme && len(url.Host) == 0 && len(url.Fragment) == 0 && len(url.Opaque) == 0) {
return false
}
return true
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isHttpURL is the validation function for validating if the current field's value is a valid HTTP(s) URL.
func isHttpURL(fl FieldLevel) bool {
if !isURL(fl) {
return false
}
field := fl.Field()
switch field.Kind() {
case reflect.String:
s := strings.ToLower(field.String())
url, err := url.Parse(s)
if err != nil || url.Host == "" {
return false
}
return url.Scheme == "http" || url.Scheme == "https"
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isHttpsURL is the validation function for validating if the current field's value is a valid HTTPS-only URL.
func isHttpsURL(fl FieldLevel) bool {
if !isURL(fl) {
return false
}
field := fl.Field()
switch field.Kind() {
case reflect.String:
s := strings.ToLower(field.String())
url, err := url.Parse(s)
if err != nil || url.Host == "" {
return false
}
return url.Scheme == "https"
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isUrnRFC2141 is the validation function for validating if the current field's value is a valid URN as per RFC 2141.
func isUrnRFC2141(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
str := field.String()
_, match := urn.Parse([]byte(str))
return match
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isFile is the validation function for validating if the current field's value is a valid existing file path.
func isFile(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
fileInfo, err := os.Stat(field.String())
if err != nil {
return false
}
return !fileInfo.IsDir()
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isImage is the validation function for validating if the current field's value contains the path to a valid image file
func isImage(fl FieldLevel) bool {
mimetypes := map[string]bool{
"image/bmp": true,
"image/cis-cod": true,
"image/gif": true,
"image/ief": true,
"image/jpeg": true,
"image/jp2": true,
"image/jpx": true,
"image/jpm": true,
"image/pipeg": true,
"image/png": true,
"image/svg+xml": true,
"image/tiff": true,
"image/webp": true,
"image/x-cmu-raster": true,
"image/x-cmx": true,
"image/x-icon": true,
"image/x-portable-anymap": true,
"image/x-portable-bitmap": true,
"image/x-portable-graymap": true,
"image/x-portable-pixmap": true,
"image/x-rgb": true,
"image/x-xbitmap": true,
"image/x-xpixmap": true,
"image/x-xwindowdump": true,
}
field := fl.Field()
switch field.Kind() {
case reflect.String:
filePath := field.String()
fileInfo, err := os.Stat(filePath)
if err != nil {
return false
}
if fileInfo.IsDir() {
return false
}
file, err := os.Open(filePath)
if err != nil {
return false
}
defer func() {
_ = file.Close()
}()
mime, err := mimetype.DetectReader(file)
if err != nil {
return false
}
if _, ok := mimetypes[mime.String()]; ok {
return true
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isFilePath is the validation function for validating if the current field's value is a valid file path.
func isFilePath(fl FieldLevel) bool {
var exists bool
var err error
field := fl.Field()
// Not valid if it is a directory.
if isDir(fl) {
return false
}
// If it exists, it obviously is valid.
// This is done first to avoid code duplication and unnecessary additional logic.
if exists = isFile(fl); exists {
return true
}
// It does not exist but may still be a valid filepath.
switch field.Kind() {
case reflect.String:
// Every OS allows for whitespace, but none
// let you use a file with no filename (to my knowledge).
// Unless you're dealing with raw inodes, but I digress.
if strings.TrimSpace(field.String()) == "" {
return false
}
// We make sure it isn't a directory.
if strings.HasSuffix(field.String(), string(os.PathSeparator)) {
return false
}
if _, err = os.Stat(field.String()); err != nil {
switch t := err.(type) {
case *fs.PathError:
if t.Err == syscall.EINVAL {
// It's definitely an invalid character in the filepath.
return false
}
// It could be a permission error, a does-not-exist error, etc.
// Out-of-scope for this validation, though.
return true
default:
// Something went *seriously* wrong.
/*
Per https://pkg.go.dev/os#Stat:
"If there is an error, it will be of type *PathError."
*/
panic(err)
}
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isE164 is the validation function for validating if the current field's value is a valid e.164 formatted phone number.
func isE164(fl FieldLevel) bool {
return e164Regex().MatchString(fl.Field().String())
}
// isEmail is the validation function for validating if the current field's value is a valid email address.
func isEmail(fl FieldLevel) bool {
_, err := mail.ParseAddress(fl.Field().String())
if err != nil {
return false
}
return emailRegex().MatchString(fl.Field().String())
}
// isHSLA is the validation function for validating if the current field's value is a valid HSLA color.
func isHSLA(fl FieldLevel) bool {
return hslaRegex().MatchString(fl.Field().String())
}
// isHSL is the validation function for validating if the current field's value is a valid HSL color.
func isHSL(fl FieldLevel) bool {
return hslRegex().MatchString(fl.Field().String())
}
// isRGBA is the validation function for validating if the current field's value is a valid RGBA color.
func isRGBA(fl FieldLevel) bool {
return rgbaRegex().MatchString(fl.Field().String())
}
// isRGB is the validation function for validating if the current field's value is a valid RGB color.
func isRGB(fl FieldLevel) bool {
return rgbRegex().MatchString(fl.Field().String())
}
// isHEXColor is the validation function for validating if the current field's value is a valid HEX color.
func isHEXColor(fl FieldLevel) bool {
return hexColorRegex().MatchString(fl.Field().String())
}
// isHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
func isHexadecimal(fl FieldLevel) bool {
return hexadecimalRegex().MatchString(fl.Field().String())
}
// isNumber is the validation function for validating if the current field's value is a valid number.
func isNumber(fl FieldLevel) bool {
switch fl.Field().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
return true
default:
return numberRegex().MatchString(fl.Field().String())
}
}
// isNumeric is the validation function for validating if the current field's value is a valid numeric value.
func isNumeric(fl FieldLevel) bool {
switch fl.Field().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
return true
default:
return numericRegex().MatchString(fl.Field().String())
}
}
// isAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
func isAlphanum(fl FieldLevel) bool {
return alphaNumericRegex().MatchString(fl.Field().String())
}
// isAlpha is the validation function for validating if the current field's value is a valid alpha value.
func isAlpha(fl FieldLevel) bool {
return alphaRegex().MatchString(fl.Field().String())
}
// isAlphanumUnicode is the validation function for validating if the current field's value is a valid alphanumeric unicode value.
func isAlphanumUnicode(fl FieldLevel) bool {
return alphaUnicodeNumericRegex().MatchString(fl.Field().String())
}
// isAlphaSpace is the validation function for validating if the current field's value is a valid alpha value with spaces.
func isAlphaSpace(fl FieldLevel) bool {
return alphaSpaceRegex().MatchString(fl.Field().String())
}
// isAlphaNumericSpace is the validation function for validating if the current field's value is a valid alphanumeric value with spaces.
func isAlphaNumericSpace(fl FieldLevel) bool {
return alphanNumericSpaceRegex().MatchString(fl.Field().String())
}
// isAlphaUnicode is the validation function for validating if the current field's value is a valid alpha unicode value.
func isAlphaUnicode(fl FieldLevel) bool {
return alphaUnicodeRegex().MatchString(fl.Field().String())
}
// isBoolean is the validation function for validating if the current field's value is a valid boolean value or can be safely converted to a boolean value.
func isBoolean(fl FieldLevel) bool {
switch fl.Field().Kind() {
case reflect.Bool:
return true
default:
_, err := strconv.ParseBool(fl.Field().String())
return err == nil
}
}
// isDefault is the opposite of required aka hasValue
func isDefault(fl FieldLevel) bool {
return !hasValue(fl)
}
// hasValue is the validation function for validating if the current field's value is not the default static value.
func hasValue(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return !field.IsNil()
default:
if fl.(*validate).fldIsPointer && getValue(field) != nil {
return true
}
return field.IsValid() && !field.IsZero()
}
}
// hasNotZeroValue is the validation function for validating if the current field's value is not the zero value for its type.
func hasNotZeroValue(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.Slice, reflect.Map:
// For slices and maps, consider them "not zero" only if they're both non-nil AND have elements
return !field.IsNil() && field.Len() > 0
case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return !field.IsNil()
default:
if fl.(*validate).fldIsPointer && getValue(field) != nil {
return !field.IsZero()
}
return field.IsValid() && !field.IsZero()
}
}
// requireCheckFieldKind is a func for check field kind
func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue bool) bool {
field := fl.Field()
kind := field.Kind()
var nullable, found bool
if len(param) > 0 {
field, kind, nullable, found = fl.GetStructFieldOKAdvanced2(fl.Parent(), param)
if !found {
return defaultNotFoundValue
}
}
switch kind {
case reflect.Invalid:
return defaultNotFoundValue
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return field.IsNil()
default:
if nullable && getValue(field) != nil {
return false
}
return field.IsValid() && field.IsZero()
}
}
// requireCheckFieldValue is a func for check field value
func requireCheckFieldValue(
fl FieldLevel, param string, value string, defaultNotFoundValue bool,
) bool {
field, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), param)
if !found {
return defaultNotFoundValue
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() == asInt(value)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() == asUint(value)
case reflect.Float32:
return field.Float() == asFloat32(value)
case reflect.Float64:
return field.Float() == asFloat64(value)
case reflect.Slice, reflect.Map:
if value == "nil" {
return field.IsNil()
}
return int64(field.Len()) == asInt(value)
case reflect.Array:
// Arrays can't be nil, so only compare lengths
return int64(field.Len()) == asInt(value)
case reflect.Bool:
return field.Bool() == (value == "true")
case reflect.Ptr:
if field.IsNil() {
return value == "nil"
}
// Handle non-nil pointers
return requireCheckFieldValue(fl, param, value, defaultNotFoundValue)
}
// default reflect.String:
return field.String() == value
}
// requiredIf is the validation function
// The field under validation must be present and not empty only if all the other specified fields are equal to the value following with the specified field.
func requiredIf(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
if len(params)%2 != 0 {
panic(fmt.Sprintf("Bad param number for required_if %s", fl.FieldName()))
}
seen := make(map[string]struct{})
for i := 0; i < len(params); i += 2 {
if _, ok := seen[params[i]]; ok {
panic(fmt.Sprintf("Duplicate param %s for required_if %s", params[i], fl.FieldName()))
}
seen[params[i]] = struct{}{}
}
for i := 0; i < len(params); i += 2 {
if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
return true
}
}
return hasValue(fl)
}
// excludedIf is the validation function
// The field under validation must not be present or is empty only if all the other specified fields are equal to the value following with the specified field.
func excludedIf(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
if len(params)%2 != 0 {
panic(fmt.Sprintf("Bad param number for excluded_if %s", fl.FieldName()))
}
for i := 0; i < len(params); i += 2 {
if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
return true
}
}
return !hasValue(fl)
}
// requiredUnless is the validation function
// The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.
func requiredUnless(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
if len(params)%2 != 0 {
panic(fmt.Sprintf("Bad param number for required_unless %s", fl.FieldName()))
}
for i := 0; i < len(params); i += 2 {
if requireCheckFieldValue(fl, params[i], params[i+1], false) {
return true
}
}
return hasValue(fl)
}
// skipUnless is the validation function
// The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.
func skipUnless(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
if len(params)%2 != 0 {
panic(fmt.Sprintf("Bad param number for skip_unless %s", fl.FieldName()))
}
for i := 0; i < len(params); i += 2 {
if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
return true
}
}
return hasValue(fl)
}
// excludedUnless is the validation function
// The field under validation must not be present or is empty unless all the other specified fields are equal to the value following with the specified field.
func excludedUnless(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
if len(params)%2 != 0 {
panic(fmt.Sprintf("Bad param number for excluded_unless %s", fl.FieldName()))
}
for i := 0; i < len(params); i += 2 {
if requireCheckFieldValue(fl, params[i], params[i+1], false) {
return true
}
}
return !hasValue(fl)
}
// excludedWith is the validation function
// The field under validation must not be present or is empty if any of the other specified fields are present.
func excludedWith(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if !requireCheckFieldKind(fl, param, true) {
return !hasValue(fl)
}
}
return true
}
// requiredWith is the validation function
// The field under validation must be present and not empty only if any of the other specified fields are present.
func requiredWith(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if !requireCheckFieldKind(fl, param, true) {
return hasValue(fl)
}
}
return true
}
// excludedWithAll is the validation function
// The field under validation must not be present or is empty if all of the other specified fields are present.
func excludedWithAll(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if requireCheckFieldKind(fl, param, true) {
return true
}
}
return !hasValue(fl)
}
// requiredWithAll is the validation function
// The field under validation must be present and not empty only if all of the other specified fields are present.
func requiredWithAll(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if requireCheckFieldKind(fl, param, true) {
return true
}
}
return hasValue(fl)
}
// excludedWithout is the validation function
// The field under validation must not be present or is empty when any of the other specified fields are not present.
func excludedWithout(fl FieldLevel) bool {
if requireCheckFieldKind(fl, strings.TrimSpace(fl.Param()), true) {
return !hasValue(fl)
}
return true
}
// requiredWithout is the validation function
// The field under validation must be present and not empty only when any of the other specified fields are not present.
func requiredWithout(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if requireCheckFieldKind(fl, param, true) {
return hasValue(fl)
}
}
return true
}
// excludedWithoutAll is the validation function
// The field under validation must not be present or is empty when all of the other specified fields are not present.
func excludedWithoutAll(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if !requireCheckFieldKind(fl, param, true) {
return true
}
}
return !hasValue(fl)
}
// requiredWithoutAll is the validation function
// The field under validation must be present and not empty only when all of the other specified fields are not present.
func requiredWithoutAll(fl FieldLevel) bool {
params := parseOneOfParam2(fl.Param())
for _, param := range params {
if !requireCheckFieldKind(fl, param, true) {
return true
}
}
return hasValue(fl)
}
// isGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
func isGteField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() >= currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() >= currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() >= currentField.Float()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField.Convert(timeType)).(time.Time)
fieldTime := getValue(field.Convert(timeType)).(time.Time)
return fieldTime.After(t) || fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
return len(field.String()) >= len(currentField.String())
}
// isGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
func isGtField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() > currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() > currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() > currentField.Float()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField.Convert(timeType)).(time.Time)
fieldTime := getValue(field.Convert(timeType)).(time.Time)
return fieldTime.After(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
return len(field.String()) > len(currentField.String())
}
// isGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
func isGte(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) >= p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) >= p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() >= p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() >= p
case reflect.Float32:
p := asFloat32(param)
return field.Float() >= p
case reflect.Float64:
p := asFloat64(param)
return field.Float() >= p
case reflect.Struct:
if field.Type().ConvertibleTo(timeType) {
now := time.Now().UTC()
t := getValue(field.Convert(timeType)).(time.Time)
return t.After(now) || t.Equal(now)
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isGt is the validation function for validating if the current field's value is greater than the param's value.
func isGt(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) > p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) > p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() > p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() > p
case reflect.Float32:
p := asFloat32(param)
return field.Float() > p
case reflect.Float64:
p := asFloat64(param)
return field.Float() > p
case reflect.Struct:
if field.Type().ConvertibleTo(timeType) {
return getValue(field.Convert(timeType)).(time.Time).After(time.Now().UTC())
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// hasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
func hasLengthOf(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) == p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() == p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() == p
case reflect.Float32:
p := asFloat32(param)
return field.Float() == p
case reflect.Float64:
p := asFloat64(param)
return field.Float() == p
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// hasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
func hasMinOf(fl FieldLevel) bool {
return isGte(fl)
}
// isLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
func isLteField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() <= currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() <= currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() <= currentField.Float()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField.Convert(timeType)).(time.Time)
fieldTime := getValue(field.Convert(timeType)).(time.Time)
return fieldTime.Before(t) || fieldTime.Equal(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
return len(field.String()) <= len(currentField.String())
}
// isLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
func isLtField(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
currentField, currentKind, ok := fl.GetStructFieldOK()
if !ok || currentKind != kind {
return false
}
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() < currentField.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return field.Uint() < currentField.Uint()
case reflect.Float32, reflect.Float64:
return field.Float() < currentField.Float()
case reflect.Struct:
fieldType := field.Type()
if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) {
t := getValue(currentField.Convert(timeType)).(time.Time)
fieldTime := getValue(field.Convert(timeType)).(time.Time)
return fieldTime.Before(t)
}
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
}
}
// default reflect.String
return len(field.String()) < len(currentField.String())
}
// isLte is the validation function for validating if the current field's value is less than or equal to the param's value.
func isLte(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) <= p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) <= p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() <= p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() <= p
case reflect.Float32:
p := asFloat32(param)
return field.Float() <= p
case reflect.Float64:
p := asFloat64(param)
return field.Float() <= p
case reflect.Struct:
if field.Type().ConvertibleTo(timeType) {
now := time.Now().UTC()
t := getValue(field.Convert(timeType)).(time.Time)
return t.Before(now) || t.Equal(now)
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isLt is the validation function for validating if the current field's value is less than the param's value.
func isLt(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
switch field.Kind() {
case reflect.String:
p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) < p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(field.Len()) < p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asIntFromType(field.Type(), param)
return field.Int() < p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return field.Uint() < p
case reflect.Float32:
p := asFloat32(param)
return field.Float() < p
case reflect.Float64:
p := asFloat64(param)
return field.Float() < p
case reflect.Struct:
if field.Type().ConvertibleTo(timeType) {
return getValue(field.Convert(timeType)).(time.Time).Before(time.Now().UTC())
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// hasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
func hasMaxOf(fl FieldLevel) bool {
return isLte(fl)
}
// isTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
func isTCP4AddrResolvable(fl FieldLevel) bool {
if !isIP4Addr(fl) {
return false
}
_, err := net.ResolveTCPAddr("tcp4", fl.Field().String())
return err == nil
}
// isTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
func isTCP6AddrResolvable(fl FieldLevel) bool {
if !isIP6Addr(fl) {
return false
}
_, err := net.ResolveTCPAddr("tcp6", fl.Field().String())
return err == nil
}
// isTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
func isTCPAddrResolvable(fl FieldLevel) bool {
if !isIP4Addr(fl) && !isIP6Addr(fl) {
return false
}
_, err := net.ResolveTCPAddr("tcp", fl.Field().String())
return err == nil
}
// isUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
func isUDP4AddrResolvable(fl FieldLevel) bool {
if !isIP4Addr(fl) {
return false
}
_, err := net.ResolveUDPAddr("udp4", fl.Field().String())
return err == nil
}
// isUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
func isUDP6AddrResolvable(fl FieldLevel) bool {
if !isIP6Addr(fl) {
return false
}
_, err := net.ResolveUDPAddr("udp6", fl.Field().String())
return err == nil
}
// isUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
func isUDPAddrResolvable(fl FieldLevel) bool {
if !isIP4Addr(fl) && !isIP6Addr(fl) {
return false
}
_, err := net.ResolveUDPAddr("udp", fl.Field().String())
return err == nil
}
// isIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
func isIP4AddrResolvable(fl FieldLevel) bool {
if !isIPv4(fl) {
return false
}
_, err := net.ResolveIPAddr("ip4", fl.Field().String())
return err == nil
}
// isIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
func isIP6AddrResolvable(fl FieldLevel) bool {
if !isIPv6(fl) {
return false
}
_, err := net.ResolveIPAddr("ip6", fl.Field().String())
return err == nil
}
// isIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
func isIPAddrResolvable(fl FieldLevel) bool {
if !isIP(fl) {
return false
}
_, err := net.ResolveIPAddr("ip", fl.Field().String())
return err == nil
}
// isUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
func isUnixAddrResolvable(fl FieldLevel) bool {
_, err := net.ResolveUnixAddr("unix", fl.Field().String())
return err == nil
}
// isUnixDomainSocketExists is the validation function for validating if the field's value is an existing Unix domain socket.
// It handles both filesystem-based sockets and Linux abstract sockets.
// It always returns false for Windows.
func isUnixDomainSocketExists(fl FieldLevel) bool {
if runtime.GOOS == "windows" {
return false
}
sockpath := fl.Field().String()
if sockpath == "" {
return false
}
// On Linux, check for abstract sockets (prefixed with @)
if runtime.GOOS == "linux" && strings.HasPrefix(sockpath, "@") {
return isAbstractSocketExists(sockpath)
}
// For filesystem-based sockets, check if the path exists and is a socket
stats, err := os.Stat(sockpath)
if err != nil {
return false
}
return stats.Mode().Type() == fs.ModeSocket
}
// isAbstractSocketExists checks if a Linux abstract socket exists by reading /proc/net/unix.
// Abstract sockets are identified by an @ prefix in human-readable form.
func isAbstractSocketExists(sockpath string) bool {
file, err := os.Open("/proc/net/unix")
if err != nil {
return false
}
defer func() {
_ = file.Close()
}()
scanner := bufio.NewScanner(file)
// Skip the header line
if !scanner.Scan() {
return false
}
// Abstract sockets in /proc/net/unix are represented with @ prefix
// The socket path is the last field in each line
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
// The path is the last field (8th field typically)
if len(fields) >= 8 {
path := fields[len(fields)-1]
if path == sockpath {
return true
}
}
}
return false
}
func isIP4Addr(fl FieldLevel) bool {
val := fl.Field().String()
if idx := strings.LastIndex(val, ":"); idx != -1 {
val = val[0:idx]
}
ip := net.ParseIP(val)
return ip != nil && ip.To4() != nil
}
func isIP6Addr(fl FieldLevel) bool {
val := fl.Field().String()
if idx := strings.LastIndex(val, ":"); idx != -1 {
if idx != 0 && val[idx-1:idx] == "]" {
val = val[1 : idx-1]
}
}
ip := net.ParseIP(val)
return ip != nil && ip.To4() == nil
}
func isHostnameRFC952(fl FieldLevel) bool {
return hostnameRegexRFC952().MatchString(fl.Field().String())
}
func isHostnameRFC1123(fl FieldLevel) bool {
return hostnameRegexRFC1123().MatchString(fl.Field().String())
}
func isFQDN(fl FieldLevel) bool {
val := fl.Field().String()
if val == "" {
return false
}
return fqdnRegexRFC1123().MatchString(val)
}
// isDir is the validation function for validating if the current field's value is a valid existing directory.
func isDir(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
fileInfo, err := os.Stat(field.String())
if err != nil {
return false
}
return fileInfo.IsDir()
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isDirPath is the validation function for validating if the current field's value is a valid directory.
func isDirPath(fl FieldLevel) bool {
var exists bool
var err error
field := fl.Field()
// If it exists, it obviously is valid.
// This is done first to avoid code duplication and unnecessary additional logic.
if exists = isDir(fl); exists {
return true
}
// It does not exist but may still be a valid path.
switch field.Kind() {
case reflect.String:
// Every OS allows for whitespace, but none
// let you use a dir with no name (to my knowledge).
// Unless you're dealing with raw inodes, but I digress.
if strings.TrimSpace(field.String()) == "" {
return false
}
if _, err = os.Stat(field.String()); err != nil {
switch t := err.(type) {
case *fs.PathError:
if t.Err == syscall.EINVAL {
// It's definitely an invalid character in the path.
return false
}
// It could be a permission error, a does-not-exist error, etc.
// Out-of-scope for this validation, though.
// Lastly, we make sure it is a directory.
if strings.HasSuffix(field.String(), string(os.PathSeparator)) {
return true
} else {
return false
}
default:
// Something went *seriously* wrong.
/*
Per https://pkg.go.dev/os#Stat:
"If there is an error, it will be of type *PathError."
*/
panic(err)
}
}
// We repeat the check here to make sure it is an explicit directory in case the above os.Stat didn't trigger an error.
if strings.HasSuffix(field.String(), string(os.PathSeparator)) {
return true
} else {
return false
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isJSON is the validation function for validating if the current field's value is a valid json string.
func isJSON(fl FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
val := field.String()
return json.Valid([]byte(val))
case reflect.Slice:
fieldType := field.Type()
if fieldType.ConvertibleTo(byteSliceType) {
b := getValue(field.Convert(byteSliceType)).([]byte)
return json.Valid(b)
}
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isJWT is the validation function for validating if the current field's value is a valid JWT string.
func isJWT(fl FieldLevel) bool {
return jWTRegex().MatchString(fl.Field().String())
}
// isHostnamePort validates a : combination for fields typically used for socket address.
func isHostnamePort(fl FieldLevel) bool {
val := fl.Field().String()
host, port, err := net.SplitHostPort(val)
if err != nil {
return false
}
// Port must be a iny <= 65535.
if portNum, err := strconv.ParseInt(
port, 10, 32,
); err != nil || portNum > 65535 || portNum < 1 {
return false
}
// If host is specified, it should match a DNS name
if host != "" {
return hostnameRegexRFC1123().MatchString(host)
}
return true
}
// IsPort validates if the current field's value represents a valid port
func isPort(fl FieldLevel) bool {
val := fl.Field().Uint()
return val >= 1 && val <= 65535
}
// isLowercase is the validation function for validating if the current field's value is a lowercase string.
func isLowercase(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
if field.String() == "" {
return false
}
return field.String() == strings.ToLower(field.String())
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isUppercase is the validation function for validating if the current field's value is an uppercase string.
func isUppercase(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
if field.String() == "" {
return false
}
return field.String() == strings.ToUpper(field.String())
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isDatetime is the validation function for validating if the current field's value is a valid datetime string.
func isDatetime(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
if field.Kind() == reflect.String {
_, err := time.Parse(param, field.String())
return err == nil
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isTimeZone is the validation function for validating if the current field's value is a valid time zone string.
func isTimeZone(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
// empty value is converted to UTC by time.LoadLocation but disallow it as it is not a valid time zone name
if field.String() == "" {
return false
}
// Local value is converted to the current system time zone by time.LoadLocation but disallow it as it is not a valid time zone name
if strings.ToLower(field.String()) == "local" {
return false
}
_, err := time.LoadLocation(field.String())
return err == nil
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 country code.
func isIso3166Alpha2(fl FieldLevel) bool {
_, ok := iso3166_1_alpha2[fl.Field().String()]
return ok
}
// isIso3166Alpha2EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 European Union country code.
func isIso3166Alpha2EU(fl FieldLevel) bool {
_, ok := iso3166_1_alpha2_eu[fl.Field().String()]
return ok
}
// isIso3166Alpha3 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 country code.
func isIso3166Alpha3(fl FieldLevel) bool {
_, ok := iso3166_1_alpha3[fl.Field().String()]
return ok
}
// isIso3166Alpha3EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 European Union country code.
func isIso3166Alpha3EU(fl FieldLevel) bool {
_, ok := iso3166_1_alpha3_eu[fl.Field().String()]
return ok
}
// isIso3166AlphaNumeric is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric country code.
func isIso3166AlphaNumeric(fl FieldLevel) bool {
field := fl.Field()
var code int
switch field.Kind() {
case reflect.String:
i, err := strconv.Atoi(field.String())
if err != nil {
return false
}
code = i % 1000
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
code = int(field.Int() % 1000)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
code = int(field.Uint() % 1000)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
_, ok := iso3166_1_alpha_numeric[code]
return ok
}
// isIso3166AlphaNumericEU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric European Union country code.
func isIso3166AlphaNumericEU(fl FieldLevel) bool {
field := fl.Field()
var code int
switch field.Kind() {
case reflect.String:
i, err := strconv.Atoi(field.String())
if err != nil {
return false
}
code = i % 1000
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
code = int(field.Int() % 1000)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
code = int(field.Uint() % 1000)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
_, ok := iso3166_1_alpha_numeric_eu[code]
return ok
}
// isIso31662 is the validation function for validating if the current field's value is a valid iso3166-2 code.
func isIso31662(fl FieldLevel) bool {
_, ok := iso3166_2[fl.Field().String()]
return ok
}
// isIso4217 is the validation function for validating if the current field's value is a valid iso4217 currency code.
func isIso4217(fl FieldLevel) bool {
_, ok := iso4217[fl.Field().String()]
return ok
}
// isIso4217Numeric is the validation function for validating if the current field's value is a valid iso4217 numeric currency code.
func isIso4217Numeric(fl FieldLevel) bool {
field := fl.Field()
var code int
switch field.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
code = int(field.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
code = int(field.Uint())
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
_, ok := iso4217_numeric[code]
return ok
}
// isBCP47LanguageTag is the validation function for validating if the current field's value is a valid BCP 47 language tag, as parsed by language.Parse
func isBCP47LanguageTag(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
_, err := language.Parse(field.String())
return err == nil
}
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
// isIsoBic2014Format is the validation function for validating if the current field's value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362 2014
func isIsoBic2014Format(fl FieldLevel) bool {
bicString := fl.Field().String()
return bic2014Regex().MatchString(bicString)
}
// isIsoBic2022Format is the validation function for validating if the current field's value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362 2022
func isIsoBic2022Format(fl FieldLevel) bool {
bicString := fl.Field().String()
return bic2022Regex().MatchString(bicString)
}
// isSemverFormat is the validation function for validating if the current field's value is a valid semver version, defined in Semantic Versioning 2.0.0
func isSemverFormat(fl FieldLevel) bool {
semverString := fl.Field().String()
return semverRegex().MatchString(semverString)
}
// isCveFormat is the validation function for validating if the current field's value is a valid cve id, defined in CVE mitre org
func isCveFormat(fl FieldLevel) bool {
cveString := fl.Field().String()
return cveRegex().MatchString(cveString)
}
// isDnsRFC1035LabelFormat is the validation function
// for validating if the current field's value is
// a valid dns RFC 1035 label, defined in RFC 1035.
func isDnsRFC1035LabelFormat(fl FieldLevel) bool {
val := fl.Field().String()
size := len(val)
if size > 63 {
return false
}
return dnsRegexRFC1035Label().MatchString(val)
}
// digitsHaveLuhnChecksum returns true if and only if the last element of the given digits slice is the Luhn checksum of the previous elements
func digitsHaveLuhnChecksum(digits []string) bool {
size := len(digits)
sum := 0
for i, digit := range digits {
value, err := strconv.Atoi(digit)
if err != nil {
return false
}
if size%2 == 0 && i%2 == 0 || size%2 == 1 && i%2 == 1 {
v := value * 2
if v >= 10 {
sum += 1 + (v % 10)
} else {
sum += v
}
} else {
sum += value
}
}
return (sum % 10) == 0
}
// isMongoDBObjectId is the validation function for validating if the current field's value is valid MongoDB ObjectID
func isMongoDBObjectId(fl FieldLevel) bool {
val := fl.Field().String()
return mongodbIdRegex().MatchString(val)
}
// isMongoDBConnectionString is the validation function for validating if the current field's value is valid MongoDB Connection String
func isMongoDBConnectionString(fl FieldLevel) bool {
val := fl.Field().String()
return mongodbConnectionRegex().MatchString(val)
}
// isSpiceDB is the validation function for validating if the current field's value is valid for use with Authzed SpiceDB in the indicated way
func isSpiceDB(fl FieldLevel) bool {
val := fl.Field().String()
param := fl.Param()
switch param {
case "permission":
return spicedbPermissionRegex().MatchString(val)
case "type":
return spicedbTypeRegex().MatchString(val)
case "id", "":
return spicedbIDRegex().MatchString(val)
}
panic("Unrecognized parameter: " + param)
}
// isCreditCard is the validation function for validating if the current field's value is a valid credit card number
func isCreditCard(fl FieldLevel) bool {
val := fl.Field().String()
var creditCard bytes.Buffer
segments := strings.Split(val, " ")
for _, segment := range segments {
if len(segment) < 3 {
return false
}
creditCard.WriteString(segment)
}
ccDigits := strings.Split(creditCard.String(), "")
size := len(ccDigits)
if size < 12 || size > 19 {
return false
}
return digitsHaveLuhnChecksum(ccDigits)
}
// hasLuhnChecksum is the validation for validating if the current field's value has a valid Luhn checksum
func hasLuhnChecksum(fl FieldLevel) bool {
field := fl.Field()
var str string // convert to a string which will then be split into single digits; easier and more readable than shifting/extracting single digits from a number
switch field.Kind() {
case reflect.String:
str = field.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
str = strconv.FormatInt(field.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
str = strconv.FormatUint(field.Uint(), 10)
default:
panic(fmt.Sprintf("Bad field type %s", field.Type()))
}
size := len(str)
if size < 2 { // there has to be at least one digit that carries a meaning + the checksum
return false
}
digits := strings.Split(str, "")
return digitsHaveLuhnChecksum(digits)
}
// isCron is the validation function for validating if the current field's value is a valid cron expression
func isCron(fl FieldLevel) bool {
cronString := fl.Field().String()
return cronRegex().MatchString(cronString)
}
// isEIN is the validation function for validating if the current field's value is a valid U.S. Employer Identification Number (EIN)
func isEIN(fl FieldLevel) bool {
field := fl.Field()
if field.Len() != 10 {
return false
}
return einRegex().MatchString(field.String())
}
func isValidateFn(fl FieldLevel) bool {
const defaultParam = `Validate`
field := fl.Field()
validateFn := cmp.Or(fl.Param(), defaultParam)
ok, err := tryCallValidateFn(field, validateFn)
if err != nil {
return false
}
return ok
}
var (
errMethodNotFound = errors.New(`method not found`)
errMethodReturnNoValues = errors.New(`method return o values (void)`)
errMethodReturnInvalidType = errors.New(`method should return invalid type`)
)
func tryCallValidateFn(field reflect.Value, validateFn string) (bool, error) {
method := field.MethodByName(validateFn)
if field.CanAddr() && !method.IsValid() {
method = field.Addr().MethodByName(validateFn)
}
if !method.IsValid() {
return false, fmt.Errorf("unable to call %q on type %q: %w",
validateFn, field.Type().String(), errMethodNotFound)
}
returnValues := method.Call([]reflect.Value{})
if len(returnValues) == 0 {
return false, fmt.Errorf("unable to use result of method %q on type %q: %w",
validateFn, field.Type().String(), errMethodReturnNoValues)
}
firstReturnValue := returnValues[0]
switch firstReturnValue.Kind() {
case reflect.Bool:
return firstReturnValue.Bool(), nil
case reflect.Interface:
errorType := reflect.TypeOf((*error)(nil)).Elem()
if firstReturnValue.Type().Implements(errorType) {
return firstReturnValue.IsNil(), nil
}
return false, fmt.Errorf("unable to use result of method %q on type %q: %w (got interface %v expect error)",
validateFn, field.Type().String(), errMethodReturnInvalidType, firstReturnValue.Type().String())
default:
return false, fmt.Errorf("unable to use result of method %q on type %q: %w (got %v expect error or bool)",
validateFn, field.Type().String(), errMethodReturnInvalidType, firstReturnValue.Type().String())
}
}
golang-github-go-playground-validator-v10-10.30.1/benchmarks_test.go 0000664 0000000 0000000 00000051302 15124100770 0025260 0 ustar 00root root 0000000 0000000 package validator
import (
"bytes"
sql "database/sql/driver"
"errors"
"testing"
"time"
)
func BenchmarkFieldSuccess(b *testing.B) {
validate := New()
s := "1"
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(&s, "len=1")
}
}
func BenchmarkFieldSuccessParallel(b *testing.B) {
validate := New()
s := "1"
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(&s, "len=1")
}
})
}
func BenchmarkFieldFailure(b *testing.B) {
validate := New()
s := "12"
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(&s, "len=1")
}
}
func BenchmarkFieldFailureParallel(b *testing.B) {
validate := New()
s := "12"
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(&s, "len=1")
}
})
}
func BenchmarkFieldArrayDiveSuccess(b *testing.B) {
validate := New()
m := []string{"val1", "val2", "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldArrayDiveSuccessParallel(b *testing.B) {
validate := New()
m := []string{"val1", "val2", "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,required")
}
})
}
func BenchmarkFieldArrayDiveFailure(b *testing.B) {
validate := New()
m := []string{"val1", "", "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldArrayDiveFailureParallel(b *testing.B) {
validate := New()
m := []string{"val1", "", "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,required")
}
})
}
func BenchmarkFieldMapDiveSuccess(b *testing.B) {
validate := New()
m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldMapDiveSuccessParallel(b *testing.B) {
validate := New()
m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,required")
}
})
}
func BenchmarkFieldMapDiveFailure(b *testing.B) {
validate := New()
m := map[string]string{"": "", "val3": "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldMapDiveFailureParallel(b *testing.B) {
validate := New()
m := map[string]string{"": "", "val3": "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,required")
}
})
}
func BenchmarkFieldMapDiveWithKeysSuccess(b *testing.B) {
validate := New()
m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
}
}
func BenchmarkFieldMapDiveWithKeysSuccessParallel(b *testing.B) {
validate := New()
m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
}
})
}
func BenchmarkFieldMapDiveWithKeysFailure(b *testing.B) {
validate := New()
m := map[string]string{"": "", "val3": "val3"}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
}
}
func BenchmarkFieldMapDiveWithKeysFailureParallel(b *testing.B) {
validate := New()
m := map[string]string{"": "", "val3": "val3"}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
}
})
}
func BenchmarkFieldCustomTypeSuccess(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
Name: "1",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(val, "len=1")
}
}
func BenchmarkFieldCustomTypeSuccessParallel(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
Name: "1",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(val, "len=1")
}
})
}
func BenchmarkFieldCustomTypeFailure(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(val, "len=1")
}
}
func BenchmarkFieldCustomTypeFailureParallel(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(val, "len=1")
}
})
}
func BenchmarkFieldOrTagSuccess(b *testing.B) {
validate := New()
s := "rgba(0,0,0,1)"
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(s, "rgb|rgba")
}
}
func BenchmarkFieldOrTagSuccessParallel(b *testing.B) {
validate := New()
s := "rgba(0,0,0,1)"
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(s, "rgb|rgba")
}
})
}
func BenchmarkFieldOrTagFailure(b *testing.B) {
validate := New()
s := "#000"
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Var(s, "rgb|rgba")
}
}
func BenchmarkFieldOrTagFailureParallel(b *testing.B) {
validate := New()
s := "#000"
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Var(s, "rgb|rgba")
}
})
}
func BenchmarkStructLevelValidationSuccess(b *testing.B) {
validate := New()
validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
tst := TestStruct{
String: "good value",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(tst)
}
}
func BenchmarkStructLevelValidationSuccessParallel(b *testing.B) {
validate := New()
validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
tst := TestStruct{
String: "good value",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(tst)
}
})
}
func BenchmarkStructLevelValidationFailure(b *testing.B) {
validate := New()
validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
tst := TestStruct{
String: "good value",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(tst)
}
}
func BenchmarkStructLevelValidationFailureParallel(b *testing.B) {
validate := New()
validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
tst := TestStruct{
String: "good value",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(tst)
}
})
}
func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
Name: "1",
}
type Foo struct {
Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{Valuer: val, IntValue: 7}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(validFoo)
}
}
func BenchmarkStructSimpleCustomTypeSuccessParallel(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
Name: "1",
}
type Foo struct {
Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{Valuer: val, IntValue: 7}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(validFoo)
}
})
}
func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
type Foo struct {
Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{Valuer: val, IntValue: 3}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(validFoo)
}
}
func BenchmarkStructSimpleCustomTypeFailureParallel(b *testing.B) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
type Foo struct {
Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{Valuer: val, IntValue: 3}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(validate.Struct(validFoo))
}
})
}
func BenchmarkStructFilteredSuccess(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
byts := []byte("Name")
fn := func(ns []byte) bool {
return !bytes.HasSuffix(ns, byts)
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructFiltered(test, fn)
}
}
func BenchmarkStructFilteredSuccessParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
byts := []byte("Name")
fn := func(ns []byte) bool {
return !bytes.HasSuffix(ns, byts)
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructFiltered(test, fn)
}
})
}
func BenchmarkStructFilteredFailure(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
byts := []byte("NickName")
fn := func(ns []byte) bool {
return !bytes.HasSuffix(ns, byts)
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructFiltered(test, fn)
}
}
func BenchmarkStructFilteredFailureParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
byts := []byte("NickName")
fn := func(ns []byte) bool {
return !bytes.HasSuffix(ns, byts)
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructFiltered(test, fn)
}
})
}
func BenchmarkStructPartialSuccess(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructPartial(test, "Name")
}
}
func BenchmarkStructPartialSuccessParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructPartial(test, "Name")
}
})
}
func BenchmarkStructPartialFailure(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructPartial(test, "NickName")
}
}
func BenchmarkStructPartialFailureParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructPartial(test, "NickName")
}
})
}
func BenchmarkStructExceptSuccess(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructExcept(test, "Nickname")
}
}
func BenchmarkStructExceptSuccessParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructExcept(test, "NickName")
}
})
}
func BenchmarkStructExceptFailure(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.StructExcept(test, "Name")
}
}
func BenchmarkStructExceptFailureParallel(b *testing.B) {
validate := New()
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.StructExcept(test, "Name")
}
})
}
func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
validate := New()
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
test := &Test{
Start: now,
End: then,
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(test)
}
}
func BenchmarkStructSimpleCrossFieldSuccessParallel(b *testing.B) {
validate := New()
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
test := &Test{
Start: now,
End: then,
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(test)
}
})
}
func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
validate := New()
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * -5)
test := &Test{
Start: now,
End: then,
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(test)
}
}
func BenchmarkStructSimpleCrossFieldFailureParallel(b *testing.B) {
validate := New()
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * -5)
test := &Test{
Start: now,
End: then,
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(test)
}
})
}
func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
validate := New()
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
inner := &Inner{
Start: now,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(outer)
}
}
func BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel(b *testing.B) {
validate := New()
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
inner := &Inner{
Start: now,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(outer)
}
})
}
func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
validate := New()
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
inner := &Inner{
Start: then,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(outer)
}
}
func BenchmarkStructSimpleCrossStructCrossFieldFailureParallel(b *testing.B) {
validate := New()
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
inner := &Inner{
Start: then,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(outer)
}
})
}
func BenchmarkStructSimpleSuccess(b *testing.B) {
validate := New()
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(validFoo)
}
}
func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
validate := New()
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
}
validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(validFoo)
}
})
}
func BenchmarkStructSimpleFailure(b *testing.B) {
validate := New()
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
}
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(invalidFoo)
}
}
func BenchmarkStructSimpleFailureParallel(b *testing.B) {
validate := New()
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
}
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(invalidFoo)
}
})
}
func BenchmarkStructComplexSuccess(b *testing.B) {
validate := New()
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
Min: "min=1",
Max: "1234567890",
MinMax: "12345",
Lt: "012345678",
Lte: "0123456789",
Gt: "01234567890",
Gte: "0123456789",
OmitEmpty: "",
Sub: &SubTest{
Test: "1",
},
SubIgnore: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "1",
},
Iface: &Impl{
F: "123",
},
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(tSuccess)
}
}
func BenchmarkStructComplexSuccessParallel(b *testing.B) {
validate := New()
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
Min: "min=1",
Max: "1234567890",
MinMax: "12345",
Lt: "012345678",
Lte: "0123456789",
Gt: "01234567890",
Gte: "0123456789",
OmitEmpty: "",
Sub: &SubTest{
Test: "1",
},
SubIgnore: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "1",
},
Iface: &Impl{
F: "123",
},
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(tSuccess)
}
})
}
func BenchmarkStructComplexFailure(b *testing.B) {
validate := New()
tFail := &TestString{
Required: "",
Len: "",
Min: "",
Max: "12345678901",
MinMax: "",
Lt: "0123456789",
Lte: "01234567890",
Gt: "1",
Gte: "1",
OmitEmpty: "12345678901",
Sub: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "",
},
Iface: &Impl{
F: "12",
},
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(tFail)
}
}
func BenchmarkStructComplexFailureParallel(b *testing.B) {
validate := New()
tFail := &TestString{
Required: "",
Len: "",
Min: "",
Max: "12345678901",
MinMax: "",
Lt: "0123456789",
Lte: "01234567890",
Gt: "1",
Gte: "1",
OmitEmpty: "12345678901",
Sub: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "",
},
Iface: &Impl{
F: "12",
},
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(tFail)
}
})
}
type TestOneof struct {
Color string `validate:"oneof=red green"`
}
func BenchmarkOneof(b *testing.B) {
w := &TestOneof{Color: "green"}
val := New()
for i := 0; i < b.N; i++ {
_ = val.Struct(w)
}
}
func BenchmarkOneofParallel(b *testing.B) {
w := &TestOneof{Color: "green"}
val := New()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = val.Struct(w)
}
})
}
type T struct{}
func (*T) Validate() error { return errors.New("ops") }
func BenchmarkValidateFnSequencial(b *testing.B) {
validate := New()
type Test struct {
T T `validate:"validateFn"`
}
test := &Test{}
b.ResetTimer()
for n := 0; n < b.N; n++ {
_ = validate.Struct(test)
}
}
func BenchmarkValidateFnParallel(b *testing.B) {
validate := New()
type Test struct {
T T `validate:"validateFn"`
}
test := &Test{}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = validate.Struct(test)
}
})
}
golang-github-go-playground-validator-v10-10.30.1/cache.go 0000664 0000000 0000000 00000020351 15124100770 0023147 0 ustar 00root root 0000000 0000000 package validator
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
type tagType uint8
const (
typeDefault tagType = iota
typeOmitEmpty
typeIsDefault
typeNoStructLevel
typeStructOnly
typeDive
typeOr
typeKeys
typeEndKeys
typeOmitNil
typeOmitZero
)
const (
invalidValidation = "Invalid validation tag on field '%s'"
undefinedValidation = "Undefined validation function '%s' on field '%s'"
keysTagNotDefined = "'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag"
)
type structCache struct {
lock sync.Mutex
m atomic.Value // map[reflect.Type]*cStruct
}
func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) {
c, found = sc.m.Load().(map[reflect.Type]*cStruct)[key]
return
}
func (sc *structCache) Set(key reflect.Type, value *cStruct) {
m := sc.m.Load().(map[reflect.Type]*cStruct)
nm := make(map[reflect.Type]*cStruct, len(m)+1)
for k, v := range m {
nm[k] = v
}
nm[key] = value
sc.m.Store(nm)
}
type tagCache struct {
lock sync.Mutex
m atomic.Value // map[string]*cTag
}
func (tc *tagCache) Get(key string) (c *cTag, found bool) {
c, found = tc.m.Load().(map[string]*cTag)[key]
return
}
func (tc *tagCache) Set(key string, value *cTag) {
m := tc.m.Load().(map[string]*cTag)
nm := make(map[string]*cTag, len(m)+1)
for k, v := range m {
nm[k] = v
}
nm[key] = value
tc.m.Store(nm)
}
type cStruct struct {
name string
fields []*cField
fn StructLevelFuncCtx
}
type cField struct {
idx int
name string
altName string
namesEqual bool
cTags *cTag
}
type cTag struct {
tag string
aliasTag string
actualAliasTag string
param string
keys *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation
next *cTag
fn FuncCtx
typeof tagType
hasTag bool
hasAlias bool
hasParam bool // true if parameter used eg. eq= where the equal sign has been set
isBlockEnd bool // indicates the current tag represents the last validation in the block
runValidationWhenNil bool
}
func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct {
v.structCache.lock.Lock()
defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise!
typ := current.Type()
// could have been multiple trying to access, but once first is done this ensures struct
// isn't parsed again.
cs, ok := v.structCache.Get(typ)
if ok {
return cs
}
cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]}
numFields := current.NumField()
rules := v.rules[typ]
var ctag *cTag
var fld reflect.StructField
var tag string
var customName string
for i := 0; i < numFields; i++ {
fld = typ.Field(i)
if !v.privateFieldValidation && !fld.Anonymous && len(fld.PkgPath) > 0 {
continue
}
if rtag, ok := rules[fld.Name]; ok {
tag = rtag
} else {
tag = fld.Tag.Get(v.tagName)
}
if tag == skipValidationTag {
continue
}
customName = fld.Name
if v.hasTagNameFunc {
name := v.tagNameFunc(fld)
if len(name) > 0 {
customName = name
}
}
// NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different
// and so only struct level caching can be used instead of combined with Field tag caching
if len(tag) > 0 {
ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false)
} else {
// even if field doesn't have validations need cTag for traversing to potential inner/nested
// elements of the field.
ctag = new(cTag)
}
cs.fields = append(cs.fields, &cField{
idx: i,
name: fld.Name,
altName: customName,
cTags: ctag,
namesEqual: fld.Name == customName,
})
}
v.structCache.Set(typ, cs)
return cs
}
func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias string, hasAlias bool) (firstCtag *cTag, current *cTag) {
var t string
noAlias := len(alias) == 0
tags := strings.Split(tag, tagSeparator)
for i := 0; i < len(tags); i++ {
t = tags[i]
if noAlias {
alias = t
}
// check map for alias and process new tags, otherwise process as usual
if tagsVal, found := v.aliases[t]; found {
if i == 0 {
firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
} else {
next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
current.next, current = next, curr
}
continue
}
var prevTag tagType
if i == 0 {
current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true, typeof: typeDefault}
firstCtag = current
} else {
prevTag = current.typeof
current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true}
current = current.next
}
switch t {
case diveTag:
current.typeof = typeDive
case keysTag:
current.typeof = typeKeys
if i == 0 || prevTag != typeDive {
panic(fmt.Sprintf("'%s' tag must be immediately preceded by the '%s' tag", keysTag, diveTag))
}
// need to pass along only keys tag
// need to increment i to skip over the keys tags
b := make([]byte, 0, 64)
i++
for ; i < len(tags); i++ {
b = append(b, tags[i]...)
b = append(b, ',')
if tags[i] == endKeysTag {
break
}
}
current.keys, _ = v.parseFieldTagsRecursive(string(b[:len(b)-1]), fieldName, "", false)
case endKeysTag:
current.typeof = typeEndKeys
// if there are more in tags then there was no keysTag defined
// and an error should be thrown
if i != len(tags)-1 {
panic(keysTagNotDefined)
}
return
case omitzero:
current.typeof = typeOmitZero
continue
case omitempty:
current.typeof = typeOmitEmpty
case omitnil:
current.typeof = typeOmitNil
case structOnlyTag:
current.typeof = typeStructOnly
case noStructLevelTag:
current.typeof = typeNoStructLevel
default:
if t == isdefault {
current.typeof = typeIsDefault
}
// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
orVals := strings.Split(t, orSeparator)
for j := 0; j < len(orVals); j++ {
vals := strings.SplitN(orVals[j], tagKeySeparator, 2)
if noAlias {
alias = vals[0]
current.aliasTag = alias
} else {
current.actualAliasTag = t
}
if j > 0 {
current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true}
current = current.next
}
current.hasParam = len(vals) > 1
current.tag = vals[0]
if len(current.tag) == 0 {
panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName)))
}
if wrapper, ok := v.validations[current.tag]; ok {
current.fn = wrapper.fn
current.runValidationWhenNil = wrapper.runValidationOnNil
} else if aliasTag, isAlias := v.aliases[current.tag]; isAlias {
aliasFirst, aliasLast := v.parseFieldTagsRecursive(aliasTag, fieldName, current.tag, true)
current.tag = aliasFirst.tag
current.fn = aliasFirst.fn
current.runValidationWhenNil = aliasFirst.runValidationWhenNil
current.hasParam = aliasFirst.hasParam
current.param = aliasFirst.param
current.typeof = aliasFirst.typeof
current.hasAlias = true
if aliasFirst.next != nil {
nextInChain := current.next
current.next = aliasFirst.next
aliasLast.next = nextInChain
aliasLast.isBlockEnd = false
current = aliasLast
}
} else {
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
}
if len(orVals) > 1 {
current.typeof = typeOr
}
if len(vals) > 1 {
current.param = strings.ReplaceAll(strings.ReplaceAll(vals[1], utf8HexComma, ","), utf8Pipe, "|")
}
}
current.isBlockEnd = true
}
}
return
}
func (v *Validate) fetchCacheTag(tag string) *cTag {
// find cached tag
ctag, found := v.tagCache.Get(tag)
if !found {
v.tagCache.lock.Lock()
defer v.tagCache.lock.Unlock()
// could have been multiple trying to access, but once first is done this ensures tag
// isn't parsed again.
ctag, found = v.tagCache.Get(tag)
if !found {
ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
v.tagCache.Set(tag, ctag)
}
}
return ctag
}
golang-github-go-playground-validator-v10-10.30.1/country_codes.go 0000664 0000000 0000000 00000224600 15124100770 0024767 0 ustar 00root root 0000000 0000000 package validator
var iso3166_1_alpha2 = map[string]struct{}{
// see: https://www.iso.org/iso-3166-country-codes.html
"AF": {}, "AX": {}, "AL": {}, "DZ": {}, "AS": {},
"AD": {}, "AO": {}, "AI": {}, "AQ": {}, "AG": {},
"AR": {}, "AM": {}, "AW": {}, "AU": {}, "AT": {},
"AZ": {}, "BS": {}, "BH": {}, "BD": {}, "BB": {},
"BY": {}, "BE": {}, "BZ": {}, "BJ": {}, "BM": {},
"BT": {}, "BO": {}, "BQ": {}, "BA": {}, "BW": {},
"BV": {}, "BR": {}, "IO": {}, "BN": {}, "BG": {},
"BF": {}, "BI": {}, "KH": {}, "CM": {}, "CA": {},
"CV": {}, "KY": {}, "CF": {}, "TD": {}, "CL": {},
"CN": {}, "CX": {}, "CC": {}, "CO": {}, "KM": {},
"CG": {}, "CD": {}, "CK": {}, "CR": {}, "CI": {},
"HR": {}, "CU": {}, "CW": {}, "CY": {}, "CZ": {},
"DK": {}, "DJ": {}, "DM": {}, "DO": {}, "EC": {},
"EG": {}, "SV": {}, "GQ": {}, "ER": {}, "EE": {},
"ET": {}, "FK": {}, "FO": {}, "FJ": {}, "FI": {},
"FR": {}, "GF": {}, "PF": {}, "TF": {}, "GA": {},
"GM": {}, "GE": {}, "DE": {}, "GH": {}, "GI": {},
"GR": {}, "GL": {}, "GD": {}, "GP": {}, "GU": {},
"GT": {}, "GG": {}, "GN": {}, "GW": {}, "GY": {},
"HT": {}, "HM": {}, "VA": {}, "HN": {}, "HK": {},
"HU": {}, "IS": {}, "IN": {}, "ID": {}, "IR": {},
"IQ": {}, "IE": {}, "IM": {}, "IL": {}, "IT": {},
"JM": {}, "JP": {}, "JE": {}, "JO": {}, "KZ": {},
"KE": {}, "KI": {}, "KP": {}, "KR": {}, "KW": {},
"KG": {}, "LA": {}, "LV": {}, "LB": {}, "LS": {},
"LR": {}, "LY": {}, "LI": {}, "LT": {}, "LU": {},
"MO": {}, "MK": {}, "MG": {}, "MW": {}, "MY": {},
"MV": {}, "ML": {}, "MT": {}, "MH": {}, "MQ": {},
"MR": {}, "MU": {}, "YT": {}, "MX": {}, "FM": {},
"MD": {}, "MC": {}, "MN": {}, "ME": {}, "MS": {},
"MA": {}, "MZ": {}, "MM": {}, "NA": {}, "NR": {},
"NP": {}, "NL": {}, "NC": {}, "NZ": {}, "NI": {},
"NE": {}, "NG": {}, "NU": {}, "NF": {}, "MP": {},
"NO": {}, "OM": {}, "PK": {}, "PW": {}, "PS": {},
"PA": {}, "PG": {}, "PY": {}, "PE": {}, "PH": {},
"PN": {}, "PL": {}, "PT": {}, "PR": {}, "QA": {},
"RE": {}, "RO": {}, "RU": {}, "RW": {}, "BL": {},
"SH": {}, "KN": {}, "LC": {}, "MF": {}, "PM": {},
"VC": {}, "WS": {}, "SM": {}, "ST": {}, "SA": {},
"SN": {}, "RS": {}, "SC": {}, "SL": {}, "SG": {},
"SX": {}, "SK": {}, "SI": {}, "SB": {}, "SO": {},
"ZA": {}, "GS": {}, "SS": {}, "ES": {}, "LK": {},
"SD": {}, "SR": {}, "SJ": {}, "SZ": {}, "SE": {},
"CH": {}, "SY": {}, "TW": {}, "TJ": {}, "TZ": {},
"TH": {}, "TL": {}, "TG": {}, "TK": {}, "TO": {},
"TT": {}, "TN": {}, "TR": {}, "TM": {}, "TC": {},
"TV": {}, "UG": {}, "UA": {}, "AE": {}, "GB": {},
"US": {}, "UM": {}, "UY": {}, "UZ": {}, "VU": {},
"VE": {}, "VN": {}, "VG": {}, "VI": {}, "WF": {},
"EH": {}, "YE": {}, "ZM": {}, "ZW": {}, "XK": {},
}
var iso3166_1_alpha2_eu = map[string]struct{}{
"AT": {}, "BE": {}, "BG": {}, "HR": {}, "CY": {},
"CZ": {}, "DK": {}, "EE": {}, "FI": {}, "FR": {},
"DE": {}, "GR": {}, "HU": {}, "IE": {}, "IT": {},
"LV": {}, "LT": {}, "LU": {}, "MT": {}, "NL": {},
"PL": {}, "PT": {}, "RO": {}, "SK": {}, "SI": {},
"ES": {}, "SE": {},
}
var iso3166_1_alpha3 = map[string]struct{}{
// see: https://www.iso.org/iso-3166-country-codes.html
"AFG": {}, "ALB": {}, "DZA": {}, "ASM": {}, "AND": {},
"AGO": {}, "AIA": {}, "ATA": {}, "ATG": {}, "ARG": {},
"ARM": {}, "ABW": {}, "AUS": {}, "AUT": {}, "AZE": {},
"BHS": {}, "BHR": {}, "BGD": {}, "BRB": {}, "BLR": {},
"BEL": {}, "BLZ": {}, "BEN": {}, "BMU": {}, "BTN": {},
"BOL": {}, "BES": {}, "BIH": {}, "BWA": {}, "BVT": {},
"BRA": {}, "IOT": {}, "BRN": {}, "BGR": {}, "BFA": {},
"BDI": {}, "CPV": {}, "KHM": {}, "CMR": {}, "CAN": {},
"CYM": {}, "CAF": {}, "TCD": {}, "CHL": {}, "CHN": {},
"CXR": {}, "CCK": {}, "COL": {}, "COM": {}, "COD": {},
"COG": {}, "COK": {}, "CRI": {}, "HRV": {}, "CUB": {},
"CUW": {}, "CYP": {}, "CZE": {}, "CIV": {}, "DNK": {},
"DJI": {}, "DMA": {}, "DOM": {}, "ECU": {}, "EGY": {},
"SLV": {}, "GNQ": {}, "ERI": {}, "EST": {}, "SWZ": {},
"ETH": {}, "FLK": {}, "FRO": {}, "FJI": {}, "FIN": {},
"FRA": {}, "GUF": {}, "PYF": {}, "ATF": {}, "GAB": {},
"GMB": {}, "GEO": {}, "DEU": {}, "GHA": {}, "GIB": {},
"GRC": {}, "GRL": {}, "GRD": {}, "GLP": {}, "GUM": {},
"GTM": {}, "GGY": {}, "GIN": {}, "GNB": {}, "GUY": {},
"HTI": {}, "HMD": {}, "VAT": {}, "HND": {}, "HKG": {},
"HUN": {}, "ISL": {}, "IND": {}, "IDN": {}, "IRN": {},
"IRQ": {}, "IRL": {}, "IMN": {}, "ISR": {}, "ITA": {},
"JAM": {}, "JPN": {}, "JEY": {}, "JOR": {}, "KAZ": {},
"KEN": {}, "KIR": {}, "PRK": {}, "KOR": {}, "KWT": {},
"KGZ": {}, "LAO": {}, "LVA": {}, "LBN": {}, "LSO": {},
"LBR": {}, "LBY": {}, "LIE": {}, "LTU": {}, "LUX": {},
"MAC": {}, "MDG": {}, "MWI": {}, "MYS": {}, "MDV": {},
"MLI": {}, "MLT": {}, "MHL": {}, "MTQ": {}, "MRT": {},
"MUS": {}, "MYT": {}, "MEX": {}, "FSM": {}, "MDA": {},
"MCO": {}, "MNG": {}, "MNE": {}, "MSR": {}, "MAR": {},
"MOZ": {}, "MMR": {}, "NAM": {}, "NRU": {}, "NPL": {},
"NLD": {}, "NCL": {}, "NZL": {}, "NIC": {}, "NER": {},
"NGA": {}, "NIU": {}, "NFK": {}, "MKD": {}, "MNP": {},
"NOR": {}, "OMN": {}, "PAK": {}, "PLW": {}, "PSE": {},
"PAN": {}, "PNG": {}, "PRY": {}, "PER": {}, "PHL": {},
"PCN": {}, "POL": {}, "PRT": {}, "PRI": {}, "QAT": {},
"ROU": {}, "RUS": {}, "RWA": {}, "REU": {}, "BLM": {},
"SHN": {}, "KNA": {}, "LCA": {}, "MAF": {}, "SPM": {},
"VCT": {}, "WSM": {}, "SMR": {}, "STP": {}, "SAU": {},
"SEN": {}, "SRB": {}, "SYC": {}, "SLE": {}, "SGP": {},
"SXM": {}, "SVK": {}, "SVN": {}, "SLB": {}, "SOM": {},
"ZAF": {}, "SGS": {}, "SSD": {}, "ESP": {}, "LKA": {},
"SDN": {}, "SUR": {}, "SJM": {}, "SWE": {}, "CHE": {},
"SYR": {}, "TWN": {}, "TJK": {}, "TZA": {}, "THA": {},
"TLS": {}, "TGO": {}, "TKL": {}, "TON": {}, "TTO": {},
"TUN": {}, "TUR": {}, "TKM": {}, "TCA": {}, "TUV": {},
"UGA": {}, "UKR": {}, "ARE": {}, "GBR": {}, "UMI": {},
"USA": {}, "URY": {}, "UZB": {}, "VUT": {}, "VEN": {},
"VNM": {}, "VGB": {}, "VIR": {}, "WLF": {}, "ESH": {},
"YEM": {}, "ZMB": {}, "ZWE": {}, "ALA": {}, "UNK": {},
}
var iso3166_1_alpha3_eu = map[string]struct{}{
"AUT": {}, "BEL": {}, "BGR": {}, "HRV": {}, "CYP": {},
"CZE": {}, "DNK": {}, "EST": {}, "FIN": {}, "FRA": {},
"DEU": {}, "GRC": {}, "HUN": {}, "IRL": {}, "ITA": {},
"LVA": {}, "LTU": {}, "LUX": {}, "MLT": {}, "NLD": {},
"POL": {}, "PRT": {}, "ROU": {}, "SVK": {}, "SVN": {},
"ESP": {}, "SWE": {},
}
var iso3166_1_alpha_numeric = map[int]struct{}{
// see: https://www.iso.org/iso-3166-country-codes.html
4: {}, 8: {}, 12: {}, 16: {}, 20: {},
24: {}, 660: {}, 10: {}, 28: {}, 32: {},
51: {}, 533: {}, 36: {}, 40: {}, 31: {},
44: {}, 48: {}, 50: {}, 52: {}, 112: {},
56: {}, 84: {}, 204: {}, 60: {}, 64: {},
68: {}, 535: {}, 70: {}, 72: {}, 74: {},
76: {}, 86: {}, 96: {}, 100: {}, 854: {},
108: {}, 132: {}, 116: {}, 120: {}, 124: {},
136: {}, 140: {}, 148: {}, 152: {}, 156: {},
162: {}, 166: {}, 170: {}, 174: {}, 180: {},
178: {}, 184: {}, 188: {}, 191: {}, 192: {},
531: {}, 196: {}, 203: {}, 384: {}, 208: {},
262: {}, 212: {}, 214: {}, 218: {}, 818: {},
222: {}, 226: {}, 232: {}, 233: {}, 748: {},
231: {}, 238: {}, 234: {}, 242: {}, 246: {},
250: {}, 254: {}, 258: {}, 260: {}, 266: {},
270: {}, 268: {}, 276: {}, 288: {}, 292: {},
300: {}, 304: {}, 308: {}, 312: {}, 316: {},
320: {}, 831: {}, 324: {}, 624: {}, 328: {},
332: {}, 334: {}, 336: {}, 340: {}, 344: {},
348: {}, 352: {}, 356: {}, 360: {}, 364: {},
368: {}, 372: {}, 833: {}, 376: {}, 380: {},
388: {}, 392: {}, 832: {}, 400: {}, 398: {},
404: {}, 296: {}, 408: {}, 410: {}, 414: {},
417: {}, 418: {}, 428: {}, 422: {}, 426: {},
430: {}, 434: {}, 438: {}, 440: {}, 442: {},
446: {}, 450: {}, 454: {}, 458: {}, 462: {},
466: {}, 470: {}, 584: {}, 474: {}, 478: {},
480: {}, 175: {}, 484: {}, 583: {}, 498: {},
492: {}, 496: {}, 499: {}, 500: {}, 504: {},
508: {}, 104: {}, 516: {}, 520: {}, 524: {},
528: {}, 540: {}, 554: {}, 558: {}, 562: {},
566: {}, 570: {}, 574: {}, 807: {}, 580: {},
578: {}, 512: {}, 586: {}, 585: {}, 275: {},
591: {}, 598: {}, 600: {}, 604: {}, 608: {},
612: {}, 616: {}, 620: {}, 630: {}, 634: {},
642: {}, 643: {}, 646: {}, 638: {}, 652: {},
654: {}, 659: {}, 662: {}, 663: {}, 666: {},
670: {}, 882: {}, 674: {}, 678: {}, 682: {},
686: {}, 688: {}, 690: {}, 694: {}, 702: {},
534: {}, 703: {}, 705: {}, 90: {}, 706: {},
710: {}, 239: {}, 728: {}, 724: {}, 144: {},
729: {}, 740: {}, 744: {}, 752: {}, 756: {},
760: {}, 158: {}, 762: {}, 834: {}, 764: {},
626: {}, 768: {}, 772: {}, 776: {}, 780: {},
788: {}, 792: {}, 795: {}, 796: {}, 798: {},
800: {}, 804: {}, 784: {}, 826: {}, 581: {},
840: {}, 858: {}, 860: {}, 548: {}, 862: {},
704: {}, 92: {}, 850: {}, 876: {}, 732: {},
887: {}, 894: {}, 716: {}, 248: {}, 153: {},
}
var iso3166_1_alpha_numeric_eu = map[int]struct{}{
40: {}, 56: {}, 100: {}, 191: {}, 196: {},
200: {}, 208: {}, 233: {}, 246: {}, 250: {},
276: {}, 300: {}, 348: {}, 372: {}, 380: {},
428: {}, 440: {}, 442: {}, 470: {}, 528: {},
616: {}, 620: {}, 642: {}, 703: {}, 705: {},
724: {}, 752: {},
}
var iso3166_2 = map[string]struct{}{
"AD-02": {}, "AD-03": {}, "AD-04": {}, "AD-05": {}, "AD-06": {},
"AD-07": {}, "AD-08": {}, "AE-AJ": {}, "AE-AZ": {}, "AE-DU": {},
"AE-FU": {}, "AE-RK": {}, "AE-SH": {}, "AE-UQ": {}, "AF-BAL": {},
"AF-BAM": {}, "AF-BDG": {}, "AF-BDS": {}, "AF-BGL": {}, "AF-DAY": {},
"AF-FRA": {}, "AF-FYB": {}, "AF-GHA": {}, "AF-GHO": {}, "AF-HEL": {},
"AF-HER": {}, "AF-JOW": {}, "AF-KAB": {}, "AF-KAN": {}, "AF-KAP": {},
"AF-KDZ": {}, "AF-KHO": {}, "AF-KNR": {}, "AF-LAG": {}, "AF-LOG": {},
"AF-NAN": {}, "AF-NIM": {}, "AF-NUR": {}, "AF-PAN": {}, "AF-PAR": {},
"AF-PIA": {}, "AF-PKA": {}, "AF-SAM": {}, "AF-SAR": {}, "AF-TAK": {},
"AF-URU": {}, "AF-WAR": {}, "AF-ZAB": {}, "AG-03": {}, "AG-04": {},
"AG-05": {}, "AG-06": {}, "AG-07": {}, "AG-08": {}, "AG-10": {},
"AG-11": {}, "AL-01": {}, "AL-02": {}, "AL-03": {}, "AL-04": {},
"AL-05": {}, "AL-06": {}, "AL-07": {}, "AL-08": {}, "AL-09": {},
"AL-10": {}, "AL-11": {}, "AL-12": {}, "AL-BR": {}, "AL-BU": {},
"AL-DI": {}, "AL-DL": {}, "AL-DR": {}, "AL-DV": {}, "AL-EL": {},
"AL-ER": {}, "AL-FR": {}, "AL-GJ": {}, "AL-GR": {}, "AL-HA": {},
"AL-KA": {}, "AL-KB": {}, "AL-KC": {}, "AL-KO": {}, "AL-KR": {},
"AL-KU": {}, "AL-LB": {}, "AL-LE": {}, "AL-LU": {}, "AL-MK": {},
"AL-MM": {}, "AL-MR": {}, "AL-MT": {}, "AL-PG": {}, "AL-PQ": {},
"AL-PR": {}, "AL-PU": {}, "AL-SH": {}, "AL-SK": {}, "AL-SR": {},
"AL-TE": {}, "AL-TP": {}, "AL-TR": {}, "AL-VL": {}, "AM-AG": {},
"AM-AR": {}, "AM-AV": {}, "AM-ER": {}, "AM-GR": {}, "AM-KT": {},
"AM-LO": {}, "AM-SH": {}, "AM-SU": {}, "AM-TV": {}, "AM-VD": {},
"AO-BGO": {}, "AO-BGU": {}, "AO-BIE": {}, "AO-CAB": {}, "AO-CCU": {},
"AO-CNN": {}, "AO-CNO": {}, "AO-CUS": {}, "AO-HUA": {}, "AO-HUI": {},
"AO-LNO": {}, "AO-LSU": {}, "AO-LUA": {}, "AO-MAL": {}, "AO-MOX": {},
"AO-NAM": {}, "AO-UIG": {}, "AO-ZAI": {}, "AR-A": {}, "AR-B": {},
"AR-C": {}, "AR-D": {}, "AR-E": {}, "AR-F": {}, "AR-G": {}, "AR-H": {},
"AR-J": {}, "AR-K": {}, "AR-L": {}, "AR-M": {}, "AR-N": {},
"AR-P": {}, "AR-Q": {}, "AR-R": {}, "AR-S": {}, "AR-T": {},
"AR-U": {}, "AR-V": {}, "AR-W": {}, "AR-X": {}, "AR-Y": {},
"AR-Z": {}, "AT-1": {}, "AT-2": {}, "AT-3": {}, "AT-4": {},
"AT-5": {}, "AT-6": {}, "AT-7": {}, "AT-8": {}, "AT-9": {},
"AU-ACT": {}, "AU-NSW": {}, "AU-NT": {}, "AU-QLD": {}, "AU-SA": {},
"AU-TAS": {}, "AU-VIC": {}, "AU-WA": {}, "AZ-ABS": {}, "AZ-AGA": {},
"AZ-AGC": {}, "AZ-AGM": {}, "AZ-AGS": {}, "AZ-AGU": {}, "AZ-AST": {},
"AZ-BA": {}, "AZ-BAB": {}, "AZ-BAL": {}, "AZ-BAR": {}, "AZ-BEY": {},
"AZ-BIL": {}, "AZ-CAB": {}, "AZ-CAL": {}, "AZ-CUL": {}, "AZ-DAS": {},
"AZ-FUZ": {}, "AZ-GA": {}, "AZ-GAD": {}, "AZ-GOR": {}, "AZ-GOY": {},
"AZ-GYG": {}, "AZ-HAC": {}, "AZ-IMI": {}, "AZ-ISM": {}, "AZ-KAL": {},
"AZ-KAN": {}, "AZ-KUR": {}, "AZ-LA": {}, "AZ-LAC": {}, "AZ-LAN": {},
"AZ-LER": {}, "AZ-MAS": {}, "AZ-MI": {}, "AZ-NA": {}, "AZ-NEF": {},
"AZ-NV": {}, "AZ-NX": {}, "AZ-OGU": {}, "AZ-ORD": {}, "AZ-QAB": {},
"AZ-QAX": {}, "AZ-QAZ": {}, "AZ-QBA": {}, "AZ-QBI": {}, "AZ-QOB": {},
"AZ-QUS": {}, "AZ-SA": {}, "AZ-SAB": {}, "AZ-SAD": {}, "AZ-SAH": {},
"AZ-SAK": {}, "AZ-SAL": {}, "AZ-SAR": {}, "AZ-SAT": {}, "AZ-SBN": {},
"AZ-SIY": {}, "AZ-SKR": {}, "AZ-SM": {}, "AZ-SMI": {}, "AZ-SMX": {},
"AZ-SR": {}, "AZ-SUS": {}, "AZ-TAR": {}, "AZ-TOV": {}, "AZ-UCA": {},
"AZ-XA": {}, "AZ-XAC": {}, "AZ-XCI": {}, "AZ-XIZ": {}, "AZ-XVD": {},
"AZ-YAR": {}, "AZ-YE": {}, "AZ-YEV": {}, "AZ-ZAN": {}, "AZ-ZAQ": {},
"AZ-ZAR": {}, "BA-01": {}, "BA-02": {}, "BA-03": {}, "BA-04": {},
"BA-05": {}, "BA-06": {}, "BA-07": {}, "BA-08": {}, "BA-09": {},
"BA-10": {}, "BA-BIH": {}, "BA-BRC": {}, "BA-SRP": {}, "BB-01": {},
"BB-02": {}, "BB-03": {}, "BB-04": {}, "BB-05": {}, "BB-06": {},
"BB-07": {}, "BB-08": {}, "BB-09": {}, "BB-10": {}, "BB-11": {},
"BD-01": {}, "BD-02": {}, "BD-03": {}, "BD-04": {}, "BD-05": {},
"BD-06": {}, "BD-07": {}, "BD-08": {}, "BD-09": {}, "BD-10": {},
"BD-11": {}, "BD-12": {}, "BD-13": {}, "BD-14": {}, "BD-15": {},
"BD-16": {}, "BD-17": {}, "BD-18": {}, "BD-19": {}, "BD-20": {},
"BD-21": {}, "BD-22": {}, "BD-23": {}, "BD-24": {}, "BD-25": {},
"BD-26": {}, "BD-27": {}, "BD-28": {}, "BD-29": {}, "BD-30": {},
"BD-31": {}, "BD-32": {}, "BD-33": {}, "BD-34": {}, "BD-35": {},
"BD-36": {}, "BD-37": {}, "BD-38": {}, "BD-39": {}, "BD-40": {},
"BD-41": {}, "BD-42": {}, "BD-43": {}, "BD-44": {}, "BD-45": {},
"BD-46": {}, "BD-47": {}, "BD-48": {}, "BD-49": {}, "BD-50": {},
"BD-51": {}, "BD-52": {}, "BD-53": {}, "BD-54": {}, "BD-55": {},
"BD-56": {}, "BD-57": {}, "BD-58": {}, "BD-59": {}, "BD-60": {},
"BD-61": {}, "BD-62": {}, "BD-63": {}, "BD-64": {}, "BD-A": {},
"BD-B": {}, "BD-C": {}, "BD-D": {}, "BD-E": {}, "BD-F": {},
"BD-G": {}, "BD-H": {}, "BE-BRU": {}, "BE-VAN": {}, "BE-VBR": {}, "BE-VLG": {},
"BE-VLI": {}, "BE-VOV": {}, "BE-VWV": {}, "BE-WAL": {}, "BE-WBR": {},
"BE-WHT": {}, "BE-WLG": {}, "BE-WLX": {}, "BE-WNA": {}, "BF-01": {},
"BF-02": {}, "BF-03": {}, "BF-04": {}, "BF-05": {}, "BF-06": {},
"BF-07": {}, "BF-08": {}, "BF-09": {}, "BF-10": {}, "BF-11": {},
"BF-12": {}, "BF-13": {}, "BF-BAL": {}, "BF-BAM": {}, "BF-BAN": {},
"BF-BAZ": {}, "BF-BGR": {}, "BF-BLG": {}, "BF-BLK": {}, "BF-COM": {},
"BF-GAN": {}, "BF-GNA": {}, "BF-GOU": {}, "BF-HOU": {}, "BF-IOB": {},
"BF-KAD": {}, "BF-KEN": {}, "BF-KMD": {}, "BF-KMP": {}, "BF-KOP": {},
"BF-KOS": {}, "BF-KOT": {}, "BF-KOW": {}, "BF-LER": {}, "BF-LOR": {},
"BF-MOU": {}, "BF-NAM": {}, "BF-NAO": {}, "BF-NAY": {}, "BF-NOU": {},
"BF-OUB": {}, "BF-OUD": {}, "BF-PAS": {}, "BF-PON": {}, "BF-SEN": {},
"BF-SIS": {}, "BF-SMT": {}, "BF-SNG": {}, "BF-SOM": {}, "BF-SOR": {},
"BF-TAP": {}, "BF-TUI": {}, "BF-YAG": {}, "BF-YAT": {}, "BF-ZIR": {},
"BF-ZON": {}, "BF-ZOU": {}, "BG-01": {}, "BG-02": {}, "BG-03": {},
"BG-04": {}, "BG-05": {}, "BG-06": {}, "BG-07": {}, "BG-08": {},
"BG-09": {}, "BG-10": {}, "BG-11": {}, "BG-12": {}, "BG-13": {},
"BG-14": {}, "BG-15": {}, "BG-16": {}, "BG-17": {}, "BG-18": {},
"BG-19": {}, "BG-20": {}, "BG-21": {}, "BG-22": {}, "BG-23": {},
"BG-24": {}, "BG-25": {}, "BG-26": {}, "BG-27": {}, "BG-28": {},
"BH-13": {}, "BH-14": {}, "BH-15": {}, "BH-16": {}, "BH-17": {},
"BI-BB": {}, "BI-BL": {}, "BI-BM": {}, "BI-BR": {}, "BI-CA": {},
"BI-CI": {}, "BI-GI": {}, "BI-KI": {}, "BI-KR": {}, "BI-KY": {},
"BI-MA": {}, "BI-MU": {}, "BI-MW": {}, "BI-NG": {}, "BI-RM": {}, "BI-RT": {},
"BI-RY": {}, "BJ-AK": {}, "BJ-AL": {}, "BJ-AQ": {}, "BJ-BO": {},
"BJ-CO": {}, "BJ-DO": {}, "BJ-KO": {}, "BJ-LI": {}, "BJ-MO": {},
"BJ-OU": {}, "BJ-PL": {}, "BJ-ZO": {}, "BN-BE": {}, "BN-BM": {},
"BN-TE": {}, "BN-TU": {}, "BO-B": {}, "BO-C": {}, "BO-H": {},
"BO-L": {}, "BO-N": {}, "BO-O": {}, "BO-P": {}, "BO-S": {},
"BO-T": {}, "BQ-BO": {}, "BQ-SA": {}, "BQ-SE": {}, "BR-AC": {},
"BR-AL": {}, "BR-AM": {}, "BR-AP": {}, "BR-BA": {}, "BR-CE": {},
"BR-DF": {}, "BR-ES": {}, "BR-FN": {}, "BR-GO": {}, "BR-MA": {},
"BR-MG": {}, "BR-MS": {}, "BR-MT": {}, "BR-PA": {}, "BR-PB": {},
"BR-PE": {}, "BR-PI": {}, "BR-PR": {}, "BR-RJ": {}, "BR-RN": {},
"BR-RO": {}, "BR-RR": {}, "BR-RS": {}, "BR-SC": {}, "BR-SE": {},
"BR-SP": {}, "BR-TO": {}, "BS-AK": {}, "BS-BI": {}, "BS-BP": {},
"BS-BY": {}, "BS-CE": {}, "BS-CI": {}, "BS-CK": {}, "BS-CO": {},
"BS-CS": {}, "BS-EG": {}, "BS-EX": {}, "BS-FP": {}, "BS-GC": {},
"BS-HI": {}, "BS-HT": {}, "BS-IN": {}, "BS-LI": {}, "BS-MC": {},
"BS-MG": {}, "BS-MI": {}, "BS-NE": {}, "BS-NO": {}, "BS-NP": {}, "BS-NS": {},
"BS-RC": {}, "BS-RI": {}, "BS-SA": {}, "BS-SE": {}, "BS-SO": {},
"BS-SS": {}, "BS-SW": {}, "BS-WG": {}, "BT-11": {}, "BT-12": {},
"BT-13": {}, "BT-14": {}, "BT-15": {}, "BT-21": {}, "BT-22": {},
"BT-23": {}, "BT-24": {}, "BT-31": {}, "BT-32": {}, "BT-33": {},
"BT-34": {}, "BT-41": {}, "BT-42": {}, "BT-43": {}, "BT-44": {},
"BT-45": {}, "BT-GA": {}, "BT-TY": {}, "BW-CE": {}, "BW-CH": {}, "BW-GH": {},
"BW-KG": {}, "BW-KL": {}, "BW-KW": {}, "BW-NE": {}, "BW-NW": {},
"BW-SE": {}, "BW-SO": {}, "BY-BR": {}, "BY-HM": {}, "BY-HO": {},
"BY-HR": {}, "BY-MA": {}, "BY-MI": {}, "BY-VI": {}, "BZ-BZ": {},
"BZ-CY": {}, "BZ-CZL": {}, "BZ-OW": {}, "BZ-SC": {}, "BZ-TOL": {},
"CA-AB": {}, "CA-BC": {}, "CA-MB": {}, "CA-NB": {}, "CA-NL": {},
"CA-NS": {}, "CA-NT": {}, "CA-NU": {}, "CA-ON": {}, "CA-PE": {},
"CA-QC": {}, "CA-SK": {}, "CA-YT": {}, "CD-BC": {}, "CD-BN": {},
"CD-EQ": {}, "CD-HK": {}, "CD-IT": {}, "CD-KA": {}, "CD-KC": {}, "CD-KE": {}, "CD-KG": {}, "CD-KN": {},
"CD-KW": {}, "CD-KS": {}, "CD-LU": {}, "CD-MA": {}, "CD-NK": {}, "CD-OR": {}, "CD-SA": {}, "CD-SK": {},
"CD-TA": {}, "CD-TO": {}, "CF-AC": {}, "CF-BB": {}, "CF-BGF": {}, "CF-BK": {}, "CF-HK": {}, "CF-HM": {},
"CF-HS": {}, "CF-KB": {}, "CF-KG": {}, "CF-LB": {}, "CF-MB": {},
"CF-MP": {}, "CF-NM": {}, "CF-OP": {}, "CF-SE": {}, "CF-UK": {},
"CF-VK": {}, "CG-11": {}, "CG-12": {}, "CG-13": {}, "CG-14": {},
"CG-15": {}, "CG-16": {}, "CG-2": {}, "CG-5": {}, "CG-7": {}, "CG-8": {},
"CG-9": {}, "CG-BZV": {}, "CH-AG": {}, "CH-AI": {}, "CH-AR": {},
"CH-BE": {}, "CH-BL": {}, "CH-BS": {}, "CH-FR": {}, "CH-GE": {},
"CH-GL": {}, "CH-GR": {}, "CH-JU": {}, "CH-LU": {}, "CH-NE": {},
"CH-NW": {}, "CH-OW": {}, "CH-SG": {}, "CH-SH": {}, "CH-SO": {},
"CH-SZ": {}, "CH-TG": {}, "CH-TI": {}, "CH-UR": {}, "CH-VD": {},
"CH-VS": {}, "CH-ZG": {}, "CH-ZH": {}, "CI-AB": {}, "CI-BS": {},
"CI-CM": {}, "CI-DN": {}, "CI-GD": {}, "CI-LC": {}, "CI-LG": {},
"CI-MG": {}, "CI-SM": {}, "CI-SV": {}, "CI-VB": {}, "CI-WR": {},
"CI-YM": {}, "CI-ZZ": {}, "CL-AI": {}, "CL-AN": {}, "CL-AP": {},
"CL-AR": {}, "CL-AT": {}, "CL-BI": {}, "CL-CO": {}, "CL-LI": {},
"CL-LL": {}, "CL-LR": {}, "CL-MA": {}, "CL-ML": {}, "CL-NB": {}, "CL-RM": {},
"CL-TA": {}, "CL-VS": {}, "CM-AD": {}, "CM-CE": {}, "CM-EN": {},
"CM-ES": {}, "CM-LT": {}, "CM-NO": {}, "CM-NW": {}, "CM-OU": {},
"CM-SU": {}, "CM-SW": {}, "CN-AH": {}, "CN-BJ": {}, "CN-CQ": {},
"CN-FJ": {}, "CN-GS": {}, "CN-GD": {}, "CN-GX": {}, "CN-GZ": {},
"CN-HI": {}, "CN-HE": {}, "CN-HL": {}, "CN-HA": {}, "CN-HB": {},
"CN-HN": {}, "CN-JS": {}, "CN-JX": {}, "CN-JL": {}, "CN-LN": {},
"CN-NM": {}, "CN-NX": {}, "CN-QH": {}, "CN-SN": {}, "CN-SD": {}, "CN-SH": {},
"CN-SX": {}, "CN-SC": {}, "CN-TJ": {}, "CN-XJ": {}, "CN-XZ": {}, "CN-YN": {},
"CN-ZJ": {}, "CO-AMA": {}, "CO-ANT": {}, "CO-ARA": {}, "CO-ATL": {},
"CO-BOL": {}, "CO-BOY": {}, "CO-CAL": {}, "CO-CAQ": {}, "CO-CAS": {},
"CO-CAU": {}, "CO-CES": {}, "CO-CHO": {}, "CO-COR": {}, "CO-CUN": {},
"CO-DC": {}, "CO-GUA": {}, "CO-GUV": {}, "CO-HUI": {}, "CO-LAG": {},
"CO-MAG": {}, "CO-MET": {}, "CO-NAR": {}, "CO-NSA": {}, "CO-PUT": {},
"CO-QUI": {}, "CO-RIS": {}, "CO-SAN": {}, "CO-SAP": {}, "CO-SUC": {},
"CO-TOL": {}, "CO-VAC": {}, "CO-VAU": {}, "CO-VID": {}, "CR-A": {},
"CR-C": {}, "CR-G": {}, "CR-H": {}, "CR-L": {}, "CR-P": {},
"CR-SJ": {}, "CU-01": {}, "CU-02": {}, "CU-03": {}, "CU-04": {},
"CU-05": {}, "CU-06": {}, "CU-07": {}, "CU-08": {}, "CU-09": {},
"CU-10": {}, "CU-11": {}, "CU-12": {}, "CU-13": {}, "CU-14": {}, "CU-15": {},
"CU-16": {}, "CU-99": {}, "CV-B": {}, "CV-BR": {}, "CV-BV": {}, "CV-CA": {},
"CV-CF": {}, "CV-CR": {}, "CV-MA": {}, "CV-MO": {}, "CV-PA": {},
"CV-PN": {}, "CV-PR": {}, "CV-RB": {}, "CV-RG": {}, "CV-RS": {},
"CV-S": {}, "CV-SD": {}, "CV-SF": {}, "CV-SL": {}, "CV-SM": {},
"CV-SO": {}, "CV-SS": {}, "CV-SV": {}, "CV-TA": {}, "CV-TS": {},
"CY-01": {}, "CY-02": {}, "CY-03": {}, "CY-04": {}, "CY-05": {},
"CY-06": {}, "CZ-10": {}, "CZ-101": {}, "CZ-102": {}, "CZ-103": {},
"CZ-104": {}, "CZ-105": {}, "CZ-106": {}, "CZ-107": {}, "CZ-108": {},
"CZ-109": {}, "CZ-110": {}, "CZ-111": {}, "CZ-112": {}, "CZ-113": {},
"CZ-114": {}, "CZ-115": {}, "CZ-116": {}, "CZ-117": {}, "CZ-118": {},
"CZ-119": {}, "CZ-120": {}, "CZ-121": {}, "CZ-122": {}, "CZ-20": {},
"CZ-201": {}, "CZ-202": {}, "CZ-203": {}, "CZ-204": {}, "CZ-205": {},
"CZ-206": {}, "CZ-207": {}, "CZ-208": {}, "CZ-209": {}, "CZ-20A": {},
"CZ-20B": {}, "CZ-20C": {}, "CZ-31": {}, "CZ-311": {}, "CZ-312": {},
"CZ-313": {}, "CZ-314": {}, "CZ-315": {}, "CZ-316": {}, "CZ-317": {},
"CZ-32": {}, "CZ-321": {}, "CZ-322": {}, "CZ-323": {}, "CZ-324": {},
"CZ-325": {}, "CZ-326": {}, "CZ-327": {}, "CZ-41": {}, "CZ-411": {},
"CZ-412": {}, "CZ-413": {}, "CZ-42": {}, "CZ-421": {}, "CZ-422": {},
"CZ-423": {}, "CZ-424": {}, "CZ-425": {}, "CZ-426": {}, "CZ-427": {},
"CZ-51": {}, "CZ-511": {}, "CZ-512": {}, "CZ-513": {}, "CZ-514": {},
"CZ-52": {}, "CZ-521": {}, "CZ-522": {}, "CZ-523": {}, "CZ-524": {},
"CZ-525": {}, "CZ-53": {}, "CZ-531": {}, "CZ-532": {}, "CZ-533": {},
"CZ-534": {}, "CZ-63": {}, "CZ-631": {}, "CZ-632": {}, "CZ-633": {},
"CZ-634": {}, "CZ-635": {}, "CZ-64": {}, "CZ-641": {}, "CZ-642": {},
"CZ-643": {}, "CZ-644": {}, "CZ-645": {}, "CZ-646": {}, "CZ-647": {},
"CZ-71": {}, "CZ-711": {}, "CZ-712": {}, "CZ-713": {}, "CZ-714": {},
"CZ-715": {}, "CZ-72": {}, "CZ-721": {}, "CZ-722": {}, "CZ-723": {},
"CZ-724": {}, "CZ-80": {}, "CZ-801": {}, "CZ-802": {}, "CZ-803": {},
"CZ-804": {}, "CZ-805": {}, "CZ-806": {}, "DE-BB": {}, "DE-BE": {},
"DE-BW": {}, "DE-BY": {}, "DE-HB": {}, "DE-HE": {}, "DE-HH": {},
"DE-MV": {}, "DE-NI": {}, "DE-NW": {}, "DE-RP": {}, "DE-SH": {},
"DE-SL": {}, "DE-SN": {}, "DE-ST": {}, "DE-TH": {}, "DJ-AR": {},
"DJ-AS": {}, "DJ-DI": {}, "DJ-DJ": {}, "DJ-OB": {}, "DJ-TA": {},
"DK-81": {}, "DK-82": {}, "DK-83": {}, "DK-84": {}, "DK-85": {},
"DM-01": {}, "DM-02": {}, "DM-03": {}, "DM-04": {}, "DM-05": {},
"DM-06": {}, "DM-07": {}, "DM-08": {}, "DM-09": {}, "DM-10": {},
"DO-01": {}, "DO-02": {}, "DO-03": {}, "DO-04": {}, "DO-05": {},
"DO-06": {}, "DO-07": {}, "DO-08": {}, "DO-09": {}, "DO-10": {},
"DO-11": {}, "DO-12": {}, "DO-13": {}, "DO-14": {}, "DO-15": {},
"DO-16": {}, "DO-17": {}, "DO-18": {}, "DO-19": {}, "DO-20": {},
"DO-21": {}, "DO-22": {}, "DO-23": {}, "DO-24": {}, "DO-25": {},
"DO-26": {}, "DO-27": {}, "DO-28": {}, "DO-29": {}, "DO-30": {}, "DO-31": {},
"DZ-01": {}, "DZ-02": {}, "DZ-03": {}, "DZ-04": {}, "DZ-05": {},
"DZ-06": {}, "DZ-07": {}, "DZ-08": {}, "DZ-09": {}, "DZ-10": {},
"DZ-11": {}, "DZ-12": {}, "DZ-13": {}, "DZ-14": {}, "DZ-15": {},
"DZ-16": {}, "DZ-17": {}, "DZ-18": {}, "DZ-19": {}, "DZ-20": {},
"DZ-21": {}, "DZ-22": {}, "DZ-23": {}, "DZ-24": {}, "DZ-25": {},
"DZ-26": {}, "DZ-27": {}, "DZ-28": {}, "DZ-29": {}, "DZ-30": {},
"DZ-31": {}, "DZ-32": {}, "DZ-33": {}, "DZ-34": {}, "DZ-35": {},
"DZ-36": {}, "DZ-37": {}, "DZ-38": {}, "DZ-39": {}, "DZ-40": {},
"DZ-41": {}, "DZ-42": {}, "DZ-43": {}, "DZ-44": {}, "DZ-45": {},
"DZ-46": {}, "DZ-47": {}, "DZ-48": {}, "DZ-49": {}, "DZ-51": {},
"DZ-53": {}, "DZ-55": {}, "DZ-56": {}, "DZ-57": {}, "EC-A": {}, "EC-B": {},
"EC-C": {}, "EC-D": {}, "EC-E": {}, "EC-F": {}, "EC-G": {},
"EC-H": {}, "EC-I": {}, "EC-L": {}, "EC-M": {}, "EC-N": {},
"EC-O": {}, "EC-P": {}, "EC-R": {}, "EC-S": {}, "EC-SD": {},
"EC-SE": {}, "EC-T": {}, "EC-U": {}, "EC-W": {}, "EC-X": {},
"EC-Y": {}, "EC-Z": {}, "EE-37": {}, "EE-39": {}, "EE-44": {}, "EE-45": {},
"EE-49": {}, "EE-50": {}, "EE-51": {}, "EE-52": {}, "EE-56": {}, "EE-57": {},
"EE-59": {}, "EE-60": {}, "EE-64": {}, "EE-65": {}, "EE-67": {}, "EE-68": {},
"EE-70": {}, "EE-71": {}, "EE-74": {}, "EE-78": {}, "EE-79": {}, "EE-81": {}, "EE-82": {},
"EE-84": {}, "EE-86": {}, "EE-87": {}, "EG-ALX": {}, "EG-ASN": {}, "EG-AST": {},
"EG-BA": {}, "EG-BH": {}, "EG-BNS": {}, "EG-C": {}, "EG-DK": {},
"EG-DT": {}, "EG-FYM": {}, "EG-GH": {}, "EG-GZ": {}, "EG-HU": {},
"EG-IS": {}, "EG-JS": {}, "EG-KB": {}, "EG-KFS": {}, "EG-KN": {},
"EG-LX": {}, "EG-MN": {}, "EG-MNF": {}, "EG-MT": {}, "EG-PTS": {}, "EG-SHG": {},
"EG-SHR": {}, "EG-SIN": {}, "EG-SU": {}, "EG-SUZ": {}, "EG-WAD": {},
"ER-AN": {}, "ER-DK": {}, "ER-DU": {}, "ER-GB": {}, "ER-MA": {},
"ER-SK": {}, "ES-A": {}, "ES-AB": {}, "ES-AL": {}, "ES-AN": {},
"ES-AR": {}, "ES-AS": {}, "ES-AV": {}, "ES-B": {}, "ES-BA": {},
"ES-BI": {}, "ES-BU": {}, "ES-C": {}, "ES-CA": {}, "ES-CB": {},
"ES-CC": {}, "ES-CE": {}, "ES-CL": {}, "ES-CM": {}, "ES-CN": {},
"ES-CO": {}, "ES-CR": {}, "ES-CS": {}, "ES-CT": {}, "ES-CU": {},
"ES-EX": {}, "ES-GA": {}, "ES-GC": {}, "ES-GI": {}, "ES-GR": {},
"ES-GU": {}, "ES-H": {}, "ES-HU": {}, "ES-IB": {}, "ES-J": {},
"ES-L": {}, "ES-LE": {}, "ES-LO": {}, "ES-LU": {}, "ES-M": {},
"ES-MA": {}, "ES-MC": {}, "ES-MD": {}, "ES-ML": {}, "ES-MU": {},
"ES-NA": {}, "ES-NC": {}, "ES-O": {}, "ES-OR": {}, "ES-P": {},
"ES-PM": {}, "ES-PO": {}, "ES-PV": {}, "ES-RI": {}, "ES-S": {},
"ES-SA": {}, "ES-SE": {}, "ES-SG": {}, "ES-SO": {}, "ES-SS": {},
"ES-T": {}, "ES-TE": {}, "ES-TF": {}, "ES-TO": {}, "ES-V": {},
"ES-VA": {}, "ES-VC": {}, "ES-VI": {}, "ES-Z": {}, "ES-ZA": {},
"ET-AA": {}, "ET-AF": {}, "ET-AM": {}, "ET-BE": {}, "ET-DD": {},
"ET-GA": {}, "ET-HA": {}, "ET-OR": {}, "ET-SN": {}, "ET-SO": {},
"ET-TI": {}, "FI-01": {}, "FI-02": {}, "FI-03": {}, "FI-04": {},
"FI-05": {}, "FI-06": {}, "FI-07": {}, "FI-08": {}, "FI-09": {},
"FI-10": {}, "FI-11": {}, "FI-12": {}, "FI-13": {}, "FI-14": {},
"FI-15": {}, "FI-16": {}, "FI-17": {}, "FI-18": {}, "FI-19": {},
"FJ-C": {}, "FJ-E": {}, "FJ-N": {}, "FJ-R": {}, "FJ-W": {},
"FM-KSA": {}, "FM-PNI": {}, "FM-TRK": {}, "FM-YAP": {}, "FR-01": {},
"FR-02": {}, "FR-03": {}, "FR-04": {}, "FR-05": {}, "FR-06": {},
"FR-07": {}, "FR-08": {}, "FR-09": {}, "FR-10": {}, "FR-11": {},
"FR-12": {}, "FR-13": {}, "FR-14": {}, "FR-15": {}, "FR-16": {},
"FR-17": {}, "FR-18": {}, "FR-19": {}, "FR-20R": {}, "FR-21": {}, "FR-22": {},
"FR-23": {}, "FR-24": {}, "FR-25": {}, "FR-26": {}, "FR-27": {},
"FR-28": {}, "FR-29": {}, "FR-2A": {}, "FR-2B": {}, "FR-30": {},
"FR-31": {}, "FR-32": {}, "FR-33": {}, "FR-34": {}, "FR-35": {},
"FR-36": {}, "FR-37": {}, "FR-38": {}, "FR-39": {}, "FR-40": {},
"FR-41": {}, "FR-42": {}, "FR-43": {}, "FR-44": {}, "FR-45": {},
"FR-46": {}, "FR-47": {}, "FR-48": {}, "FR-49": {}, "FR-50": {},
"FR-51": {}, "FR-52": {}, "FR-53": {}, "FR-54": {}, "FR-55": {},
"FR-56": {}, "FR-57": {}, "FR-58": {}, "FR-59": {}, "FR-60": {},
"FR-61": {}, "FR-62": {}, "FR-63": {}, "FR-64": {}, "FR-65": {},
"FR-66": {}, "FR-67": {}, "FR-68": {}, "FR-69": {}, "FR-70": {},
"FR-71": {}, "FR-72": {}, "FR-73": {}, "FR-74": {}, "FR-75": {},
"FR-76": {}, "FR-77": {}, "FR-78": {}, "FR-79": {}, "FR-80": {},
"FR-81": {}, "FR-82": {}, "FR-83": {}, "FR-84": {}, "FR-85": {},
"FR-86": {}, "FR-87": {}, "FR-88": {}, "FR-89": {}, "FR-90": {},
"FR-91": {}, "FR-92": {}, "FR-93": {}, "FR-94": {}, "FR-95": {},
"FR-ARA": {}, "FR-BFC": {}, "FR-BL": {}, "FR-BRE": {}, "FR-COR": {},
"FR-CP": {}, "FR-CVL": {}, "FR-GES": {}, "FR-GF": {}, "FR-GP": {},
"FR-GUA": {}, "FR-HDF": {}, "FR-IDF": {}, "FR-LRE": {}, "FR-MAY": {},
"FR-MF": {}, "FR-MQ": {}, "FR-NAQ": {}, "FR-NC": {}, "FR-NOR": {},
"FR-OCC": {}, "FR-PAC": {}, "FR-PDL": {}, "FR-PF": {}, "FR-PM": {},
"FR-RE": {}, "FR-TF": {}, "FR-WF": {}, "FR-YT": {}, "GA-1": {},
"GA-2": {}, "GA-3": {}, "GA-4": {}, "GA-5": {}, "GA-6": {},
"GA-7": {}, "GA-8": {}, "GA-9": {}, "GB-ABC": {}, "GB-ABD": {},
"GB-ABE": {}, "GB-AGB": {}, "GB-AGY": {}, "GB-AND": {}, "GB-ANN": {},
"GB-ANS": {}, "GB-BAS": {}, "GB-BBD": {}, "GB-BDF": {}, "GB-BDG": {},
"GB-BEN": {}, "GB-BEX": {}, "GB-BFS": {}, "GB-BGE": {}, "GB-BGW": {},
"GB-BIR": {}, "GB-BKM": {}, "GB-BMH": {}, "GB-BNE": {}, "GB-BNH": {},
"GB-BNS": {}, "GB-BOL": {}, "GB-BPL": {}, "GB-BRC": {}, "GB-BRD": {},
"GB-BRY": {}, "GB-BST": {}, "GB-BUR": {}, "GB-CAM": {}, "GB-CAY": {},
"GB-CBF": {}, "GB-CCG": {}, "GB-CGN": {}, "GB-CHE": {}, "GB-CHW": {},
"GB-CLD": {}, "GB-CLK": {}, "GB-CMA": {}, "GB-CMD": {}, "GB-CMN": {},
"GB-CON": {}, "GB-COV": {}, "GB-CRF": {}, "GB-CRY": {}, "GB-CWY": {},
"GB-DAL": {}, "GB-DBY": {}, "GB-DEN": {}, "GB-DER": {}, "GB-DEV": {},
"GB-DGY": {}, "GB-DNC": {}, "GB-DND": {}, "GB-DOR": {}, "GB-DRS": {},
"GB-DUD": {}, "GB-DUR": {}, "GB-EAL": {}, "GB-EAW": {}, "GB-EAY": {},
"GB-EDH": {}, "GB-EDU": {}, "GB-ELN": {}, "GB-ELS": {}, "GB-ENF": {},
"GB-ENG": {}, "GB-ERW": {}, "GB-ERY": {}, "GB-ESS": {}, "GB-ESX": {},
"GB-FAL": {}, "GB-FIF": {}, "GB-FLN": {}, "GB-FMO": {}, "GB-GAT": {},
"GB-GBN": {}, "GB-GLG": {}, "GB-GLS": {}, "GB-GRE": {}, "GB-GWN": {},
"GB-HAL": {}, "GB-HAM": {}, "GB-HAV": {}, "GB-HCK": {}, "GB-HEF": {},
"GB-HIL": {}, "GB-HLD": {}, "GB-HMF": {}, "GB-HNS": {}, "GB-HPL": {},
"GB-HRT": {}, "GB-HRW": {}, "GB-HRY": {}, "GB-IOS": {}, "GB-IOW": {},
"GB-ISL": {}, "GB-IVC": {}, "GB-KEC": {}, "GB-KEN": {}, "GB-KHL": {},
"GB-KIR": {}, "GB-KTT": {}, "GB-KWL": {}, "GB-LAN": {}, "GB-LBC": {},
"GB-LBH": {}, "GB-LCE": {}, "GB-LDS": {}, "GB-LEC": {}, "GB-LEW": {},
"GB-LIN": {}, "GB-LIV": {}, "GB-LND": {}, "GB-LUT": {}, "GB-MAN": {},
"GB-MDB": {}, "GB-MDW": {}, "GB-MEA": {}, "GB-MIK": {}, "GD-01": {},
"GB-MLN": {}, "GB-MON": {}, "GB-MRT": {}, "GB-MRY": {}, "GB-MTY": {},
"GB-MUL": {}, "GB-NAY": {}, "GB-NBL": {}, "GB-NEL": {}, "GB-NET": {},
"GB-NFK": {}, "GB-NGM": {}, "GB-NIR": {}, "GB-NLK": {}, "GB-NLN": {},
"GB-NMD": {}, "GB-NSM": {}, "GB-NTH": {}, "GB-NTL": {}, "GB-NTT": {},
"GB-NTY": {}, "GB-NWM": {}, "GB-NWP": {}, "GB-NYK": {}, "GB-OLD": {},
"GB-ORK": {}, "GB-OXF": {}, "GB-PEM": {}, "GB-PKN": {}, "GB-PLY": {},
"GB-POL": {}, "GB-POR": {}, "GB-POW": {}, "GB-PTE": {}, "GB-RCC": {},
"GB-RCH": {}, "GB-RCT": {}, "GB-RDB": {}, "GB-RDG": {}, "GB-RFW": {},
"GB-RIC": {}, "GB-ROT": {}, "GB-RUT": {}, "GB-SAW": {}, "GB-SAY": {},
"GB-SCB": {}, "GB-SCT": {}, "GB-SFK": {}, "GB-SFT": {}, "GB-SGC": {},
"GB-SHF": {}, "GB-SHN": {}, "GB-SHR": {}, "GB-SKP": {}, "GB-SLF": {},
"GB-SLG": {}, "GB-SLK": {}, "GB-SND": {}, "GB-SOL": {}, "GB-SOM": {},
"GB-SOS": {}, "GB-SRY": {}, "GB-STE": {}, "GB-STG": {}, "GB-STH": {},
"GB-STN": {}, "GB-STS": {}, "GB-STT": {}, "GB-STY": {}, "GB-SWA": {},
"GB-SWD": {}, "GB-SWK": {}, "GB-TAM": {}, "GB-TFW": {}, "GB-THR": {},
"GB-TOB": {}, "GB-TOF": {}, "GB-TRF": {}, "GB-TWH": {}, "GB-UKM": {},
"GB-VGL": {}, "GB-WAR": {}, "GB-WBK": {}, "GB-WDU": {}, "GB-WFT": {},
"GB-WGN": {}, "GB-WIL": {}, "GB-WKF": {}, "GB-WLL": {}, "GB-WLN": {},
"GB-WLS": {}, "GB-WLV": {}, "GB-WND": {}, "GB-WNM": {}, "GB-WOK": {},
"GB-WOR": {}, "GB-WRL": {}, "GB-WRT": {}, "GB-WRX": {}, "GB-WSM": {},
"GB-WSX": {}, "GB-YOR": {}, "GB-ZET": {}, "GD-02": {}, "GD-03": {},
"GD-04": {}, "GD-05": {}, "GD-06": {}, "GD-10": {}, "GE-AB": {},
"GE-AJ": {}, "GE-GU": {}, "GE-IM": {}, "GE-KA": {}, "GE-KK": {},
"GE-MM": {}, "GE-RL": {}, "GE-SJ": {}, "GE-SK": {}, "GE-SZ": {},
"GE-TB": {}, "GH-AA": {}, "GH-AH": {}, "GH-AF": {}, "GH-BA": {}, "GH-BO": {}, "GH-BE": {}, "GH-CP": {},
"GH-EP": {}, "GH-NP": {}, "GH-TV": {}, "GH-UE": {}, "GH-UW": {},
"GH-WP": {}, "GL-AV": {}, "GL-KU": {}, "GL-QA": {}, "GL-QT": {}, "GL-QE": {}, "GL-SM": {},
"GM-B": {}, "GM-L": {}, "GM-M": {}, "GM-N": {}, "GM-U": {},
"GM-W": {}, "GN-B": {}, "GN-BE": {}, "GN-BF": {}, "GN-BK": {},
"GN-C": {}, "GN-CO": {}, "GN-D": {}, "GN-DB": {}, "GN-DI": {},
"GN-DL": {}, "GN-DU": {}, "GN-F": {}, "GN-FA": {}, "GN-FO": {},
"GN-FR": {}, "GN-GA": {}, "GN-GU": {}, "GN-K": {}, "GN-KA": {},
"GN-KB": {}, "GN-KD": {}, "GN-KE": {}, "GN-KN": {}, "GN-KO": {},
"GN-KS": {}, "GN-L": {}, "GN-LA": {}, "GN-LE": {}, "GN-LO": {},
"GN-M": {}, "GN-MC": {}, "GN-MD": {}, "GN-ML": {}, "GN-MM": {},
"GN-N": {}, "GN-NZ": {}, "GN-PI": {}, "GN-SI": {}, "GN-TE": {},
"GN-TO": {}, "GN-YO": {}, "GQ-AN": {}, "GQ-BN": {}, "GQ-BS": {},
"GQ-C": {}, "GQ-CS": {}, "GQ-I": {}, "GQ-KN": {}, "GQ-LI": {},
"GQ-WN": {}, "GR-01": {}, "GR-03": {}, "GR-04": {}, "GR-05": {},
"GR-06": {}, "GR-07": {}, "GR-11": {}, "GR-12": {}, "GR-13": {},
"GR-14": {}, "GR-15": {}, "GR-16": {}, "GR-17": {}, "GR-21": {},
"GR-22": {}, "GR-23": {}, "GR-24": {}, "GR-31": {}, "GR-32": {},
"GR-33": {}, "GR-34": {}, "GR-41": {}, "GR-42": {}, "GR-43": {},
"GR-44": {}, "GR-51": {}, "GR-52": {}, "GR-53": {}, "GR-54": {},
"GR-55": {}, "GR-56": {}, "GR-57": {}, "GR-58": {}, "GR-59": {},
"GR-61": {}, "GR-62": {}, "GR-63": {}, "GR-64": {}, "GR-69": {},
"GR-71": {}, "GR-72": {}, "GR-73": {}, "GR-81": {}, "GR-82": {},
"GR-83": {}, "GR-84": {}, "GR-85": {}, "GR-91": {}, "GR-92": {},
"GR-93": {}, "GR-94": {}, "GR-A": {}, "GR-A1": {}, "GR-B": {},
"GR-C": {}, "GR-D": {}, "GR-E": {}, "GR-F": {}, "GR-G": {},
"GR-H": {}, "GR-I": {}, "GR-J": {}, "GR-K": {}, "GR-L": {},
"GR-M": {}, "GT-01": {}, "GT-02": {}, "GT-03": {}, "GT-04": {},
"GT-05": {}, "GT-06": {}, "GT-07": {}, "GT-08": {}, "GT-09": {},
"GT-10": {}, "GT-11": {}, "GT-12": {}, "GT-13": {}, "GT-14": {},
"GT-15": {}, "GT-16": {}, "GT-17": {}, "GT-18": {}, "GT-19": {},
"GT-20": {}, "GT-21": {}, "GT-22": {}, "GW-BA": {}, "GW-BL": {},
"GW-BM": {}, "GW-BS": {}, "GW-CA": {}, "GW-GA": {}, "GW-L": {},
"GW-N": {}, "GW-OI": {}, "GW-QU": {}, "GW-S": {}, "GW-TO": {},
"GY-BA": {}, "GY-CU": {}, "GY-DE": {}, "GY-EB": {}, "GY-ES": {},
"GY-MA": {}, "GY-PM": {}, "GY-PT": {}, "GY-UD": {}, "GY-UT": {},
"HN-AT": {}, "HN-CH": {}, "HN-CL": {}, "HN-CM": {}, "HN-CP": {},
"HN-CR": {}, "HN-EP": {}, "HN-FM": {}, "HN-GD": {}, "HN-IB": {},
"HN-IN": {}, "HN-LE": {}, "HN-LP": {}, "HN-OC": {}, "HN-OL": {},
"HN-SB": {}, "HN-VA": {}, "HN-YO": {}, "HR-01": {}, "HR-02": {},
"HR-03": {}, "HR-04": {}, "HR-05": {}, "HR-06": {}, "HR-07": {},
"HR-08": {}, "HR-09": {}, "HR-10": {}, "HR-11": {}, "HR-12": {},
"HR-13": {}, "HR-14": {}, "HR-15": {}, "HR-16": {}, "HR-17": {},
"HR-18": {}, "HR-19": {}, "HR-20": {}, "HR-21": {}, "HT-AR": {},
"HT-CE": {}, "HT-GA": {}, "HT-ND": {}, "HT-NE": {}, "HT-NO": {}, "HT-NI": {},
"HT-OU": {}, "HT-SD": {}, "HT-SE": {}, "HU-BA": {}, "HU-BC": {},
"HU-BE": {}, "HU-BK": {}, "HU-BU": {}, "HU-BZ": {}, "HU-CS": {},
"HU-DE": {}, "HU-DU": {}, "HU-EG": {}, "HU-ER": {}, "HU-FE": {},
"HU-GS": {}, "HU-GY": {}, "HU-HB": {}, "HU-HE": {}, "HU-HV": {},
"HU-JN": {}, "HU-KE": {}, "HU-KM": {}, "HU-KV": {}, "HU-MI": {},
"HU-NK": {}, "HU-NO": {}, "HU-NY": {}, "HU-PE": {}, "HU-PS": {},
"HU-SD": {}, "HU-SF": {}, "HU-SH": {}, "HU-SK": {}, "HU-SN": {},
"HU-SO": {}, "HU-SS": {}, "HU-ST": {}, "HU-SZ": {}, "HU-TB": {},
"HU-TO": {}, "HU-VA": {}, "HU-VE": {}, "HU-VM": {}, "HU-ZA": {},
"HU-ZE": {}, "ID-AC": {}, "ID-BA": {}, "ID-BB": {}, "ID-BE": {},
"ID-BT": {}, "ID-GO": {}, "ID-IJ": {}, "ID-JA": {}, "ID-JB": {},
"ID-JI": {}, "ID-JK": {}, "ID-JT": {}, "ID-JW": {}, "ID-KA": {},
"ID-KB": {}, "ID-KI": {}, "ID-KU": {}, "ID-KR": {}, "ID-KS": {},
"ID-KT": {}, "ID-LA": {}, "ID-MA": {}, "ID-ML": {}, "ID-MU": {},
"ID-NB": {}, "ID-NT": {}, "ID-NU": {}, "ID-PA": {}, "ID-PB": {},
"ID-PD": {}, "ID-PE": {}, "ID-PP": {}, "ID-PS": {}, "ID-PT": {}, "ID-RI": {},
"ID-SA": {}, "ID-SB": {}, "ID-SG": {}, "ID-SL": {}, "ID-SM": {},
"ID-SN": {}, "ID-SR": {}, "ID-SS": {}, "ID-ST": {}, "ID-SU": {},
"ID-YO": {}, "IE-C": {}, "IE-CE": {}, "IE-CN": {}, "IE-CO": {},
"IE-CW": {}, "IE-D": {}, "IE-DL": {}, "IE-G": {}, "IE-KE": {},
"IE-KK": {}, "IE-KY": {}, "IE-L": {}, "IE-LD": {}, "IE-LH": {},
"IE-LK": {}, "IE-LM": {}, "IE-LS": {}, "IE-M": {}, "IE-MH": {},
"IE-MN": {}, "IE-MO": {}, "IE-OY": {}, "IE-RN": {}, "IE-SO": {},
"IE-TA": {}, "IE-U": {}, "IE-WD": {}, "IE-WH": {}, "IE-WW": {},
"IE-WX": {}, "IL-D": {}, "IL-HA": {}, "IL-JM": {}, "IL-M": {},
"IL-TA": {}, "IL-Z": {}, "IN-AN": {}, "IN-AP": {}, "IN-AR": {},
"IN-AS": {}, "IN-BR": {}, "IN-CH": {}, "IN-CT": {}, "IN-DH": {},
"IN-DL": {}, "IN-DN": {}, "IN-GA": {}, "IN-GJ": {}, "IN-HP": {},
"IN-HR": {}, "IN-JH": {}, "IN-JK": {}, "IN-KA": {}, "IN-KL": {},
"IN-LA": {}, "IN-LD": {}, "IN-MH": {}, "IN-ML": {}, "IN-MN": {}, "IN-MP": {},
"IN-MZ": {}, "IN-NL": {}, "IN-TG": {}, "IN-OR": {}, "IN-PB": {}, "IN-PY": {},
"IN-RJ": {}, "IN-SK": {}, "IN-TN": {}, "IN-TR": {}, "IN-UP": {},
"IN-UT": {}, "IN-WB": {}, "IQ-AN": {}, "IQ-AR": {}, "IQ-BA": {},
"IQ-BB": {}, "IQ-BG": {}, "IQ-DA": {}, "IQ-DI": {}, "IQ-DQ": {},
"IQ-KA": {}, "IQ-KI": {}, "IQ-MA": {}, "IQ-MU": {}, "IQ-NA": {}, "IQ-NI": {},
"IQ-QA": {}, "IQ-SD": {}, "IQ-SW": {}, "IQ-SU": {}, "IQ-TS": {}, "IQ-WA": {},
"IR-00": {}, "IR-01": {}, "IR-02": {}, "IR-03": {}, "IR-04": {}, "IR-05": {},
"IR-06": {}, "IR-07": {}, "IR-08": {}, "IR-09": {}, "IR-10": {}, "IR-11": {},
"IR-12": {}, "IR-13": {}, "IR-14": {}, "IR-15": {}, "IR-16": {},
"IR-17": {}, "IR-18": {}, "IR-19": {}, "IR-20": {}, "IR-21": {},
"IR-22": {}, "IR-23": {}, "IR-24": {}, "IR-25": {}, "IR-26": {},
"IR-27": {}, "IR-28": {}, "IR-29": {}, "IR-30": {}, "IR-31": {},
"IS-0": {}, "IS-1": {}, "IS-2": {}, "IS-3": {}, "IS-4": {},
"IS-5": {}, "IS-6": {}, "IS-7": {}, "IS-8": {}, "IT-21": {},
"IT-23": {}, "IT-25": {}, "IT-32": {}, "IT-34": {}, "IT-36": {},
"IT-42": {}, "IT-45": {}, "IT-52": {}, "IT-55": {}, "IT-57": {},
"IT-62": {}, "IT-65": {}, "IT-67": {}, "IT-72": {}, "IT-75": {},
"IT-77": {}, "IT-78": {}, "IT-82": {}, "IT-88": {}, "IT-AG": {},
"IT-AL": {}, "IT-AN": {}, "IT-AO": {}, "IT-AP": {}, "IT-AQ": {},
"IT-AR": {}, "IT-AT": {}, "IT-AV": {}, "IT-BA": {}, "IT-BG": {},
"IT-BI": {}, "IT-BL": {}, "IT-BN": {}, "IT-BO": {}, "IT-BR": {},
"IT-BS": {}, "IT-BT": {}, "IT-BZ": {}, "IT-CA": {}, "IT-CB": {},
"IT-CE": {}, "IT-CH": {}, "IT-CI": {}, "IT-CL": {}, "IT-CN": {},
"IT-CO": {}, "IT-CR": {}, "IT-CS": {}, "IT-CT": {}, "IT-CZ": {},
"IT-EN": {}, "IT-FC": {}, "IT-FE": {}, "IT-FG": {}, "IT-FI": {},
"IT-FM": {}, "IT-FR": {}, "IT-GE": {}, "IT-GO": {}, "IT-GR": {},
"IT-IM": {}, "IT-IS": {}, "IT-KR": {}, "IT-LC": {}, "IT-LE": {},
"IT-LI": {}, "IT-LO": {}, "IT-LT": {}, "IT-LU": {}, "IT-MB": {},
"IT-MC": {}, "IT-ME": {}, "IT-MI": {}, "IT-MN": {}, "IT-MO": {},
"IT-MS": {}, "IT-MT": {}, "IT-NA": {}, "IT-NO": {}, "IT-NU": {},
"IT-OG": {}, "IT-OR": {}, "IT-OT": {}, "IT-PA": {}, "IT-PC": {},
"IT-PD": {}, "IT-PE": {}, "IT-PG": {}, "IT-PI": {}, "IT-PN": {},
"IT-PO": {}, "IT-PR": {}, "IT-PT": {}, "IT-PU": {}, "IT-PV": {},
"IT-PZ": {}, "IT-RA": {}, "IT-RC": {}, "IT-RE": {}, "IT-RG": {},
"IT-RI": {}, "IT-RM": {}, "IT-RN": {}, "IT-RO": {}, "IT-SA": {},
"IT-SI": {}, "IT-SO": {}, "IT-SP": {}, "IT-SR": {}, "IT-SS": {},
"IT-SV": {}, "IT-TA": {}, "IT-TE": {}, "IT-TN": {}, "IT-TO": {},
"IT-TP": {}, "IT-TR": {}, "IT-TS": {}, "IT-TV": {}, "IT-UD": {},
"IT-VA": {}, "IT-VB": {}, "IT-VC": {}, "IT-VE": {}, "IT-VI": {},
"IT-VR": {}, "IT-VS": {}, "IT-VT": {}, "IT-VV": {}, "JM-01": {},
"JM-02": {}, "JM-03": {}, "JM-04": {}, "JM-05": {}, "JM-06": {},
"JM-07": {}, "JM-08": {}, "JM-09": {}, "JM-10": {}, "JM-11": {},
"JM-12": {}, "JM-13": {}, "JM-14": {}, "JO-AJ": {}, "JO-AM": {},
"JO-AQ": {}, "JO-AT": {}, "JO-AZ": {}, "JO-BA": {}, "JO-IR": {},
"JO-JA": {}, "JO-KA": {}, "JO-MA": {}, "JO-MD": {}, "JO-MN": {},
"JP-01": {}, "JP-02": {}, "JP-03": {}, "JP-04": {}, "JP-05": {},
"JP-06": {}, "JP-07": {}, "JP-08": {}, "JP-09": {}, "JP-10": {},
"JP-11": {}, "JP-12": {}, "JP-13": {}, "JP-14": {}, "JP-15": {},
"JP-16": {}, "JP-17": {}, "JP-18": {}, "JP-19": {}, "JP-20": {},
"JP-21": {}, "JP-22": {}, "JP-23": {}, "JP-24": {}, "JP-25": {},
"JP-26": {}, "JP-27": {}, "JP-28": {}, "JP-29": {}, "JP-30": {},
"JP-31": {}, "JP-32": {}, "JP-33": {}, "JP-34": {}, "JP-35": {},
"JP-36": {}, "JP-37": {}, "JP-38": {}, "JP-39": {}, "JP-40": {},
"JP-41": {}, "JP-42": {}, "JP-43": {}, "JP-44": {}, "JP-45": {},
"JP-46": {}, "JP-47": {}, "KE-01": {}, "KE-02": {}, "KE-03": {},
"KE-04": {}, "KE-05": {}, "KE-06": {}, "KE-07": {}, "KE-08": {},
"KE-09": {}, "KE-10": {}, "KE-11": {}, "KE-12": {}, "KE-13": {},
"KE-14": {}, "KE-15": {}, "KE-16": {}, "KE-17": {}, "KE-18": {},
"KE-19": {}, "KE-20": {}, "KE-21": {}, "KE-22": {}, "KE-23": {},
"KE-24": {}, "KE-25": {}, "KE-26": {}, "KE-27": {}, "KE-28": {},
"KE-29": {}, "KE-30": {}, "KE-31": {}, "KE-32": {}, "KE-33": {},
"KE-34": {}, "KE-35": {}, "KE-36": {}, "KE-37": {}, "KE-38": {},
"KE-39": {}, "KE-40": {}, "KE-41": {}, "KE-42": {}, "KE-43": {},
"KE-44": {}, "KE-45": {}, "KE-46": {}, "KE-47": {}, "KG-B": {},
"KG-C": {}, "KG-GB": {}, "KG-GO": {}, "KG-J": {}, "KG-N": {}, "KG-O": {},
"KG-T": {}, "KG-Y": {}, "KH-1": {}, "KH-10": {}, "KH-11": {},
"KH-12": {}, "KH-13": {}, "KH-14": {}, "KH-15": {}, "KH-16": {},
"KH-17": {}, "KH-18": {}, "KH-19": {}, "KH-2": {}, "KH-20": {},
"KH-21": {}, "KH-22": {}, "KH-23": {}, "KH-24": {}, "KH-3": {},
"KH-4": {}, "KH-5": {}, "KH-6": {}, "KH-7": {}, "KH-8": {},
"KH-9": {}, "KI-G": {}, "KI-L": {}, "KI-P": {}, "KM-A": {},
"KM-G": {}, "KM-M": {}, "KN-01": {}, "KN-02": {}, "KN-03": {},
"KN-04": {}, "KN-05": {}, "KN-06": {}, "KN-07": {}, "KN-08": {},
"KN-09": {}, "KN-10": {}, "KN-11": {}, "KN-12": {}, "KN-13": {},
"KN-15": {}, "KN-K": {}, "KN-N": {}, "KP-01": {}, "KP-02": {},
"KP-03": {}, "KP-04": {}, "KP-05": {}, "KP-06": {}, "KP-07": {},
"KP-08": {}, "KP-09": {}, "KP-10": {}, "KP-13": {}, "KR-11": {},
"KR-26": {}, "KR-27": {}, "KR-28": {}, "KR-29": {}, "KR-30": {},
"KR-31": {}, "KR-41": {}, "KR-42": {}, "KR-43": {}, "KR-44": {},
"KR-45": {}, "KR-46": {}, "KR-47": {}, "KR-48": {}, "KR-49": {}, "KR-50": {},
"KW-AH": {}, "KW-FA": {}, "KW-HA": {}, "KW-JA": {}, "KW-KU": {},
"KW-MU": {}, "KZ-10": {}, "KZ-75": {}, "KZ-19": {}, "KZ-11": {},
"KZ-15": {}, "KZ-71": {}, "KZ-23": {}, "KZ-27": {}, "KZ-47": {},
"KZ-55": {}, "KZ-35": {}, "KZ-39": {}, "KZ-43": {}, "KZ-63": {},
"KZ-79": {}, "KZ-59": {}, "KZ-61": {}, "KZ-62": {}, "KZ-31": {},
"KZ-33": {}, "LA-AT": {}, "LA-BK": {}, "LA-BL": {},
"LA-CH": {}, "LA-HO": {}, "LA-KH": {}, "LA-LM": {}, "LA-LP": {},
"LA-OU": {}, "LA-PH": {}, "LA-SL": {}, "LA-SV": {}, "LA-VI": {},
"LA-VT": {}, "LA-XA": {}, "LA-XE": {}, "LA-XI": {}, "LA-XS": {},
"LB-AK": {}, "LB-AS": {}, "LB-BA": {}, "LB-BH": {}, "LB-BI": {},
"LB-JA": {}, "LB-JL": {}, "LB-NA": {}, "LC-01": {}, "LC-02": {},
"LC-03": {}, "LC-05": {}, "LC-06": {}, "LC-07": {}, "LC-08": {},
"LC-10": {}, "LC-11": {}, "LI-01": {}, "LI-02": {},
"LI-03": {}, "LI-04": {}, "LI-05": {}, "LI-06": {}, "LI-07": {},
"LI-08": {}, "LI-09": {}, "LI-10": {}, "LI-11": {}, "LK-1": {},
"LK-11": {}, "LK-12": {}, "LK-13": {}, "LK-2": {}, "LK-21": {},
"LK-22": {}, "LK-23": {}, "LK-3": {}, "LK-31": {}, "LK-32": {},
"LK-33": {}, "LK-4": {}, "LK-41": {}, "LK-42": {}, "LK-43": {},
"LK-44": {}, "LK-45": {}, "LK-5": {}, "LK-51": {}, "LK-52": {},
"LK-53": {}, "LK-6": {}, "LK-61": {}, "LK-62": {}, "LK-7": {},
"LK-71": {}, "LK-72": {}, "LK-8": {}, "LK-81": {}, "LK-82": {},
"LK-9": {}, "LK-91": {}, "LK-92": {}, "LR-BG": {}, "LR-BM": {},
"LR-CM": {}, "LR-GB": {}, "LR-GG": {}, "LR-GK": {}, "LR-LO": {},
"LR-MG": {}, "LR-MO": {}, "LR-MY": {}, "LR-NI": {}, "LR-RI": {},
"LR-SI": {}, "LS-A": {}, "LS-B": {}, "LS-C": {}, "LS-D": {},
"LS-E": {}, "LS-F": {}, "LS-G": {}, "LS-H": {}, "LS-J": {},
"LS-K": {}, "LT-AL": {}, "LT-KL": {}, "LT-KU": {}, "LT-MR": {},
"LT-PN": {}, "LT-SA": {}, "LT-TA": {}, "LT-TE": {}, "LT-UT": {},
"LT-VL": {}, "LU-CA": {}, "LU-CL": {}, "LU-DI": {}, "LU-EC": {},
"LU-ES": {}, "LU-GR": {}, "LU-LU": {}, "LU-ME": {}, "LU-RD": {},
"LU-RM": {}, "LU-VD": {}, "LU-WI": {}, "LU-D": {}, "LU-G": {}, "LU-L": {},
"LV-001": {}, "LV-111": {}, "LV-112": {}, "LV-113": {},
"LV-002": {}, "LV-003": {}, "LV-004": {}, "LV-005": {}, "LV-006": {},
"LV-007": {}, "LV-008": {}, "LV-009": {}, "LV-010": {}, "LV-011": {},
"LV-012": {}, "LV-013": {}, "LV-014": {}, "LV-015": {}, "LV-016": {},
"LV-017": {}, "LV-018": {}, "LV-019": {}, "LV-020": {}, "LV-021": {},
"LV-022": {}, "LV-023": {}, "LV-024": {}, "LV-025": {}, "LV-026": {},
"LV-027": {}, "LV-028": {}, "LV-029": {}, "LV-030": {}, "LV-031": {},
"LV-032": {}, "LV-033": {}, "LV-034": {}, "LV-035": {}, "LV-036": {},
"LV-037": {}, "LV-038": {}, "LV-039": {}, "LV-040": {}, "LV-041": {},
"LV-042": {}, "LV-043": {}, "LV-044": {}, "LV-045": {}, "LV-046": {},
"LV-047": {}, "LV-048": {}, "LV-049": {}, "LV-050": {}, "LV-051": {},
"LV-052": {}, "LV-053": {}, "LV-054": {}, "LV-055": {}, "LV-056": {},
"LV-057": {}, "LV-058": {}, "LV-059": {}, "LV-060": {}, "LV-061": {},
"LV-062": {}, "LV-063": {}, "LV-064": {}, "LV-065": {}, "LV-066": {},
"LV-067": {}, "LV-068": {}, "LV-069": {}, "LV-070": {}, "LV-071": {},
"LV-072": {}, "LV-073": {}, "LV-074": {}, "LV-075": {}, "LV-076": {},
"LV-077": {}, "LV-078": {}, "LV-079": {}, "LV-080": {}, "LV-081": {},
"LV-082": {}, "LV-083": {}, "LV-084": {}, "LV-085": {}, "LV-086": {},
"LV-087": {}, "LV-088": {}, "LV-089": {}, "LV-090": {}, "LV-091": {},
"LV-092": {}, "LV-093": {}, "LV-094": {}, "LV-095": {}, "LV-096": {},
"LV-097": {}, "LV-098": {}, "LV-099": {}, "LV-100": {}, "LV-101": {},
"LV-102": {}, "LV-103": {}, "LV-104": {}, "LV-105": {}, "LV-106": {},
"LV-107": {}, "LV-108": {}, "LV-109": {}, "LV-110": {}, "LV-DGV": {},
"LV-JEL": {}, "LV-JKB": {}, "LV-JUR": {}, "LV-LPX": {}, "LV-REZ": {},
"LV-RIX": {}, "LV-VEN": {}, "LV-VMR": {}, "LY-BA": {}, "LY-BU": {},
"LY-DR": {}, "LY-GT": {}, "LY-JA": {}, "LY-JB": {}, "LY-JG": {},
"LY-JI": {}, "LY-JU": {}, "LY-KF": {}, "LY-MB": {}, "LY-MI": {},
"LY-MJ": {}, "LY-MQ": {}, "LY-NL": {}, "LY-NQ": {}, "LY-SB": {},
"LY-SR": {}, "LY-TB": {}, "LY-WA": {}, "LY-WD": {}, "LY-WS": {},
"LY-ZA": {}, "MA-01": {}, "MA-02": {}, "MA-03": {}, "MA-04": {},
"MA-05": {}, "MA-06": {}, "MA-07": {}, "MA-08": {}, "MA-09": {},
"MA-10": {}, "MA-11": {}, "MA-12": {}, "MA-13": {}, "MA-14": {},
"MA-15": {}, "MA-16": {}, "MA-AGD": {}, "MA-AOU": {}, "MA-ASZ": {},
"MA-AZI": {}, "MA-BEM": {}, "MA-BER": {}, "MA-BES": {}, "MA-BOD": {},
"MA-BOM": {}, "MA-CAS": {}, "MA-CHE": {}, "MA-CHI": {}, "MA-CHT": {},
"MA-ERR": {}, "MA-ESI": {}, "MA-ESM": {}, "MA-FAH": {}, "MA-FES": {},
"MA-FIG": {}, "MA-GUE": {}, "MA-HAJ": {}, "MA-HAO": {}, "MA-HOC": {},
"MA-IFR": {}, "MA-INE": {}, "MA-JDI": {}, "MA-JRA": {}, "MA-KEN": {},
"MA-KES": {}, "MA-KHE": {}, "MA-KHN": {}, "MA-KHO": {}, "MA-LAA": {},
"MA-LAR": {}, "MA-MED": {}, "MA-MEK": {}, "MA-MMD": {}, "MA-MMN": {},
"MA-MOH": {}, "MA-MOU": {}, "MA-NAD": {}, "MA-NOU": {}, "MA-OUA": {},
"MA-OUD": {}, "MA-OUJ": {}, "MA-RAB": {}, "MA-SAF": {}, "MA-SAL": {},
"MA-SEF": {}, "MA-SET": {}, "MA-SIK": {}, "MA-SKH": {}, "MA-SYB": {},
"MA-TAI": {}, "MA-TAO": {}, "MA-TAR": {}, "MA-TAT": {}, "MA-TAZ": {},
"MA-TET": {}, "MA-TIZ": {}, "MA-TNG": {}, "MA-TNT": {}, "MA-ZAG": {},
"MC-CL": {}, "MC-CO": {}, "MC-FO": {}, "MC-GA": {}, "MC-JE": {},
"MC-LA": {}, "MC-MA": {}, "MC-MC": {}, "MC-MG": {}, "MC-MO": {},
"MC-MU": {}, "MC-PH": {}, "MC-SD": {}, "MC-SO": {}, "MC-SP": {},
"MC-SR": {}, "MC-VR": {}, "MD-AN": {}, "MD-BA": {}, "MD-BD": {},
"MD-BR": {}, "MD-BS": {}, "MD-CA": {}, "MD-CL": {}, "MD-CM": {},
"MD-CR": {}, "MD-CS": {}, "MD-CT": {}, "MD-CU": {}, "MD-DO": {},
"MD-DR": {}, "MD-DU": {}, "MD-ED": {}, "MD-FA": {}, "MD-FL": {},
"MD-GA": {}, "MD-GL": {}, "MD-HI": {}, "MD-IA": {}, "MD-LE": {},
"MD-NI": {}, "MD-OC": {}, "MD-OR": {}, "MD-RE": {}, "MD-RI": {},
"MD-SD": {}, "MD-SI": {}, "MD-SN": {}, "MD-SO": {}, "MD-ST": {},
"MD-SV": {}, "MD-TA": {}, "MD-TE": {}, "MD-UN": {}, "ME-01": {},
"ME-02": {}, "ME-03": {}, "ME-04": {}, "ME-05": {}, "ME-06": {},
"ME-07": {}, "ME-08": {}, "ME-09": {}, "ME-10": {}, "ME-11": {},
"ME-12": {}, "ME-13": {}, "ME-14": {}, "ME-15": {}, "ME-16": {},
"ME-17": {}, "ME-18": {}, "ME-19": {}, "ME-20": {}, "ME-21": {}, "ME-22": {}, "ME-23": {}, "ME-24": {}, "ME-25": {},
"MG-A": {}, "MG-D": {}, "MG-F": {}, "MG-M": {}, "MG-T": {},
"MG-U": {}, "MH-ALK": {}, "MH-ALL": {}, "MH-ARN": {}, "MH-AUR": {},
"MH-EBO": {}, "MH-ENI": {}, "MH-JAB": {}, "MH-JAL": {}, "MH-KIL": {},
"MH-KWA": {}, "MH-L": {}, "MH-LAE": {}, "MH-LIB": {}, "MH-LIK": {},
"MH-MAJ": {}, "MH-MAL": {}, "MH-MEJ": {}, "MH-MIL": {}, "MH-NMK": {},
"MH-NMU": {}, "MH-RON": {}, "MH-T": {}, "MH-UJA": {}, "MH-UTI": {},
"MH-WTJ": {}, "MH-WTN": {}, "MK-101": {}, "MK-102": {}, "MK-103": {},
"MK-104": {}, "MK-105": {},
"MK-106": {}, "MK-107": {}, "MK-108": {}, "MK-109": {}, "MK-201": {},
"MK-202": {}, "MK-205": {}, "MK-206": {}, "MK-207": {}, "MK-208": {},
"MK-209": {}, "MK-210": {}, "MK-211": {}, "MK-301": {}, "MK-303": {},
"MK-307": {}, "MK-308": {}, "MK-310": {}, "MK-311": {}, "MK-312": {},
"MK-401": {}, "MK-402": {}, "MK-403": {}, "MK-404": {}, "MK-405": {},
"MK-406": {}, "MK-408": {}, "MK-409": {}, "MK-410": {}, "MK-501": {},
"MK-502": {}, "MK-503": {}, "MK-505": {}, "MK-506": {}, "MK-507": {},
"MK-508": {}, "MK-509": {}, "MK-601": {}, "MK-602": {}, "MK-604": {},
"MK-605": {}, "MK-606": {}, "MK-607": {}, "MK-608": {}, "MK-609": {},
"MK-701": {}, "MK-702": {}, "MK-703": {}, "MK-704": {}, "MK-705": {},
"MK-803": {}, "MK-804": {}, "MK-806": {}, "MK-807": {}, "MK-809": {},
"MK-810": {}, "MK-811": {}, "MK-812": {}, "MK-813": {}, "MK-814": {},
"MK-816": {}, "ML-1": {}, "ML-2": {}, "ML-3": {}, "ML-4": {},
"ML-5": {}, "ML-6": {}, "ML-7": {}, "ML-8": {}, "ML-BKO": {},
"MM-01": {}, "MM-02": {}, "MM-03": {}, "MM-04": {}, "MM-05": {},
"MM-06": {}, "MM-07": {}, "MM-11": {}, "MM-12": {}, "MM-13": {},
"MM-14": {}, "MM-15": {}, "MM-16": {}, "MM-17": {}, "MM-18": {}, "MN-035": {},
"MN-037": {}, "MN-039": {}, "MN-041": {}, "MN-043": {}, "MN-046": {},
"MN-047": {}, "MN-049": {}, "MN-051": {}, "MN-053": {}, "MN-055": {},
"MN-057": {}, "MN-059": {}, "MN-061": {}, "MN-063": {}, "MN-064": {},
"MN-065": {}, "MN-067": {}, "MN-069": {}, "MN-071": {}, "MN-073": {},
"MN-1": {}, "MR-01": {}, "MR-02": {}, "MR-03": {}, "MR-04": {},
"MR-05": {}, "MR-06": {}, "MR-07": {}, "MR-08": {}, "MR-09": {},
"MR-10": {}, "MR-11": {}, "MR-12": {}, "MR-13": {}, "MR-NKC": {}, "MT-01": {},
"MT-02": {}, "MT-03": {}, "MT-04": {}, "MT-05": {}, "MT-06": {},
"MT-07": {}, "MT-08": {}, "MT-09": {}, "MT-10": {}, "MT-11": {},
"MT-12": {}, "MT-13": {}, "MT-14": {}, "MT-15": {}, "MT-16": {},
"MT-17": {}, "MT-18": {}, "MT-19": {}, "MT-20": {}, "MT-21": {},
"MT-22": {}, "MT-23": {}, "MT-24": {}, "MT-25": {}, "MT-26": {},
"MT-27": {}, "MT-28": {}, "MT-29": {}, "MT-30": {}, "MT-31": {},
"MT-32": {}, "MT-33": {}, "MT-34": {}, "MT-35": {}, "MT-36": {},
"MT-37": {}, "MT-38": {}, "MT-39": {}, "MT-40": {}, "MT-41": {},
"MT-42": {}, "MT-43": {}, "MT-44": {}, "MT-45": {}, "MT-46": {},
"MT-47": {}, "MT-48": {}, "MT-49": {}, "MT-50": {}, "MT-51": {},
"MT-52": {}, "MT-53": {}, "MT-54": {}, "MT-55": {}, "MT-56": {},
"MT-57": {}, "MT-58": {}, "MT-59": {}, "MT-60": {}, "MT-61": {},
"MT-62": {}, "MT-63": {}, "MT-64": {}, "MT-65": {}, "MT-66": {},
"MT-67": {}, "MT-68": {}, "MU-AG": {}, "MU-BL": {}, "MU-BR": {},
"MU-CC": {}, "MU-CU": {}, "MU-FL": {}, "MU-GP": {}, "MU-MO": {},
"MU-PA": {}, "MU-PL": {}, "MU-PU": {}, "MU-PW": {}, "MU-QB": {},
"MU-RO": {}, "MU-RP": {}, "MU-RR": {}, "MU-SA": {}, "MU-VP": {}, "MV-00": {},
"MV-01": {}, "MV-02": {}, "MV-03": {}, "MV-04": {}, "MV-05": {},
"MV-07": {}, "MV-08": {}, "MV-12": {}, "MV-13": {}, "MV-14": {},
"MV-17": {}, "MV-20": {}, "MV-23": {}, "MV-24": {}, "MV-25": {},
"MV-26": {}, "MV-27": {}, "MV-28": {}, "MV-29": {}, "MV-CE": {},
"MV-MLE": {}, "MV-NC": {}, "MV-NO": {}, "MV-SC": {}, "MV-SU": {},
"MV-UN": {}, "MV-US": {}, "MW-BA": {}, "MW-BL": {}, "MW-C": {},
"MW-CK": {}, "MW-CR": {}, "MW-CT": {}, "MW-DE": {}, "MW-DO": {},
"MW-KR": {}, "MW-KS": {}, "MW-LI": {}, "MW-LK": {}, "MW-MC": {},
"MW-MG": {}, "MW-MH": {}, "MW-MU": {}, "MW-MW": {}, "MW-MZ": {},
"MW-N": {}, "MW-NB": {}, "MW-NE": {}, "MW-NI": {}, "MW-NK": {},
"MW-NS": {}, "MW-NU": {}, "MW-PH": {}, "MW-RU": {}, "MW-S": {},
"MW-SA": {}, "MW-TH": {}, "MW-ZO": {}, "MX-AGU": {}, "MX-BCN": {},
"MX-BCS": {}, "MX-CAM": {}, "MX-CHH": {}, "MX-CHP": {}, "MX-COA": {},
"MX-COL": {}, "MX-CMX": {}, "MX-DIF": {}, "MX-DUR": {}, "MX-GRO": {}, "MX-GUA": {},
"MX-HID": {}, "MX-JAL": {}, "MX-MEX": {}, "MX-MIC": {}, "MX-MOR": {},
"MX-NAY": {}, "MX-NLE": {}, "MX-OAX": {}, "MX-PUE": {}, "MX-QUE": {},
"MX-ROO": {}, "MX-SIN": {}, "MX-SLP": {}, "MX-SON": {}, "MX-TAB": {},
"MX-TAM": {}, "MX-TLA": {}, "MX-VER": {}, "MX-YUC": {}, "MX-ZAC": {},
"MY-01": {}, "MY-02": {}, "MY-03": {}, "MY-04": {}, "MY-05": {},
"MY-06": {}, "MY-07": {}, "MY-08": {}, "MY-09": {}, "MY-10": {},
"MY-11": {}, "MY-12": {}, "MY-13": {}, "MY-14": {}, "MY-15": {},
"MY-16": {}, "MZ-A": {}, "MZ-B": {}, "MZ-G": {}, "MZ-I": {},
"MZ-L": {}, "MZ-MPM": {}, "MZ-N": {}, "MZ-P": {}, "MZ-Q": {},
"MZ-S": {}, "MZ-T": {}, "NA-CA": {}, "NA-ER": {}, "NA-HA": {},
"NA-KA": {}, "NA-KE": {}, "NA-KH": {}, "NA-KU": {}, "NA-KW": {}, "NA-OD": {}, "NA-OH": {},
"NA-OK": {}, "NA-ON": {}, "NA-OS": {}, "NA-OT": {}, "NA-OW": {},
"NE-1": {}, "NE-2": {}, "NE-3": {}, "NE-4": {}, "NE-5": {},
"NE-6": {}, "NE-7": {}, "NE-8": {}, "NG-AB": {}, "NG-AD": {},
"NG-AK": {}, "NG-AN": {}, "NG-BA": {}, "NG-BE": {}, "NG-BO": {},
"NG-BY": {}, "NG-CR": {}, "NG-DE": {}, "NG-EB": {}, "NG-ED": {},
"NG-EK": {}, "NG-EN": {}, "NG-FC": {}, "NG-GO": {}, "NG-IM": {},
"NG-JI": {}, "NG-KD": {}, "NG-KE": {}, "NG-KN": {}, "NG-KO": {},
"NG-KT": {}, "NG-KW": {}, "NG-LA": {}, "NG-NA": {}, "NG-NI": {},
"NG-OG": {}, "NG-ON": {}, "NG-OS": {}, "NG-OY": {}, "NG-PL": {},
"NG-RI": {}, "NG-SO": {}, "NG-TA": {}, "NG-YO": {}, "NG-ZA": {},
"NI-AN": {}, "NI-AS": {}, "NI-BO": {}, "NI-CA": {}, "NI-CI": {},
"NI-CO": {}, "NI-ES": {}, "NI-GR": {}, "NI-JI": {}, "NI-LE": {},
"NI-MD": {}, "NI-MN": {}, "NI-MS": {}, "NI-MT": {}, "NI-NS": {},
"NI-RI": {}, "NI-SJ": {}, "NL-AW": {}, "NL-BQ1": {}, "NL-BQ2": {},
"NL-BQ3": {}, "NL-CW": {}, "NL-DR": {}, "NL-FL": {}, "NL-FR": {},
"NL-GE": {}, "NL-GR": {}, "NL-LI": {}, "NL-NB": {}, "NL-NH": {},
"NL-OV": {}, "NL-SX": {}, "NL-UT": {}, "NL-ZE": {}, "NL-ZH": {},
"NO-03": {}, "NO-11": {}, "NO-15": {}, "NO-16": {}, "NO-17": {},
"NO-18": {}, "NO-21": {}, "NO-30": {}, "NO-34": {}, "NO-38": {},
"NO-42": {}, "NO-46": {}, "NO-50": {}, "NO-54": {},
"NO-22": {}, "NP-1": {}, "NP-2": {}, "NP-3": {}, "NP-4": {},
"NP-5": {}, "NP-BA": {}, "NP-BH": {}, "NP-DH": {}, "NP-GA": {},
"NP-JA": {}, "NP-KA": {}, "NP-KO": {}, "NP-LU": {}, "NP-MA": {},
"NP-ME": {}, "NP-NA": {}, "NP-P1": {}, "NP-P2": {}, "NP-P3": {}, "NP-P4": {}, "NP-P5": {}, "NP-P6": {}, "NP-P7": {}, "NP-RA": {}, "NP-SA": {}, "NP-SE": {},
"NR-01": {}, "NR-02": {}, "NR-03": {}, "NR-04": {}, "NR-05": {},
"NR-06": {}, "NR-07": {}, "NR-08": {}, "NR-09": {}, "NR-10": {},
"NR-11": {}, "NR-12": {}, "NR-13": {}, "NR-14": {}, "NZ-AUK": {},
"NZ-BOP": {}, "NZ-CAN": {}, "NZ-CIT": {}, "NZ-GIS": {}, "NZ-HKB": {},
"NZ-MBH": {}, "NZ-MWT": {}, "NZ-N": {}, "NZ-NSN": {}, "NZ-NTL": {},
"NZ-OTA": {}, "NZ-S": {}, "NZ-STL": {}, "NZ-TAS": {}, "NZ-TKI": {},
"NZ-WGN": {}, "NZ-WKO": {}, "NZ-WTC": {}, "OM-BA": {}, "OM-BS": {}, "OM-BU": {}, "OM-BJ": {},
"OM-DA": {}, "OM-MA": {}, "OM-MU": {}, "OM-SH": {}, "OM-SJ": {}, "OM-SS": {}, "OM-WU": {},
"OM-ZA": {}, "OM-ZU": {}, "PA-1": {}, "PA-2": {}, "PA-3": {},
"PA-4": {}, "PA-5": {}, "PA-6": {}, "PA-7": {}, "PA-8": {},
"PA-9": {}, "PA-EM": {}, "PA-KY": {}, "PA-NB": {}, "PE-AMA": {},
"PE-ANC": {}, "PE-APU": {}, "PE-ARE": {}, "PE-AYA": {}, "PE-CAJ": {},
"PE-CAL": {}, "PE-CUS": {}, "PE-HUC": {}, "PE-HUV": {}, "PE-ICA": {},
"PE-JUN": {}, "PE-LAL": {}, "PE-LAM": {}, "PE-LIM": {}, "PE-LMA": {},
"PE-LOR": {}, "PE-MDD": {}, "PE-MOQ": {}, "PE-PAS": {}, "PE-PIU": {},
"PE-PUN": {}, "PE-SAM": {}, "PE-TAC": {}, "PE-TUM": {}, "PE-UCA": {},
"PG-CPK": {}, "PG-CPM": {}, "PG-EBR": {}, "PG-EHG": {}, "PG-EPW": {},
"PG-ESW": {}, "PG-GPK": {}, "PG-MBA": {}, "PG-MPL": {}, "PG-MPM": {},
"PG-MRL": {}, "PG-NCD": {}, "PG-NIK": {}, "PG-NPP": {}, "PG-NSB": {},
"PG-SAN": {}, "PG-SHM": {}, "PG-WBK": {}, "PG-WHM": {}, "PG-WPD": {},
"PH-00": {}, "PH-01": {}, "PH-02": {}, "PH-03": {}, "PH-05": {},
"PH-06": {}, "PH-07": {}, "PH-08": {}, "PH-09": {}, "PH-10": {},
"PH-11": {}, "PH-12": {}, "PH-13": {}, "PH-14": {}, "PH-15": {},
"PH-40": {}, "PH-41": {}, "PH-ABR": {}, "PH-AGN": {}, "PH-AGS": {},
"PH-AKL": {}, "PH-ALB": {}, "PH-ANT": {}, "PH-APA": {}, "PH-AUR": {},
"PH-BAN": {}, "PH-BAS": {}, "PH-BEN": {}, "PH-BIL": {}, "PH-BOH": {},
"PH-BTG": {}, "PH-BTN": {}, "PH-BUK": {}, "PH-BUL": {}, "PH-CAG": {},
"PH-CAM": {}, "PH-CAN": {}, "PH-CAP": {}, "PH-CAS": {}, "PH-CAT": {},
"PH-CAV": {}, "PH-CEB": {}, "PH-COM": {}, "PH-DAO": {}, "PH-DAS": {},
"PH-DAV": {}, "PH-DIN": {}, "PH-EAS": {}, "PH-GUI": {}, "PH-IFU": {},
"PH-ILI": {}, "PH-ILN": {}, "PH-ILS": {}, "PH-ISA": {}, "PH-KAL": {},
"PH-LAG": {}, "PH-LAN": {}, "PH-LAS": {}, "PH-LEY": {}, "PH-LUN": {},
"PH-MAD": {}, "PH-MAG": {}, "PH-MAS": {}, "PH-MDC": {}, "PH-MDR": {},
"PH-MOU": {}, "PH-MSC": {}, "PH-MSR": {}, "PH-NCO": {}, "PH-NEC": {},
"PH-NER": {}, "PH-NSA": {}, "PH-NUE": {}, "PH-NUV": {}, "PH-PAM": {},
"PH-PAN": {}, "PH-PLW": {}, "PH-QUE": {}, "PH-QUI": {}, "PH-RIZ": {},
"PH-ROM": {}, "PH-SAR": {}, "PH-SCO": {}, "PH-SIG": {}, "PH-SLE": {},
"PH-SLU": {}, "PH-SOR": {}, "PH-SUK": {}, "PH-SUN": {}, "PH-SUR": {},
"PH-TAR": {}, "PH-TAW": {}, "PH-WSA": {}, "PH-ZAN": {}, "PH-ZAS": {},
"PH-ZMB": {}, "PH-ZSI": {}, "PK-BA": {}, "PK-GB": {}, "PK-IS": {},
"PK-JK": {}, "PK-KP": {}, "PK-PB": {}, "PK-SD": {}, "PK-TA": {},
"PL-02": {}, "PL-04": {}, "PL-06": {}, "PL-08": {}, "PL-10": {},
"PL-12": {}, "PL-14": {}, "PL-16": {}, "PL-18": {}, "PL-20": {},
"PL-22": {}, "PL-24": {}, "PL-26": {}, "PL-28": {}, "PL-30": {}, "PL-32": {},
"PS-BTH": {}, "PS-DEB": {}, "PS-GZA": {}, "PS-HBN": {},
"PS-JEM": {}, "PS-JEN": {}, "PS-JRH": {}, "PS-KYS": {}, "PS-NBS": {},
"PS-NGZ": {}, "PS-QQA": {}, "PS-RBH": {}, "PS-RFH": {}, "PS-SLT": {},
"PS-TBS": {}, "PS-TKM": {}, "PT-01": {}, "PT-02": {}, "PT-03": {},
"PT-04": {}, "PT-05": {}, "PT-06": {}, "PT-07": {}, "PT-08": {},
"PT-09": {}, "PT-10": {}, "PT-11": {}, "PT-12": {}, "PT-13": {},
"PT-14": {}, "PT-15": {}, "PT-16": {}, "PT-17": {}, "PT-18": {},
"PT-20": {}, "PT-30": {}, "PW-002": {}, "PW-004": {}, "PW-010": {},
"PW-050": {}, "PW-100": {}, "PW-150": {}, "PW-212": {}, "PW-214": {},
"PW-218": {}, "PW-222": {}, "PW-224": {}, "PW-226": {}, "PW-227": {},
"PW-228": {}, "PW-350": {}, "PW-370": {}, "PY-1": {}, "PY-10": {},
"PY-11": {}, "PY-12": {}, "PY-13": {}, "PY-14": {}, "PY-15": {},
"PY-16": {}, "PY-19": {}, "PY-2": {}, "PY-3": {}, "PY-4": {},
"PY-5": {}, "PY-6": {}, "PY-7": {}, "PY-8": {}, "PY-9": {},
"PY-ASU": {}, "QA-DA": {}, "QA-KH": {}, "QA-MS": {}, "QA-RA": {},
"QA-US": {}, "QA-WA": {}, "QA-ZA": {}, "RO-AB": {}, "RO-AG": {},
"RO-AR": {}, "RO-B": {}, "RO-BC": {}, "RO-BH": {}, "RO-BN": {},
"RO-BR": {}, "RO-BT": {}, "RO-BV": {}, "RO-BZ": {}, "RO-CJ": {},
"RO-CL": {}, "RO-CS": {}, "RO-CT": {}, "RO-CV": {}, "RO-DB": {},
"RO-DJ": {}, "RO-GJ": {}, "RO-GL": {}, "RO-GR": {}, "RO-HD": {},
"RO-HR": {}, "RO-IF": {}, "RO-IL": {}, "RO-IS": {}, "RO-MH": {},
"RO-MM": {}, "RO-MS": {}, "RO-NT": {}, "RO-OT": {}, "RO-PH": {},
"RO-SB": {}, "RO-SJ": {}, "RO-SM": {}, "RO-SV": {}, "RO-TL": {},
"RO-TM": {}, "RO-TR": {}, "RO-VL": {}, "RO-VN": {}, "RO-VS": {},
"RS-00": {}, "RS-01": {}, "RS-02": {}, "RS-03": {}, "RS-04": {},
"RS-05": {}, "RS-06": {}, "RS-07": {}, "RS-08": {}, "RS-09": {},
"RS-10": {}, "RS-11": {}, "RS-12": {}, "RS-13": {}, "RS-14": {},
"RS-15": {}, "RS-16": {}, "RS-17": {}, "RS-18": {}, "RS-19": {},
"RS-20": {}, "RS-21": {}, "RS-22": {}, "RS-23": {}, "RS-24": {},
"RS-25": {}, "RS-26": {}, "RS-27": {}, "RS-28": {}, "RS-29": {},
"RS-KM": {}, "RS-VO": {}, "RU-AD": {}, "RU-AL": {}, "RU-ALT": {},
"RU-AMU": {}, "RU-ARK": {}, "RU-AST": {}, "RU-BA": {}, "RU-BEL": {},
"RU-BRY": {}, "RU-BU": {}, "RU-CE": {}, "RU-CHE": {}, "RU-CHU": {},
"RU-CU": {}, "RU-DA": {}, "RU-IN": {}, "RU-IRK": {}, "RU-IVA": {},
"RU-KAM": {}, "RU-KB": {}, "RU-KC": {}, "RU-KDA": {}, "RU-KEM": {},
"RU-KGD": {}, "RU-KGN": {}, "RU-KHA": {}, "RU-KHM": {}, "RU-KIR": {},
"RU-KK": {}, "RU-KL": {}, "RU-KLU": {}, "RU-KO": {}, "RU-KOS": {},
"RU-KR": {}, "RU-KRS": {}, "RU-KYA": {}, "RU-LEN": {}, "RU-LIP": {},
"RU-MAG": {}, "RU-ME": {}, "RU-MO": {}, "RU-MOS": {}, "RU-MOW": {},
"RU-MUR": {}, "RU-NEN": {}, "RU-NGR": {}, "RU-NIZ": {}, "RU-NVS": {},
"RU-OMS": {}, "RU-ORE": {}, "RU-ORL": {}, "RU-PER": {}, "RU-PNZ": {},
"RU-PRI": {}, "RU-PSK": {}, "RU-ROS": {}, "RU-RYA": {}, "RU-SA": {},
"RU-SAK": {}, "RU-SAM": {}, "RU-SAR": {}, "RU-SE": {}, "RU-SMO": {},
"RU-SPE": {}, "RU-STA": {}, "RU-SVE": {}, "RU-TA": {}, "RU-TAM": {},
"RU-TOM": {}, "RU-TUL": {}, "RU-TVE": {}, "RU-TY": {}, "RU-TYU": {},
"RU-UD": {}, "RU-ULY": {}, "RU-VGG": {}, "RU-VLA": {}, "RU-VLG": {},
"RU-VOR": {}, "RU-YAN": {}, "RU-YAR": {}, "RU-YEV": {}, "RU-ZAB": {},
"RW-01": {}, "RW-02": {}, "RW-03": {}, "RW-04": {}, "RW-05": {},
"SA-01": {}, "SA-02": {}, "SA-03": {}, "SA-04": {}, "SA-05": {},
"SA-06": {}, "SA-07": {}, "SA-08": {}, "SA-09": {}, "SA-10": {},
"SA-11": {}, "SA-12": {}, "SA-14": {}, "SB-CE": {}, "SB-CH": {},
"SB-CT": {}, "SB-GU": {}, "SB-IS": {}, "SB-MK": {}, "SB-ML": {},
"SB-RB": {}, "SB-TE": {}, "SB-WE": {}, "SC-01": {}, "SC-02": {},
"SC-03": {}, "SC-04": {}, "SC-05": {}, "SC-06": {}, "SC-07": {},
"SC-08": {}, "SC-09": {}, "SC-10": {}, "SC-11": {}, "SC-12": {},
"SC-13": {}, "SC-14": {}, "SC-15": {}, "SC-16": {}, "SC-17": {},
"SC-18": {}, "SC-19": {}, "SC-20": {}, "SC-21": {}, "SC-22": {},
"SC-23": {}, "SC-24": {}, "SC-25": {}, "SD-DC": {}, "SD-DE": {},
"SD-DN": {}, "SD-DS": {}, "SD-DW": {}, "SD-GD": {}, "SD-GK": {}, "SD-GZ": {},
"SD-KA": {}, "SD-KH": {}, "SD-KN": {}, "SD-KS": {}, "SD-NB": {},
"SD-NO": {}, "SD-NR": {}, "SD-NW": {}, "SD-RS": {}, "SD-SI": {},
"SE-AB": {}, "SE-AC": {}, "SE-BD": {}, "SE-C": {}, "SE-D": {},
"SE-E": {}, "SE-F": {}, "SE-G": {}, "SE-H": {}, "SE-I": {},
"SE-K": {}, "SE-M": {}, "SE-N": {}, "SE-O": {}, "SE-S": {},
"SE-T": {}, "SE-U": {}, "SE-W": {}, "SE-X": {}, "SE-Y": {},
"SE-Z": {}, "SG-01": {}, "SG-02": {}, "SG-03": {}, "SG-04": {},
"SG-05": {}, "SH-AC": {}, "SH-HL": {}, "SH-TA": {}, "SI-001": {},
"SI-002": {}, "SI-003": {}, "SI-004": {}, "SI-005": {}, "SI-006": {},
"SI-007": {}, "SI-008": {}, "SI-009": {}, "SI-010": {}, "SI-011": {},
"SI-012": {}, "SI-013": {}, "SI-014": {}, "SI-015": {}, "SI-016": {},
"SI-017": {}, "SI-018": {}, "SI-019": {}, "SI-020": {}, "SI-021": {},
"SI-022": {}, "SI-023": {}, "SI-024": {}, "SI-025": {}, "SI-026": {},
"SI-027": {}, "SI-028": {}, "SI-029": {}, "SI-030": {}, "SI-031": {},
"SI-032": {}, "SI-033": {}, "SI-034": {}, "SI-035": {}, "SI-036": {},
"SI-037": {}, "SI-038": {}, "SI-039": {}, "SI-040": {}, "SI-041": {},
"SI-042": {}, "SI-043": {}, "SI-044": {}, "SI-045": {}, "SI-046": {},
"SI-047": {}, "SI-048": {}, "SI-049": {}, "SI-050": {}, "SI-051": {},
"SI-052": {}, "SI-053": {}, "SI-054": {}, "SI-055": {}, "SI-056": {},
"SI-057": {}, "SI-058": {}, "SI-059": {}, "SI-060": {}, "SI-061": {},
"SI-062": {}, "SI-063": {}, "SI-064": {}, "SI-065": {}, "SI-066": {},
"SI-067": {}, "SI-068": {}, "SI-069": {}, "SI-070": {}, "SI-071": {},
"SI-072": {}, "SI-073": {}, "SI-074": {}, "SI-075": {}, "SI-076": {},
"SI-077": {}, "SI-078": {}, "SI-079": {}, "SI-080": {}, "SI-081": {},
"SI-082": {}, "SI-083": {}, "SI-084": {}, "SI-085": {}, "SI-086": {},
"SI-087": {}, "SI-088": {}, "SI-089": {}, "SI-090": {}, "SI-091": {},
"SI-092": {}, "SI-093": {}, "SI-094": {}, "SI-095": {}, "SI-096": {},
"SI-097": {}, "SI-098": {}, "SI-099": {}, "SI-100": {}, "SI-101": {},
"SI-102": {}, "SI-103": {}, "SI-104": {}, "SI-105": {}, "SI-106": {},
"SI-107": {}, "SI-108": {}, "SI-109": {}, "SI-110": {}, "SI-111": {},
"SI-112": {}, "SI-113": {}, "SI-114": {}, "SI-115": {}, "SI-116": {},
"SI-117": {}, "SI-118": {}, "SI-119": {}, "SI-120": {}, "SI-121": {},
"SI-122": {}, "SI-123": {}, "SI-124": {}, "SI-125": {}, "SI-126": {},
"SI-127": {}, "SI-128": {}, "SI-129": {}, "SI-130": {}, "SI-131": {},
"SI-132": {}, "SI-133": {}, "SI-134": {}, "SI-135": {}, "SI-136": {},
"SI-137": {}, "SI-138": {}, "SI-139": {}, "SI-140": {}, "SI-141": {},
"SI-142": {}, "SI-143": {}, "SI-144": {}, "SI-146": {}, "SI-147": {},
"SI-148": {}, "SI-149": {}, "SI-150": {}, "SI-151": {}, "SI-152": {},
"SI-153": {}, "SI-154": {}, "SI-155": {}, "SI-156": {}, "SI-157": {},
"SI-158": {}, "SI-159": {}, "SI-160": {}, "SI-161": {}, "SI-162": {},
"SI-163": {}, "SI-164": {}, "SI-165": {}, "SI-166": {}, "SI-167": {},
"SI-168": {}, "SI-169": {}, "SI-170": {}, "SI-171": {}, "SI-172": {},
"SI-173": {}, "SI-174": {}, "SI-175": {}, "SI-176": {}, "SI-177": {},
"SI-178": {}, "SI-179": {}, "SI-180": {}, "SI-181": {}, "SI-182": {},
"SI-183": {}, "SI-184": {}, "SI-185": {}, "SI-186": {}, "SI-187": {},
"SI-188": {}, "SI-189": {}, "SI-190": {}, "SI-191": {}, "SI-192": {},
"SI-193": {}, "SI-194": {}, "SI-195": {}, "SI-196": {}, "SI-197": {},
"SI-198": {}, "SI-199": {}, "SI-200": {}, "SI-201": {}, "SI-202": {},
"SI-203": {}, "SI-204": {}, "SI-205": {}, "SI-206": {}, "SI-207": {},
"SI-208": {}, "SI-209": {}, "SI-210": {}, "SI-211": {}, "SI-212": {}, "SI-213": {}, "SK-BC": {},
"SK-BL": {}, "SK-KI": {}, "SK-NI": {}, "SK-PV": {}, "SK-TA": {},
"SK-TC": {}, "SK-ZI": {}, "SL-E": {}, "SL-N": {}, "SL-S": {},
"SL-W": {}, "SM-01": {}, "SM-02": {}, "SM-03": {}, "SM-04": {},
"SM-05": {}, "SM-06": {}, "SM-07": {}, "SM-08": {}, "SM-09": {},
"SN-DB": {}, "SN-DK": {}, "SN-FK": {}, "SN-KA": {}, "SN-KD": {},
"SN-KE": {}, "SN-KL": {}, "SN-LG": {}, "SN-MT": {}, "SN-SE": {},
"SN-SL": {}, "SN-TC": {}, "SN-TH": {}, "SN-ZG": {}, "SO-AW": {},
"SO-BK": {}, "SO-BN": {}, "SO-BR": {}, "SO-BY": {}, "SO-GA": {},
"SO-GE": {}, "SO-HI": {}, "SO-JD": {}, "SO-JH": {}, "SO-MU": {},
"SO-NU": {}, "SO-SA": {}, "SO-SD": {}, "SO-SH": {}, "SO-SO": {},
"SO-TO": {}, "SO-WO": {}, "SR-BR": {}, "SR-CM": {}, "SR-CR": {},
"SR-MA": {}, "SR-NI": {}, "SR-PM": {}, "SR-PR": {}, "SR-SA": {},
"SR-SI": {}, "SR-WA": {}, "SS-BN": {}, "SS-BW": {}, "SS-EC": {},
"SS-EE8": {}, "SS-EE": {}, "SS-EW": {}, "SS-JG": {}, "SS-LK": {}, "SS-NU": {},
"SS-UY": {}, "SS-WR": {}, "ST-01": {}, "ST-P": {}, "ST-S": {}, "SV-AH": {},
"SV-CA": {}, "SV-CH": {}, "SV-CU": {}, "SV-LI": {}, "SV-MO": {},
"SV-PA": {}, "SV-SA": {}, "SV-SM": {}, "SV-SO": {}, "SV-SS": {},
"SV-SV": {}, "SV-UN": {}, "SV-US": {}, "SY-DI": {}, "SY-DR": {},
"SY-DY": {}, "SY-HA": {}, "SY-HI": {}, "SY-HL": {}, "SY-HM": {},
"SY-ID": {}, "SY-LA": {}, "SY-QU": {}, "SY-RA": {}, "SY-RD": {},
"SY-SU": {}, "SY-TA": {}, "SZ-HH": {}, "SZ-LU": {}, "SZ-MA": {},
"SZ-SH": {}, "TD-BA": {}, "TD-BG": {}, "TD-BO": {}, "TD-CB": {},
"TD-EN": {}, "TD-GR": {}, "TD-HL": {}, "TD-KA": {}, "TD-LC": {},
"TD-LO": {}, "TD-LR": {}, "TD-MA": {}, "TD-MC": {}, "TD-ME": {},
"TD-MO": {}, "TD-ND": {}, "TD-OD": {}, "TD-SA": {}, "TD-SI": {},
"TD-TA": {}, "TD-TI": {}, "TD-WF": {}, "TG-C": {}, "TG-K": {},
"TG-M": {}, "TG-P": {}, "TG-S": {}, "TH-10": {}, "TH-11": {},
"TH-12": {}, "TH-13": {}, "TH-14": {}, "TH-15": {}, "TH-16": {},
"TH-17": {}, "TH-18": {}, "TH-19": {}, "TH-20": {}, "TH-21": {},
"TH-22": {}, "TH-23": {}, "TH-24": {}, "TH-25": {}, "TH-26": {},
"TH-27": {}, "TH-30": {}, "TH-31": {}, "TH-32": {}, "TH-33": {},
"TH-34": {}, "TH-35": {}, "TH-36": {}, "TH-37": {}, "TH-38": {}, "TH-39": {},
"TH-40": {}, "TH-41": {}, "TH-42": {}, "TH-43": {}, "TH-44": {},
"TH-45": {}, "TH-46": {}, "TH-47": {}, "TH-48": {}, "TH-49": {},
"TH-50": {}, "TH-51": {}, "TH-52": {}, "TH-53": {}, "TH-54": {},
"TH-55": {}, "TH-56": {}, "TH-57": {}, "TH-58": {}, "TH-60": {},
"TH-61": {}, "TH-62": {}, "TH-63": {}, "TH-64": {}, "TH-65": {},
"TH-66": {}, "TH-67": {}, "TH-70": {}, "TH-71": {}, "TH-72": {},
"TH-73": {}, "TH-74": {}, "TH-75": {}, "TH-76": {}, "TH-77": {},
"TH-80": {}, "TH-81": {}, "TH-82": {}, "TH-83": {}, "TH-84": {},
"TH-85": {}, "TH-86": {}, "TH-90": {}, "TH-91": {}, "TH-92": {},
"TH-93": {}, "TH-94": {}, "TH-95": {}, "TH-96": {}, "TH-S": {},
"TJ-GB": {}, "TJ-KT": {}, "TJ-SU": {}, "TJ-DU": {}, "TJ-RA": {}, "TL-AL": {}, "TL-AN": {},
"TL-BA": {}, "TL-BO": {}, "TL-CO": {}, "TL-DI": {}, "TL-ER": {},
"TL-LA": {}, "TL-LI": {}, "TL-MF": {}, "TL-MT": {}, "TL-OE": {},
"TL-VI": {}, "TM-A": {}, "TM-B": {}, "TM-D": {}, "TM-L": {},
"TM-M": {}, "TM-S": {}, "TN-11": {}, "TN-12": {}, "TN-13": {},
"TN-14": {}, "TN-21": {}, "TN-22": {}, "TN-23": {}, "TN-31": {},
"TN-32": {}, "TN-33": {}, "TN-34": {}, "TN-41": {}, "TN-42": {},
"TN-43": {}, "TN-51": {}, "TN-52": {}, "TN-53": {}, "TN-61": {},
"TN-71": {}, "TN-72": {}, "TN-73": {}, "TN-81": {}, "TN-82": {},
"TN-83": {}, "TO-01": {}, "TO-02": {}, "TO-03": {}, "TO-04": {},
"TO-05": {}, "TR-01": {}, "TR-02": {}, "TR-03": {}, "TR-04": {},
"TR-05": {}, "TR-06": {}, "TR-07": {}, "TR-08": {}, "TR-09": {},
"TR-10": {}, "TR-11": {}, "TR-12": {}, "TR-13": {}, "TR-14": {},
"TR-15": {}, "TR-16": {}, "TR-17": {}, "TR-18": {}, "TR-19": {},
"TR-20": {}, "TR-21": {}, "TR-22": {}, "TR-23": {}, "TR-24": {},
"TR-25": {}, "TR-26": {}, "TR-27": {}, "TR-28": {}, "TR-29": {},
"TR-30": {}, "TR-31": {}, "TR-32": {}, "TR-33": {}, "TR-34": {},
"TR-35": {}, "TR-36": {}, "TR-37": {}, "TR-38": {}, "TR-39": {},
"TR-40": {}, "TR-41": {}, "TR-42": {}, "TR-43": {}, "TR-44": {},
"TR-45": {}, "TR-46": {}, "TR-47": {}, "TR-48": {}, "TR-49": {},
"TR-50": {}, "TR-51": {}, "TR-52": {}, "TR-53": {}, "TR-54": {},
"TR-55": {}, "TR-56": {}, "TR-57": {}, "TR-58": {}, "TR-59": {},
"TR-60": {}, "TR-61": {}, "TR-62": {}, "TR-63": {}, "TR-64": {},
"TR-65": {}, "TR-66": {}, "TR-67": {}, "TR-68": {}, "TR-69": {},
"TR-70": {}, "TR-71": {}, "TR-72": {}, "TR-73": {}, "TR-74": {},
"TR-75": {}, "TR-76": {}, "TR-77": {}, "TR-78": {}, "TR-79": {},
"TR-80": {}, "TR-81": {}, "TT-ARI": {}, "TT-CHA": {}, "TT-CTT": {},
"TT-DMN": {}, "TT-ETO": {}, "TT-MRC": {}, "TT-TOB": {}, "TT-PED": {}, "TT-POS": {}, "TT-PRT": {},
"TT-PTF": {}, "TT-RCM": {}, "TT-SFO": {}, "TT-SGE": {}, "TT-SIP": {},
"TT-SJL": {}, "TT-TUP": {}, "TT-WTO": {}, "TV-FUN": {}, "TV-NIT": {},
"TV-NKF": {}, "TV-NKL": {}, "TV-NMA": {}, "TV-NMG": {}, "TV-NUI": {},
"TV-VAI": {}, "TW-CHA": {}, "TW-CYI": {}, "TW-CYQ": {}, "TW-KIN": {}, "TW-HSQ": {},
"TW-HSZ": {}, "TW-HUA": {}, "TW-LIE": {}, "TW-ILA": {}, "TW-KEE": {}, "TW-KHH": {},
"TW-KHQ": {}, "TW-MIA": {}, "TW-NAN": {}, "TW-NWT": {}, "TW-PEN": {}, "TW-PIF": {},
"TW-TAO": {}, "TW-TNN": {}, "TW-TNQ": {}, "TW-TPE": {}, "TW-TPQ": {},
"TW-TTT": {}, "TW-TXG": {}, "TW-TXQ": {}, "TW-YUN": {}, "TZ-01": {},
"TZ-02": {}, "TZ-03": {}, "TZ-04": {}, "TZ-05": {}, "TZ-06": {},
"TZ-07": {}, "TZ-08": {}, "TZ-09": {}, "TZ-10": {}, "TZ-11": {},
"TZ-12": {}, "TZ-13": {}, "TZ-14": {}, "TZ-15": {}, "TZ-16": {},
"TZ-17": {}, "TZ-18": {}, "TZ-19": {}, "TZ-20": {}, "TZ-21": {},
"TZ-22": {}, "TZ-23": {}, "TZ-24": {}, "TZ-25": {}, "TZ-26": {}, "TZ-27": {}, "TZ-28": {}, "TZ-29": {}, "TZ-30": {}, "TZ-31": {},
"UA-05": {}, "UA-07": {}, "UA-09": {}, "UA-12": {}, "UA-14": {},
"UA-18": {}, "UA-21": {}, "UA-23": {}, "UA-26": {}, "UA-30": {},
"UA-32": {}, "UA-35": {}, "UA-40": {}, "UA-43": {}, "UA-46": {},
"UA-48": {}, "UA-51": {}, "UA-53": {}, "UA-56": {}, "UA-59": {},
"UA-61": {}, "UA-63": {}, "UA-65": {}, "UA-68": {}, "UA-71": {},
"UA-74": {}, "UA-77": {}, "UG-101": {}, "UG-102": {}, "UG-103": {},
"UG-104": {}, "UG-105": {}, "UG-106": {}, "UG-107": {}, "UG-108": {},
"UG-109": {}, "UG-110": {}, "UG-111": {}, "UG-112": {}, "UG-113": {},
"UG-114": {}, "UG-115": {}, "UG-116": {}, "UG-201": {}, "UG-202": {},
"UG-203": {}, "UG-204": {}, "UG-205": {}, "UG-206": {}, "UG-207": {},
"UG-208": {}, "UG-209": {}, "UG-210": {}, "UG-211": {}, "UG-212": {},
"UG-213": {}, "UG-214": {}, "UG-215": {}, "UG-216": {}, "UG-217": {},
"UG-218": {}, "UG-219": {}, "UG-220": {}, "UG-221": {}, "UG-222": {},
"UG-223": {}, "UG-224": {}, "UG-301": {}, "UG-302": {}, "UG-303": {},
"UG-304": {}, "UG-305": {}, "UG-306": {}, "UG-307": {}, "UG-308": {},
"UG-309": {}, "UG-310": {}, "UG-311": {}, "UG-312": {}, "UG-313": {},
"UG-314": {}, "UG-315": {}, "UG-316": {}, "UG-317": {}, "UG-318": {},
"UG-319": {}, "UG-320": {}, "UG-321": {}, "UG-401": {}, "UG-402": {},
"UG-403": {}, "UG-404": {}, "UG-405": {}, "UG-406": {}, "UG-407": {},
"UG-408": {}, "UG-409": {}, "UG-410": {}, "UG-411": {}, "UG-412": {},
"UG-413": {}, "UG-414": {}, "UG-415": {}, "UG-416": {}, "UG-417": {},
"UG-418": {}, "UG-419": {}, "UG-C": {}, "UG-E": {}, "UG-N": {},
"UG-W": {}, "UG-322": {}, "UG-323": {}, "UG-420": {}, "UG-117": {},
"UG-118": {}, "UG-225": {}, "UG-120": {}, "UG-226": {},
"UG-121": {}, "UG-122": {}, "UG-227": {}, "UG-421": {},
"UG-325": {}, "UG-228": {}, "UG-123": {}, "UG-422": {},
"UG-326": {}, "UG-229": {}, "UG-124": {}, "UG-423": {},
"UG-230": {}, "UG-327": {}, "UG-424": {}, "UG-328": {},
"UG-425": {}, "UG-426": {}, "UG-330": {},
"UM-67": {}, "UM-71": {}, "UM-76": {}, "UM-79": {},
"UM-81": {}, "UM-84": {}, "UM-86": {}, "UM-89": {}, "UM-95": {},
"US-AK": {}, "US-AL": {}, "US-AR": {}, "US-AS": {}, "US-AZ": {},
"US-CA": {}, "US-CO": {}, "US-CT": {}, "US-DC": {}, "US-DE": {},
"US-FL": {}, "US-GA": {}, "US-GU": {}, "US-HI": {}, "US-IA": {},
"US-ID": {}, "US-IL": {}, "US-IN": {}, "US-KS": {}, "US-KY": {},
"US-LA": {}, "US-MA": {}, "US-MD": {}, "US-ME": {}, "US-MI": {},
"US-MN": {}, "US-MO": {}, "US-MP": {}, "US-MS": {}, "US-MT": {},
"US-NC": {}, "US-ND": {}, "US-NE": {}, "US-NH": {}, "US-NJ": {},
"US-NM": {}, "US-NV": {}, "US-NY": {}, "US-OH": {}, "US-OK": {},
"US-OR": {}, "US-PA": {}, "US-PR": {}, "US-RI": {}, "US-SC": {},
"US-SD": {}, "US-TN": {}, "US-TX": {}, "US-UM": {}, "US-UT": {},
"US-VA": {}, "US-VI": {}, "US-VT": {}, "US-WA": {}, "US-WI": {},
"US-WV": {}, "US-WY": {}, "UY-AR": {}, "UY-CA": {}, "UY-CL": {},
"UY-CO": {}, "UY-DU": {}, "UY-FD": {}, "UY-FS": {}, "UY-LA": {},
"UY-MA": {}, "UY-MO": {}, "UY-PA": {}, "UY-RN": {}, "UY-RO": {},
"UY-RV": {}, "UY-SA": {}, "UY-SJ": {}, "UY-SO": {}, "UY-TA": {},
"UY-TT": {}, "UZ-AN": {}, "UZ-BU": {}, "UZ-FA": {}, "UZ-JI": {},
"UZ-NG": {}, "UZ-NW": {}, "UZ-QA": {}, "UZ-QR": {}, "UZ-SA": {},
"UZ-SI": {}, "UZ-SU": {}, "UZ-TK": {}, "UZ-TO": {}, "UZ-XO": {},
"VC-01": {}, "VC-02": {}, "VC-03": {}, "VC-04": {}, "VC-05": {},
"VC-06": {}, "VE-A": {}, "VE-B": {}, "VE-C": {}, "VE-D": {},
"VE-E": {}, "VE-F": {}, "VE-G": {}, "VE-H": {}, "VE-I": {},
"VE-J": {}, "VE-K": {}, "VE-L": {}, "VE-M": {}, "VE-N": {},
"VE-O": {}, "VE-P": {}, "VE-R": {}, "VE-S": {}, "VE-T": {},
"VE-U": {}, "VE-V": {}, "VE-W": {}, "VE-X": {}, "VE-Y": {},
"VE-Z": {}, "VN-01": {}, "VN-02": {}, "VN-03": {}, "VN-04": {},
"VN-05": {}, "VN-06": {}, "VN-07": {}, "VN-09": {}, "VN-13": {},
"VN-14": {}, "VN-15": {}, "VN-18": {}, "VN-20": {}, "VN-21": {},
"VN-22": {}, "VN-23": {}, "VN-24": {}, "VN-25": {}, "VN-26": {},
"VN-27": {}, "VN-28": {}, "VN-29": {}, "VN-30": {}, "VN-31": {},
"VN-32": {}, "VN-33": {}, "VN-34": {}, "VN-35": {}, "VN-36": {},
"VN-37": {}, "VN-39": {}, "VN-40": {}, "VN-41": {}, "VN-43": {},
"VN-44": {}, "VN-45": {}, "VN-46": {}, "VN-47": {}, "VN-49": {},
"VN-50": {}, "VN-51": {}, "VN-52": {}, "VN-53": {}, "VN-54": {},
"VN-55": {}, "VN-56": {}, "VN-57": {}, "VN-58": {}, "VN-59": {},
"VN-61": {}, "VN-63": {}, "VN-66": {}, "VN-67": {}, "VN-68": {},
"VN-69": {}, "VN-70": {}, "VN-71": {}, "VN-72": {}, "VN-73": {},
"VN-CT": {}, "VN-DN": {}, "VN-HN": {}, "VN-HP": {}, "VN-SG": {},
"VU-MAP": {}, "VU-PAM": {}, "VU-SAM": {}, "VU-SEE": {}, "VU-TAE": {},
"VU-TOB": {}, "WF-SG": {}, "WF-UV": {}, "WS-AA": {}, "WS-AL": {}, "WS-AT": {}, "WS-FA": {},
"WS-GE": {}, "WS-GI": {}, "WS-PA": {}, "WS-SA": {}, "WS-TU": {},
"WS-VF": {}, "WS-VS": {}, "YE-AB": {}, "YE-AD": {}, "YE-AM": {},
"YE-BA": {}, "YE-DA": {}, "YE-DH": {}, "YE-HD": {}, "YE-HJ": {}, "YE-HU": {},
"YE-IB": {}, "YE-JA": {}, "YE-LA": {}, "YE-MA": {}, "YE-MR": {},
"YE-MU": {}, "YE-MW": {}, "YE-RA": {}, "YE-SA": {}, "YE-SD": {}, "YE-SH": {},
"YE-SN": {}, "YE-TA": {}, "ZA-EC": {}, "ZA-FS": {}, "ZA-GP": {},
"ZA-LP": {}, "ZA-MP": {}, "ZA-NC": {}, "ZA-NW": {}, "ZA-WC": {},
"ZA-ZN": {}, "ZA-KZN": {}, "ZM-01": {}, "ZM-02": {}, "ZM-03": {}, "ZM-04": {},
"ZM-05": {}, "ZM-06": {}, "ZM-07": {}, "ZM-08": {}, "ZM-09": {}, "ZM-10": {},
"ZW-BU": {}, "ZW-HA": {}, "ZW-MA": {}, "ZW-MC": {}, "ZW-ME": {},
"ZW-MI": {}, "ZW-MN": {}, "ZW-MS": {}, "ZW-MV": {}, "ZW-MW": {},
}
golang-github-go-playground-validator-v10-10.30.1/currency_codes.go 0000664 0000000 0000000 00000007202 15124100770 0025113 0 ustar 00root root 0000000 0000000 package validator
var iso4217 = map[string]struct{}{
"AFN": {}, "EUR": {}, "ALL": {}, "DZD": {}, "USD": {},
"AOA": {}, "XCD": {}, "ARS": {}, "AMD": {}, "AWG": {},
"AUD": {}, "AZN": {}, "BSD": {}, "BHD": {}, "BDT": {},
"BBD": {}, "BYN": {}, "BZD": {}, "XOF": {}, "BMD": {},
"INR": {}, "BTN": {}, "BOB": {}, "BOV": {}, "BAM": {},
"BWP": {}, "NOK": {}, "BRL": {}, "BND": {}, "BGN": {},
"BIF": {}, "CVE": {}, "KHR": {}, "XAF": {}, "CAD": {},
"KYD": {}, "CLP": {}, "CLF": {}, "CNY": {}, "COP": {},
"COU": {}, "KMF": {}, "CDF": {}, "NZD": {}, "CRC": {},
"CUP": {}, "CZK": {}, "DKK": {}, "DJF": {}, "DOP": {},
"EGP": {}, "SVC": {}, "ERN": {}, "SZL": {}, "ETB": {},
"FKP": {}, "FJD": {}, "XPF": {}, "GMD": {}, "GEL": {},
"GHS": {}, "GIP": {}, "GTQ": {}, "GBP": {}, "GNF": {},
"GYD": {}, "HTG": {}, "HNL": {}, "HKD": {}, "HUF": {},
"ISK": {}, "IDR": {}, "XDR": {}, "IRR": {}, "IQD": {},
"ILS": {}, "JMD": {}, "JPY": {}, "JOD": {}, "KZT": {},
"KES": {}, "KPW": {}, "KRW": {}, "KWD": {}, "KGS": {},
"LAK": {}, "LBP": {}, "LSL": {}, "ZAR": {}, "LRD": {},
"LYD": {}, "CHF": {}, "MOP": {}, "MKD": {}, "MGA": {},
"MWK": {}, "MYR": {}, "MVR": {}, "MRU": {}, "MUR": {},
"XUA": {}, "MXN": {}, "MXV": {}, "MDL": {}, "MNT": {},
"MAD": {}, "MZN": {}, "MMK": {}, "NAD": {}, "NPR": {},
"NIO": {}, "NGN": {}, "OMR": {}, "PKR": {}, "PAB": {},
"PGK": {}, "PYG": {}, "PEN": {}, "PHP": {}, "PLN": {},
"QAR": {}, "RON": {}, "RUB": {}, "RWF": {}, "SHP": {},
"WST": {}, "STN": {}, "SAR": {}, "RSD": {}, "SCR": {},
"SLE": {}, "SGD": {}, "XSU": {}, "SBD": {}, "SOS": {},
"SSP": {}, "LKR": {}, "SDG": {}, "SRD": {}, "SEK": {},
"CHE": {}, "CHW": {}, "SYP": {}, "TWD": {}, "TJS": {},
"TZS": {}, "THB": {}, "TOP": {}, "TTD": {}, "TND": {},
"TRY": {}, "TMT": {}, "UGX": {}, "UAH": {}, "AED": {},
"USN": {}, "UYU": {}, "UYI": {}, "UYW": {}, "UZS": {},
"VUV": {}, "VES": {}, "VED": {}, "VND": {}, "YER": {},
"ZMW": {}, "ZWG": {}, "XBA": {}, "XBB": {}, "XBC": {},
"XBD": {}, "XCG": {}, "XTS": {}, "XXX": {}, "XAU": {},
"XPD": {}, "XPT": {}, "XAG": {},
}
var iso4217_numeric = map[int]struct{}{
8: {}, 12: {}, 32: {}, 36: {}, 44: {},
48: {}, 50: {}, 51: {}, 52: {}, 60: {},
64: {}, 68: {}, 72: {}, 84: {}, 90: {},
96: {}, 104: {}, 108: {}, 116: {}, 124: {},
132: {}, 136: {}, 144: {}, 152: {}, 156: {},
170: {}, 174: {}, 188: {}, 192: {}, 203: {},
208: {}, 214: {}, 222: {}, 230: {}, 232: {},
238: {}, 242: {}, 262: {}, 270: {}, 292: {},
320: {}, 324: {}, 328: {}, 332: {}, 340: {},
344: {}, 348: {}, 352: {}, 356: {}, 360: {},
364: {}, 368: {}, 376: {}, 388: {}, 392: {},
398: {}, 400: {}, 404: {}, 408: {}, 410: {},
414: {}, 417: {}, 418: {}, 422: {}, 426: {},
430: {}, 434: {}, 446: {}, 454: {}, 458: {},
462: {}, 480: {}, 484: {}, 496: {}, 498: {},
504: {}, 512: {}, 516: {}, 524: {}, 532: {},
533: {}, 548: {}, 554: {}, 558: {}, 566: {},
578: {}, 586: {}, 590: {}, 598: {}, 600: {},
604: {}, 608: {}, 634: {}, 643: {}, 646: {},
654: {}, 682: {}, 690: {}, 702: {}, 704: {},
706: {}, 710: {}, 728: {}, 748: {}, 752: {},
756: {}, 760: {}, 764: {}, 776: {}, 780: {},
784: {}, 788: {}, 800: {}, 807: {}, 818: {},
826: {}, 834: {}, 840: {}, 858: {}, 860: {},
882: {}, 886: {}, 901: {}, 924: {}, 925: {},
926: {}, 927: {}, 928: {}, 929: {}, 930: {},
933: {}, 934: {}, 936: {}, 938: {}, 940: {},
941: {}, 943: {}, 944: {}, 946: {}, 947: {},
948: {}, 949: {}, 950: {}, 951: {}, 952: {},
953: {}, 955: {}, 956: {}, 957: {}, 958: {},
959: {}, 960: {}, 961: {}, 962: {}, 963: {},
964: {}, 965: {}, 967: {}, 968: {}, 969: {},
970: {}, 971: {}, 972: {}, 973: {}, 975: {},
976: {}, 977: {}, 978: {}, 979: {}, 980: {},
981: {}, 984: {}, 985: {}, 986: {}, 990: {},
994: {}, 997: {}, 999: {},
}
golang-github-go-playground-validator-v10-10.30.1/doc.go 0000664 0000000 0000000 00000121563 15124100770 0022660 0 ustar 00root root 0000000 0000000 /*
Package validator implements value validations for structs and individual fields
based on tags.
It can also handle Cross-Field and Cross-Struct validation for nested structs
and has the ability to dive into arrays and maps of any type.
see more examples https://github.com/go-playground/validator/tree/master/_examples
# Singleton
Validator is designed to be thread-safe and used as a singleton instance.
It caches information about your struct and validations,
in essence only parsing your validation tags once per struct type.
Using multiple instances neglects the benefit of caching.
The not thread-safe functions are explicitly marked as such in the documentation.
# Validation Functions Return Type error
Doing things this way is actually the way the standard library does, see the
file.Open method here:
https://golang.org/pkg/os/#Open.
The authors return type "error" to avoid the issue discussed in the following,
where err is always != nil:
http://stackoverflow.com/a/29138676/3158232
https://github.com/go-playground/validator/issues/134
Validator only InvalidValidationError for bad validation input, nil or
ValidationErrors as type error; so, in your code all you need to do is check
if the error returned is not nil, and if it's not check if error is
InvalidValidationError ( if necessary, most of the time it isn't ) type cast
it to type ValidationErrors like so err.(validator.ValidationErrors).
# Custom Validation Functions
Custom Validation functions can be added. Example:
// Structure
func customFunc(fl validator.FieldLevel) bool {
if fl.Field().String() == "invalid" {
return false
}
return true
}
validate.RegisterValidation("custom tag name", customFunc)
// NOTES: using the same tag name as an existing function
// will overwrite the existing one
# Cross-Field Validation
Cross-Field Validation can be done via the following tags:
- eqfield
- nefield
- gtfield
- gtefield
- ltfield
- ltefield
- eqcsfield
- necsfield
- gtcsfield
- gtecsfield
- ltcsfield
- ltecsfield
If, however, some custom cross-field validation is required, it can be done
using a custom validation.
Why not just have cross-fields validation tags (i.e. only eqcsfield and not
eqfield)?
The reason is efficiency. If you want to check a field within the same struct
"eqfield" only has to find the field on the same struct (1 level). But, if we
used "eqcsfield" it could be multiple levels down. Example:
type Inner struct {
StartDate time.Time
}
type Outer struct {
InnerStructField *Inner
CreatedAt time.Time `validate:"ltecsfield=InnerStructField.StartDate"`
}
now := time.Now()
inner := &Inner{
StartDate: now,
}
outer := &Outer{
InnerStructField: inner,
CreatedAt: now,
}
errs := validate.Struct(outer)
// NOTE: when calling validate.Struct(val) topStruct will be the top level struct passed
// into the function
// when calling validate.VarWithValue(val, field, tag) val will be
// whatever you pass, struct, field...
// when calling validate.Field(field, tag) val will be nil
# Multiple Validators
Multiple validators on a field will process in the order defined. Example:
type Test struct {
Field `validate:"max=10,min=1"`
}
// max will be checked then min
Bad Validator definitions are not handled by the library. Example:
type Test struct {
Field `validate:"min=10,max=0"`
}
// this definition of min max will never succeed
# Using Validator Tags
Baked In Cross-Field validation only compares fields on the same struct.
If Cross-Field + Cross-Struct validation is needed you should implement your
own custom validator.
Comma (",") is the default separator of validation tags. If you wish to
have a comma included within the parameter (i.e. excludesall=,) you will need to
use the UTF-8 hex representation 0x2C, which is replaced in the code as a comma,
so the above will become excludesall=0x2C.
type Test struct {
Field `validate:"excludesall=,"` // BAD! Do not include a comma.
Field `validate:"excludesall=0x2C"` // GOOD! Use the UTF-8 hex representation.
}
Pipe ("|") is the 'or' validation tags deparator. If you wish to
have a pipe included within the parameter i.e. excludesall=| you will need to
use the UTF-8 hex representation 0x7C, which is replaced in the code as a pipe,
so the above will become excludesall=0x7C
type Test struct {
Field `validate:"excludesall=|"` // BAD! Do not include a pipe!
Field `validate:"excludesall=0x7C"` // GOOD! Use the UTF-8 hex representation.
}
# Baked In Validators and Tags
Here is a list of the current built in validators:
# Skip Field
Tells the validation to skip this struct field; this is particularly
handy in ignoring embedded structs from being validated. (Usage: -)
Usage: -
# Or Operator
This is the 'or' operator allowing multiple validators to be used and
accepted. (Usage: rgb|rgba) <-- this would allow either rgb or rgba
colors to be accepted. This can also be combined with 'and' for example
( Usage: omitempty,rgb|rgba)
Usage: |
# StructOnly
When a field that is a nested struct is encountered, and contains this flag
any validation on the nested struct will be run, but none of the nested
struct fields will be validated. This is useful if inside of your program
you know the struct will be valid, but need to verify it has been assigned.
NOTE: only "required" and "omitempty" can be used on a struct itself.
Usage: structonly
# NoStructLevel
Same as structonly tag except that any struct level validations will not run.
Usage: nostructlevel
# Omit Empty
Allows conditional validation, for example, if a field is not set with
a value (Determined by the "required" validator) then other validation
such as min or max won't run, but if a value is set validation will run.
Usage: omitempty
# Omit Nil
Allows to skip the validation if the value is nil (same as omitempty, but
only for the nil-values).
Usage: omitnil
# Omit Zero
Allows to skip the validation if the value is a zero value.
For pointers, it checks if the pointer is nil or the underlying value is a zero value.
For slices and maps, it checks if the value is nil or empty.
Otherwise, behaves the same as omitempty.
Usage: omitzero
# Dive
This tells the validator to dive into a slice, array or map and validate that
level of the slice, array or map with the validation tags that follow.
Multidimensional nesting is also supported, each level you wish to dive will
require another dive tag. dive has some sub-tags, 'keys' & 'endkeys', please see
the Keys & EndKeys section just below.
Usage: dive
Example #1
[][]string with validation tag "gt=0,dive,len=1,dive,required"
// gt=0 will be applied to []
// len=1 will be applied to []string
// required will be applied to string
Example #2
[][]string with validation tag "gt=0,dive,dive,required"
// gt=0 will be applied to []
// []string will be spared validation
// required will be applied to string
Keys & EndKeys
These are to be used together directly after the dive tag and tells the validator
that anything between 'keys' and 'endkeys' applies to the keys of a map and not the
values; think of it like the 'dive' tag, but for map keys instead of values.
Multidimensional nesting is also supported, each level you wish to validate will
require another 'keys' and 'endkeys' tag. These tags are only valid for maps.
Usage: dive,keys,othertagvalidation(s),endkeys,valuevalidationtags
Example #1
map[string]string with validation tag "gt=0,dive,keys,eq=1|eq=2,endkeys,required"
// gt=0 will be applied to the map itself
// eq=1|eq=2 will be applied to the map keys
// required will be applied to map values
Example #2
map[[2]string]string with validation tag "gt=0,dive,keys,dive,eq=1|eq=2,endkeys,required"
// gt=0 will be applied to the map itself
// eq=1|eq=2 will be applied to each array element in the map keys
// required will be applied to map values
# Required
This validates that the value is not the data types default zero value.
For numbers ensures value is not zero. For strings ensures value is
not "". For booleans ensures value is not false. For slices, maps, pointers, interfaces, channels and functions
ensures the value is not nil. For structs ensures value is not the zero value when using WithRequiredStructEnabled.
Usage: required
# Required If
The field under validation must be present and not empty only if all
the other specified fields are equal to the value following the specified
field. For strings ensures value is not "". For slices, maps, pointers,
interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value.
Using the same field name multiple times in the parameters will result in a panic at runtime.
Usage: required_if
Examples:
// require the field if the Field1 is equal to the parameter given:
Usage: required_if=Field1 foobar
// require the field if the Field1 and Field2 is equal to the value respectively:
Usage: required_if=Field1 foo Field2 bar
# Required Unless
The field under validation must be present and not empty unless all
the other specified fields are equal to the value following the specified
field. For strings ensures value is not "". For slices, maps, pointers,
interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value.
Usage: required_unless
Examples:
// require the field unless the Field1 is equal to the parameter given:
Usage: required_unless=Field1 foobar
// require the field unless the Field1 and Field2 is equal to the value respectively:
Usage: required_unless=Field1 foo Field2 bar
# Required With
The field under validation must be present and not empty only if any
of the other specified fields are present. For strings ensures value is
not "". For slices, maps, pointers, interfaces, channels and functions
ensures the value is not nil. For structs ensures value is not the zero value.
Usage: required_with
Examples:
// require the field if the Field1 is present:
Usage: required_with=Field1
// require the field if the Field1 or Field2 is present:
Usage: required_with=Field1 Field2
# Required With All
The field under validation must be present and not empty only if all
of the other specified fields are present. For strings ensures value is
not "". For slices, maps, pointers, interfaces, channels and functions
ensures the value is not nil. For structs ensures value is not the zero value.
Usage: required_with_all
Example:
// require the field if the Field1 and Field2 is present:
Usage: required_with_all=Field1 Field2
# Required Without
The field under validation must be present and not empty only when any
of the other specified fields are not present. For strings ensures value is
not "". For slices, maps, pointers, interfaces, channels and functions
ensures the value is not nil. For structs ensures value is not the zero value.
Usage: required_without
Examples:
// require the field if the Field1 is not present:
Usage: required_without=Field1
// require the field if the Field1 or Field2 is not present:
Usage: required_without=Field1 Field2
# Required Without All
The field under validation must be present and not empty only when all
of the other specified fields are not present. For strings ensures value is
not "". For slices, maps, pointers, interfaces, channels and functions
ensures the value is not nil. For structs ensures value is not the zero value.
Usage: required_without_all
Example:
// require the field if the Field1 and Field2 is not present:
Usage: required_without_all=Field1 Field2
# Excluded If
The field under validation must not be present or not empty only if all
the other specified fields are equal to the value following the specified
field. For strings ensures value is not "". For slices, maps, pointers,
interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value.
Usage: excluded_if
Examples:
// exclude the field if the Field1 is equal to the parameter given:
Usage: excluded_if=Field1 foobar
// exclude the field if the Field1 and Field2 is equal to the value respectively:
Usage: excluded_if=Field1 foo Field2 bar
# Excluded Unless
The field under validation must not be present or empty unless all
the other specified fields are equal to the value following the specified
field. For strings ensures value is not "". For slices, maps, pointers,
interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value.
Usage: excluded_unless
Examples:
// exclude the field unless the Field1 is equal to the parameter given:
Usage: excluded_unless=Field1 foobar
// exclude the field unless the Field1 and Field2 is equal to the value respectively:
Usage: excluded_unless=Field1 foo Field2 bar
# Is Default
This validates that the value is the default value and is almost the
opposite of required.
Usage: isdefault
# Length
For numbers, length will ensure that the value is
equal to the parameter given. For strings, it checks that
the string length is exactly that number of characters. For slices,
arrays, and maps, validates the number of items.
Example #1
Usage: len=10
Example #2 (time.Duration)
For time.Duration, len will ensure that the value is equal to the duration given
in the parameter.
Usage: len=1h30m
# Maximum
For numbers, max will ensure that the value is
less than or equal to the parameter given. For strings, it checks
that the string length is at most that number of characters. For
slices, arrays, and maps, validates the number of items.
Example #1
Usage: max=10
Example #2 (time.Duration)
For time.Duration, max will ensure that the value is less than or equal to the
duration given in the parameter.
Usage: max=1h30m
# Minimum
For numbers, min will ensure that the value is
greater or equal to the parameter given. For strings, it checks that
the string length is at least that number of characters. For slices,
arrays, and maps, validates the number of items.
Example #1
Usage: min=10
Example #2 (time.Duration)
For time.Duration, min will ensure that the value is greater than or equal to
the duration given in the parameter.
Usage: min=1h30m
# Equals
For strings & numbers, eq will ensure that the value is
equal to the parameter given. For slices, arrays, and maps,
validates the number of items.
Example #1
Usage: eq=10
Example #2 (time.Duration)
For time.Duration, eq will ensure that the value is equal to the duration given
in the parameter.
Usage: eq=1h30m
# Not Equal
For strings & numbers, ne will ensure that the value is not
equal to the parameter given. For slices, arrays, and maps,
validates the number of items.
Example #1
Usage: ne=10
Example #2 (time.Duration)
For time.Duration, ne will ensure that the value is not equal to the duration
given in the parameter.
Usage: ne=1h30m
# One Of
For strings, ints, and uints, oneof will ensure that the value
is one of the values in the parameter. The parameter should be
a list of values separated by whitespace. Values may be
strings or numbers. To match strings with spaces in them, include
the target string between single quotes. Kind of like an 'enum'.
Usage: oneof=red green
oneof='red green' 'blue yellow'
oneof=5 7 9
# One Of Case Insensitive
Works the same as oneof but is case insensitive and therefore only accepts strings.
Usage: oneofci=red green
oneofci='red green' 'blue yellow'
# Greater Than
For numbers, this will ensure that the value is greater than the
parameter given. For strings, it checks that the string length
is greater than that number of characters. For slices, arrays
and maps it validates the number of items.
Example #1
Usage: gt=10
Example #2 (time.Time)
For time.Time ensures the time value is greater than time.Now.UTC().
Usage: gt
Example #3 (time.Duration)
For time.Duration, gt will ensure that the value is greater than the duration
given in the parameter.
Usage: gt=1h30m
# Greater Than or Equal
Same as 'min' above. Kept both to make terminology with 'len' easier.
Example #1
Usage: gte=10
Example #2 (time.Time)
For time.Time ensures the time value is greater than or equal to time.Now.UTC().
Usage: gte
Example #3 (time.Duration)
For time.Duration, gte will ensure that the value is greater than or equal to
the duration given in the parameter.
Usage: gte=1h30m
# Less Than
For numbers, this will ensure that the value is less than the parameter given.
For strings, it checks that the string length is less than that number of
characters. For slices, arrays, and maps it validates the number of items.
Example #1
Usage: lt=10
Example #2 (time.Time)
For time.Time ensures the time value is less than time.Now.UTC().
Usage: lt
Example #3 (time.Duration)
For time.Duration, lt will ensure that the value is less than the duration given
in the parameter.
Usage: lt=1h30m
# Less Than or Equal
Same as 'max' above. Kept both to make terminology with 'len' easier.
Example #1
Usage: lte=10
Example #2 (time.Time)
For time.Time ensures the time value is less than or equal to time.Now.UTC().
Usage: lte
Example #3 (time.Duration)
For time.Duration, lte will ensure that the value is less than or equal to the
duration given in the parameter.
Usage: lte=1h30m
# Field Equals Another Field
This will validate the field value against another fields value either within
a struct or passed in field.
Example #1:
// Validation on Password field using:
Usage: eqfield=ConfirmPassword
Example #2:
// Validating by field:
validate.VarWithValue(password, confirmpassword, "eqfield")
Field Equals Another Field (relative)
This does the same as eqfield except that it validates the field provided relative
to the top level struct.
Usage: eqcsfield=InnerStructField.Field)
# Field Does Not Equal Another Field
This will validate the field value against another fields value either within
a struct or passed in field.
Examples:
// Confirm two colors are not the same:
//
// Validation on Color field:
Usage: nefield=Color2
// Validating by field:
validate.VarWithValue(color1, color2, "nefield")
Field Does Not Equal Another Field (relative)
This does the same as nefield except that it validates the field provided
relative to the top level struct.
Usage: necsfield=InnerStructField.Field
# Field Greater Than Another Field
Only valid for Numbers, time.Duration and time.Time types, this will validate
the field value against another fields value either within a struct or passed in
field. usage examples are for validation of a Start and End date:
Example #1:
// Validation on End field using:
validate.Struct Usage(gtfield=Start)
Example #2:
// Validating by field:
validate.VarWithValue(start, end, "gtfield")
# Field Greater Than Another Relative Field
This does the same as gtfield except that it validates the field provided
relative to the top level struct.
Usage: gtcsfield=InnerStructField.Field
# Field Greater Than or Equal To Another Field
Only valid for Numbers, time.Duration and time.Time types, this will validate
the field value against another fields value either within a struct or passed in
field. usage examples are for validation of a Start and End date:
Example #1:
// Validation on End field using:
validate.Struct Usage(gtefield=Start)
Example #2:
// Validating by field:
validate.VarWithValue(start, end, "gtefield")
# Field Greater Than or Equal To Another Relative Field
This does the same as gtefield except that it validates the field provided relative
to the top level struct.
Usage: gtecsfield=InnerStructField.Field
# Less Than Another Field
Only valid for Numbers, time.Duration and time.Time types, this will validate
the field value against another fields value either within a struct or passed in
field. usage examples are for validation of a Start and End date:
Example #1:
// Validation on End field using:
validate.Struct Usage(ltfield=Start)
Example #2:
// Validating by field:
validate.VarWithValue(start, end, "ltfield")
# Less Than Another Relative Field
This does the same as ltfield except that it validates the field provided relative
to the top level struct.
Usage: ltcsfield=InnerStructField.Field
# Less Than or Equal To Another Field
Only valid for Numbers, time.Duration and time.Time types, this will validate
the field value against another fields value either within a struct or passed in
field. usage examples are for validation of a Start and End date:
Example #1:
// Validation on End field using:
validate.Struct Usage(ltefield=Start)
Example #2:
// Validating by field:
validate.VarWithValue(start, end, "ltefield")
# Less Than or Equal To Another Relative Field
This does the same as ltefield except that it validates the field provided relative
to the top level struct.
Usage: ltecsfield=InnerStructField.Field
# Field Contains Another Field
This does the same as contains except for struct fields. It should only be used
with string types. See the behavior of reflect.Value.String() for behavior on
other types.
Usage: containsfield=InnerStructField.Field
# Field Excludes Another Field
This does the same as excludes except for struct fields. It should only be used
with string types. See the behavior of reflect.Value.String() for behavior on
other types.
Usage: excludesfield=InnerStructField.Field
# Unique
For arrays & slices, unique will ensure that there are no duplicates.
For maps, unique will ensure that there are no duplicate values.
For slices of struct, unique will ensure that there are no duplicate values
in a field of the struct specified via a parameter.
// For arrays, slices, and maps:
Usage: unique
// For slices of struct:
Usage: unique=field
# ValidateFn
This validates that an object responds to a method that can return error or bool.
By default it expects an interface `Validate() error` and check that the method
does not return an error. Other methods can be specified using two signatures:
If the method returns an error, it check if the return value is nil.
If the method returns a boolean, it checks if the value is true.
// to use the default method Validate() error
Usage: validateFn
// to use the custom method IsValid() bool (or error)
Usage: validateFn=IsValid
# Alpha Only
This validates that a string value contains ASCII alpha characters only
Usage: alpha
# Alpha Space
This validates that a string value contains ASCII alpha characters and spaces only
Usage: alphaspace
# Alphanumeric
This validates that a string value contains ASCII alphanumeric characters only
Usage: alphanum
# Alphanumeric Space
This validates that a string value contains ASCII alphanumeric characters and spaces only
Usage: alphanumspace
# Alpha Unicode
This validates that a string value contains unicode alpha characters only
Usage: alphaunicode
# Alphanumeric Unicode
This validates that a string value contains unicode alphanumeric characters only
Usage: alphanumunicode
# Boolean
This validates that a string value can successfully be parsed into a boolean with strconv.ParseBool
Usage: boolean
# Number
This validates that a string value contains number values only.
For integers or float it returns true.
Usage: number
# Numeric
This validates that a string value contains a basic numeric value.
basic excludes exponents etc...
for integers or float it returns true.
Usage: numeric
# Hexadecimal String
This validates that a string value contains a valid hexadecimal.
Usage: hexadecimal
# Hexcolor String
This validates that a string value contains a valid hex color including
hashtag (#)
Usage: hexcolor
# Lowercase String
This validates that a string value contains only lowercase characters. An empty string is not a valid lowercase string.
Usage: lowercase
# Uppercase String
This validates that a string value contains only uppercase characters. An empty string is not a valid uppercase string.
Usage: uppercase
# RGB String
This validates that a string value contains a valid rgb color
Usage: rgb
# RGBA String
This validates that a string value contains a valid rgba color
Usage: rgba
# HSL String
This validates that a string value contains a valid hsl color
Usage: hsl
# HSLA String
This validates that a string value contains a valid hsla color
Usage: hsla
# E.164 Phone Number String
This validates that a string value contains a valid E.164 Phone number
https://en.wikipedia.org/wiki/E.164 (ex. +1123456789)
Usage: e164
# E-mail String
This validates that a string value contains a valid email
This may not conform to all possibilities of any rfc standard, but neither
does any email provider accept all possibilities.
Usage: email
# JSON String
This validates that a string value is valid JSON
Usage: json
# JWT String
This validates that a string value is a valid JWT
Usage: jwt
# File
This validates that a string value contains a valid file path and that
the file exists on the machine.
This is done using os.Stat, which is a platform independent function.
Usage: file
# Image path
This validates that a string value contains a valid file path and that
the file exists on the machine and is an image.
This is done using os.Stat and github.com/gabriel-vasile/mimetype
Usage: image
# File Path
This validates that a string value contains a valid file path but does not
validate the existence of that file.
This is done using os.Stat, which is a platform independent function.
Usage: filepath
# URL String
This validates that a string value contains a valid url
This will accept any url the golang request uri accepts but must contain
a schema for example http:// or rtmp://
Usage: url
# URI String
This validates that a string value contains a valid uri
This will accept any uri the golang request uri accepts
Usage: uri
# Urn RFC 2141 String
This validates that a string value contains a valid URN
according to the RFC 2141 spec.
Usage: urn_rfc2141
# Base32 String
This validates that a string value contains a valid bas324 value.
Although an empty string is valid base32 this will report an empty string
as an error, if you wish to accept an empty string as valid you can use
this with the omitempty tag.
Usage: base32
# Base64 String
This validates that a string value contains a valid base64 value.
Although an empty string is valid base64 this will report an empty string
as an error, if you wish to accept an empty string as valid you can use
this with the omitempty tag.
Usage: base64
# Base64URL String
This validates that a string value contains a valid base64 URL safe value
according the RFC4648 spec.
Although an empty string is a valid base64 URL safe value, this will report
an empty string as an error, if you wish to accept an empty string as valid
you can use this with the omitempty tag.
Usage: base64url
# Base64RawURL String
This validates that a string value contains a valid base64 URL safe value,
but without = padding, according the RFC4648 spec, section 3.2.
Although an empty string is a valid base64 URL safe value, this will report
an empty string as an error, if you wish to accept an empty string as valid
you can use this with the omitempty tag.
Usage: base64rawurl
# Bitcoin Address
This validates that a string value contains a valid bitcoin address.
The format of the string is checked to ensure it matches one of the three formats
P2PKH, P2SH and performs checksum validation.
Usage: btc_addr
Bitcoin Bech32 Address (segwit)
This validates that a string value contains a valid bitcoin Bech32 address as defined
by bip-0173 (https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)
Special thanks to Pieter Wuille for providing reference implementations.
Usage: btc_addr_bech32
# Ethereum Address
This validates that a string value contains a valid ethereum address.
The format of the string is checked to ensure it matches the standard Ethereum address format.
Usage: eth_addr
# Contains
This validates that a string value contains the substring value.
Usage: contains=@
# Contains Any
This validates that a string value contains any Unicode code points
in the substring value.
Usage: containsany=!@#?
# Contains Rune
This validates that a string value contains the supplied rune value.
Usage: containsrune=@
# Excludes
This validates that a string value does not contain the substring value.
Usage: excludes=@
# Excludes All
This validates that a string value does not contain any Unicode code
points in the substring value.
Usage: excludesall=!@#?
# Excludes Rune
This validates that a string value does not contain the supplied rune value.
Usage: excludesrune=@
# Starts With
This validates that a string value starts with the supplied string value
Usage: startswith=hello
# Ends With
This validates that a string value ends with the supplied string value
Usage: endswith=goodbye
# Does Not Start With
This validates that a string value does not start with the supplied string value
Usage: startsnotwith=hello
# Does Not End With
This validates that a string value does not end with the supplied string value
Usage: endsnotwith=goodbye
# International Standard Book Number
This validates that a string value contains a valid isbn10 or isbn13 value.
Usage: isbn
# International Standard Book Number 10
This validates that a string value contains a valid isbn10 value.
Usage: isbn10
# International Standard Book Number 13
This validates that a string value contains a valid isbn13 value.
Usage: isbn13
# Universally Unique Identifier UUID
This validates that a string value contains a valid UUID. Uppercase UUID values will not pass - use `uuid_rfc4122` instead.
Usage: uuid
# Universally Unique Identifier UUID v3
This validates that a string value contains a valid version 3 UUID. Uppercase UUID values will not pass - use `uuid3_rfc4122` instead.
Usage: uuid3
# Universally Unique Identifier UUID v4
This validates that a string value contains a valid version 4 UUID. Uppercase UUID values will not pass - use `uuid4_rfc4122` instead.
Usage: uuid4
# Universally Unique Identifier UUID v5
This validates that a string value contains a valid version 5 UUID. Uppercase UUID values will not pass - use `uuid5_rfc4122` instead.
Usage: uuid5
# Universally Unique Lexicographically Sortable Identifier ULID
This validates that a string value contains a valid ULID value.
Usage: ulid
# ASCII
This validates that a string value contains only ASCII characters.
NOTE: if the string is blank, this validates as true.
Usage: ascii
# Printable ASCII
This validates that a string value contains only printable ASCII characters.
NOTE: if the string is blank, this validates as true.
Usage: printascii
# Multi-Byte Characters
This validates that a string value contains one or more multibyte characters.
NOTE: if the string is blank, this validates as true.
Usage: multibyte
# Data URL
This validates that a string value contains a valid DataURI.
NOTE: this will also validate that the data portion is valid base64
Usage: datauri
# Latitude
This validates that a string value contains a valid latitude.
Usage: latitude
# Longitude
This validates that a string value contains a valid longitude.
Usage: longitude
# Employeer Identification Number EIN
This validates that a string value contains a valid U.S. Employer Identification Number.
Usage: ein
# Social Security Number SSN
This validates that a string value contains a valid U.S. Social Security Number.
Usage: ssn
# Internet Protocol Address IP
This validates that a string value contains a valid IP Address.
Usage: ip
# Internet Protocol Address IPv4
This validates that a string value contains a valid v4 IP Address.
Usage: ipv4
# Internet Protocol Address IPv6
This validates that a string value contains a valid v6 IP Address.
Usage: ipv6
# Classless Inter-Domain Routing CIDR
This validates that a string value contains a valid CIDR Address.
Usage: cidr
# Classless Inter-Domain Routing CIDRv4
This validates that a string value contains a valid v4 CIDR Address.
Usage: cidrv4
# Classless Inter-Domain Routing CIDRv6
This validates that a string value contains a valid v6 CIDR Address.
Usage: cidrv6
# Transmission Control Protocol Address TCP
This validates that a string value contains a valid resolvable TCP Address.
Usage: tcp_addr
# Transmission Control Protocol Address TCPv4
This validates that a string value contains a valid resolvable v4 TCP Address.
Usage: tcp4_addr
# Transmission Control Protocol Address TCPv6
This validates that a string value contains a valid resolvable v6 TCP Address.
Usage: tcp6_addr
# User Datagram Protocol Address UDP
This validates that a string value contains a valid resolvable UDP Address.
Usage: udp_addr
# User Datagram Protocol Address UDPv4
This validates that a string value contains a valid resolvable v4 UDP Address.
Usage: udp4_addr
# User Datagram Protocol Address UDPv6
This validates that a string value contains a valid resolvable v6 UDP Address.
Usage: udp6_addr
# Internet Protocol Address IP
This validates that a string value contains a valid resolvable IP Address.
Usage: ip_addr
# Internet Protocol Address IPv4
This validates that a string value contains a valid resolvable v4 IP Address.
Usage: ip4_addr
# Internet Protocol Address IPv6
This validates that a string value contains a valid resolvable v6 IP Address.
Usage: ip6_addr
# Unix domain socket end point Address
This validates that a string value contains a valid Unix Address.
Usage: unix_addr
# Unix Domain Socket Exists
This validates that a Unix domain socket file exists at the specified path.
It checks both filesystem-based sockets and Linux abstract sockets (prefixed with @).
For filesystem sockets, it verifies the path exists and is a socket file.
For abstract sockets on Linux, it checks /proc/net/unix.
Usage: uds_exists
# Media Access Control Address MAC
This validates that a string value contains a valid MAC Address.
Usage: mac
Note: See Go's ParseMAC for accepted formats and types:
http://golang.org/src/net/mac.go?s=866:918#L29
# Hostname RFC 952
This validates that a string value is a valid Hostname according to RFC 952 https://tools.ietf.org/html/rfc952
Usage: hostname
# Hostname RFC 1123
This validates that a string value is a valid Hostname according to RFC 1123 https://tools.ietf.org/html/rfc1123
Usage: hostname_rfc1123 or if you want to continue to use 'hostname' in your tags, create an alias.
Full Qualified Domain Name (FQDN)
This validates that a string value contains a valid FQDN.
Usage: fqdn
# HTML Tags
This validates that a string value appears to be an HTML element tag
including those described at https://developer.mozilla.org/en-US/docs/Web/HTML/Element
Usage: html
# HTML Encoded
This validates that a string value is a proper character reference in decimal
or hexadecimal format
Usage: html_encoded
# URL Encoded
This validates that a string value is percent-encoded (URL encoded) according
to https://tools.ietf.org/html/rfc3986#section-2.1
Usage: url_encoded
# Directory
This validates that a string value contains a valid directory and that
it exists on the machine.
This is done using os.Stat, which is a platform independent function.
Usage: dir
# Directory Path
This validates that a string value contains a valid directory but does
not validate the existence of that directory.
This is done using os.Stat, which is a platform independent function.
It is safest to suffix the string with os.PathSeparator if the directory
may not exist at the time of validation.
Usage: dirpath
# HostPort
This validates that a string value contains a valid DNS hostname and port that
can be used to validate fields typically passed to sockets and connections.
Usage: hostname_port
# Port
This validates that the value falls within the valid port number range of 1 to 65,535.
Usage: port
# Datetime
This validates that a string value is a valid datetime based on the supplied datetime format.
Supplied format must match the official Go time format layout as documented in https://golang.org/pkg/time/
Usage: datetime=2006-01-02
# Iso3166-1 alpha-2
This validates that a string value is a valid country code based on iso3166-1 alpha-2 standard.
see: https://www.iso.org/iso-3166-country-codes.html
Usage: iso3166_1_alpha2
# Iso3166-1 alpha-3
This validates that a string value is a valid country code based on iso3166-1 alpha-3 standard.
see: https://www.iso.org/iso-3166-country-codes.html
Usage: iso3166_1_alpha3
# Iso3166-1 alpha-numeric
This validates that a string value is a valid country code based on iso3166-1 alpha-numeric standard.
see: https://www.iso.org/iso-3166-country-codes.html
Usage: iso3166_1_alpha3
# BCP 47 Language Tag
This validates that a string value is a valid BCP 47 language tag, as parsed by language.Parse.
More information on https://pkg.go.dev/golang.org/x/text/language
Usage: bcp47_language_tag
BIC (SWIFT code - 2022 standard)
This validates that a string value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362:2022.
More information on https://www.iso.org/standard/84108.html
Usage: bic
BIC (SWIFT code - 2014 standard)
This validates that a string value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362:2014.
More information on https://www.iso.org/standard/60390.html
Usage: bic_iso_9362_2014
# RFC 1035 label
This validates that a string value is a valid dns RFC 1035 label, defined in RFC 1035.
More information on https://datatracker.ietf.org/doc/html/rfc1035
Usage: dns_rfc1035_label
# TimeZone
This validates that a string value is a valid time zone based on the time zone database present on the system.
Although empty value and Local value are allowed by time.LoadLocation golang function, they are not allowed by this validator.
More information on https://golang.org/pkg/time/#LoadLocation
Usage: timezone
# Semantic Version
This validates that a string value is a valid semver version, defined in Semantic Versioning 2.0.0.
More information on https://semver.org/
Usage: semver
# CVE Identifier
This validates that a string value is a valid cve id, defined in cve mitre.
More information on https://cve.mitre.org/
Usage: cve
# Credit Card
This validates that a string value contains a valid credit card number using Luhn algorithm.
Usage: credit_card
# Luhn Checksum
Usage: luhn_checksum
This validates that a string or (u)int value contains a valid checksum using the Luhn algorithm.
# MongoDB
This validates that a string is a valid 24 character hexadecimal string or valid connection string.
Usage: mongodb
mongodb_connection_string
Example:
type Test struct {
ObjectIdField string `validate:"mongodb"`
ConnectionStringField string `validate:"mongodb_connection_string"`
}
# Cron
This validates that a string value contains a valid cron expression.
Usage: cron
# SpiceDb ObjectID/Permission/Object Type
This validates that a string is valid for use with SpiceDb for the indicated purpose. If no purpose is given, a purpose of 'id' is assumed.
Usage: spicedb=id|permission|type
# Alias Validators and Tags
Alias Validators and Tags
NOTE: When returning an error, the tag returned in "FieldError" will be
the alias tag unless the dive tag is part of the alias. Everything after the
dive tag is not reported as the alias tag. Also, the "ActualTag" in the before
case will be the actual tag within the alias that failed.
Here is a list of the current built in alias tags:
"iscolor"
alias is "hexcolor|rgb|rgba|hsl|hsla" (Usage: iscolor)
"country_code"
alias is "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric" (Usage: country_code)
Validator notes:
regex
a regex validator won't be added because commas and = signs can be part
of a regex which conflict with the validation definitions. Although
workarounds can be made, they take away from using pure regex's.
Furthermore it's quick and dirty but the regex's become harder to
maintain and are not reusable, so it's as much a programming philosophy
as anything.
In place of this new validator functions should be created; a regex can
be used within the validator function and even be precompiled for better
efficiency within regexes.go.
And the best reason, you can submit a pull request and we can keep on
adding to the validation library of this package!
# Non standard validators
A collection of validation rules that are frequently needed but are more
complex than the ones found in the baked in validators.
A non standard validator must be registered manually like you would
with your own custom validation functions.
Example of registration and use:
type Test struct {
TestField string `validate:"yourtag"`
}
t := &Test{
TestField: "Test"
}
validate := validator.New()
validate.RegisterValidation("yourtag", validators.NotBlank)
Here is a list of the current non standard validators:
NotBlank
This validates that the value is not blank or with length zero.
For strings ensures they do not contain only spaces. For channels, maps, slices and arrays
ensures they don't have zero length. For others, a non empty value is required.
Usage: notblank
# Panics
This package panics when bad input is provided, this is by design, bad code like
that should not make it to production.
type Test struct {
TestField string `validate:"nonexistentfunction=1"`
}
t := &Test{
TestField: "Test"
}
validate.Struct(t) // this will panic
*/
package validator
golang-github-go-playground-validator-v10-10.30.1/errors.go 0000664 0000000 0000000 00000016612 15124100770 0023425 0 ustar 00root root 0000000 0000000 package validator
import (
"bytes"
"fmt"
"reflect"
"strings"
ut "github.com/go-playground/universal-translator"
)
const (
fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
)
// ValidationErrorsTranslations is the translation return type
type ValidationErrorsTranslations map[string]string
// InvalidValidationError describes an invalid argument passed to
// `Struct`, `StructExcept`, StructPartial` or `Field`
type InvalidValidationError struct {
Type reflect.Type
}
// Error returns InvalidValidationError message
func (e *InvalidValidationError) Error() string {
if e.Type == nil {
return "validator: (nil)"
}
return "validator: (nil " + e.Type.String() + ")"
}
// ValidationErrors is an array of FieldError's
// for use in custom error messages post validation.
type ValidationErrors []FieldError
// Error is intended for use in development + debugging and not intended to be a production error message.
// It allows ValidationErrors to subscribe to the Error interface.
// All information to create an error message specific to your application is contained within
// the FieldError found within the ValidationErrors array
func (ve ValidationErrors) Error() string {
buff := bytes.NewBufferString("")
for i := 0; i < len(ve); i++ {
buff.WriteString(ve[i].Error())
buff.WriteString("\n")
}
return strings.TrimSpace(buff.String())
}
// Translate translates all of the ValidationErrors
func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
trans := make(ValidationErrorsTranslations)
var fe *fieldError
for i := 0; i < len(ve); i++ {
fe = ve[i].(*fieldError)
// // in case an Anonymous struct was used, ensure that the key
// // would be 'Username' instead of ".Username"
// if len(fe.ns) > 0 && fe.ns[:1] == "." {
// trans[fe.ns[1:]] = fe.Translate(ut)
// continue
// }
trans[fe.ns] = fe.Translate(ut)
}
return trans
}
// FieldError contains all functions to get error details
type FieldError interface {
// Tag returns the validation tag that failed. if the
// validation was an alias, this will return the
// alias name and not the underlying tag that failed.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "iscolor"
Tag() string
// ActualTag returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
// If an 'or' validation fails the entire or will be returned.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "hexcolor|rgb|rgba|hsl|hsla"
ActualTag() string
// Namespace returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
//
// eg. JSON name "User.fname"
//
// See StructNamespace() for a version that returns actual names.
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract it's name
Namespace() string
// StructNamespace returns the namespace for the field error, with the field's
// actual name.
//
// eg. "User.FirstName" see Namespace for comparison
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract its name
StructNamespace() string
// Field returns the field's name with the tag name taking precedence over the
// field's actual name.
//
// `RegisterTagNameFunc` must be registered to get tag value.
//
// eg. JSON name "fname"
// see StructField for comparison
Field() string
// StructField returns the field's actual name from the struct, when able to determine.
//
// eg. "FirstName"
// see Field for comparison
StructField() string
// Value returns the actual field's value in case needed for creating the error
// message
Value() interface{}
// Param returns the param value, in string form for comparison; this will also
// help with generating an error message
Param() string
// Kind returns the Field's reflect Kind
//
// eg. time.Time's kind is a struct
Kind() reflect.Kind
// Type returns the Field's reflect Type
//
// eg. time.Time's type is time.Time
Type() reflect.Type
// Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translator can be found it returns the same as
// calling fe.Error()
Translate(ut ut.Translator) string
// Error returns the FieldError's message
Error() string
}
// compile time interface checks
var _ FieldError = new(fieldError)
var _ error = new(fieldError)
// fieldError contains a single field's validation error along
// with other properties that may be needed for error message creation
// it complies with the FieldError interface
type fieldError struct {
v *Validate
tag string
actualTag string
ns string
structNs string
fieldLen uint8
structfieldLen uint8
value interface{}
param string
kind reflect.Kind
typ reflect.Type
}
// Tag returns the validation tag that failed.
func (fe *fieldError) Tag() string {
return fe.tag
}
// ActualTag returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
func (fe *fieldError) ActualTag() string {
return fe.actualTag
}
// Namespace returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
func (fe *fieldError) Namespace() string {
return fe.ns
}
// StructNamespace returns the namespace for the field error, with the field's
// actual name.
func (fe *fieldError) StructNamespace() string {
return fe.structNs
}
// Field returns the field's name with the tag name taking precedence over the
// field's actual name.
func (fe *fieldError) Field() string {
return fe.ns[len(fe.ns)-int(fe.fieldLen):]
// // return fe.field
// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
// log.Println("FLD:", fld)
// if len(fld) > 0 && fld[:1] == "." {
// return fld[1:]
// }
// return fld
}
// StructField returns the field's actual name from the struct, when able to determine.
func (fe *fieldError) StructField() string {
// return fe.structField
return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
}
// Value returns the actual field's value in case needed for creating the error
// message
func (fe *fieldError) Value() interface{} {
return fe.value
}
// Param returns the param value, in string form for comparison; this will
// also help with generating an error message
func (fe *fieldError) Param() string {
return fe.param
}
// Kind returns the Field's reflect Kind
func (fe *fieldError) Kind() reflect.Kind {
return fe.kind
}
// Type returns the Field's reflect Type
func (fe *fieldError) Type() reflect.Type {
return fe.typ
}
// Error returns the fieldError's error message
func (fe *fieldError) Error() string {
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
}
// Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translation can be found, it returns the original
// untranslated error message.
func (fe *fieldError) Translate(ut ut.Translator) string {
var fn TranslationFunc
m, ok := fe.v.transTagFunc[ut]
if !ok {
return fe.Error()
}
fn, ok = m[fe.tag]
if !ok {
fn, ok = m[fe.actualTag]
if !ok {
return fe.Error()
}
}
return fn(ut, fe)
}
golang-github-go-playground-validator-v10-10.30.1/field_level.go 0000664 0000000 0000000 00000011474 15124100770 0024364 0 ustar 00root root 0000000 0000000 package validator
import "reflect"
// FieldLevel contains all the information and helper functions
// to validate a field
type FieldLevel interface {
// Top returns the top level struct, if any
Top() reflect.Value
// Parent returns the current fields parent struct, if any or
// the comparison value if called 'VarWithValue'
Parent() reflect.Value
// Field returns current field for validation
Field() reflect.Value
// FieldName returns the field's name with the tag
// name taking precedence over the fields actual name.
FieldName() string
// StructFieldName returns the struct field's name
StructFieldName() string
// Param returns param for validation against current field
Param() string
// GetTag returns the current validations tag name
GetTag() string
// ExtractType gets the actual underlying type of field value.
// It will dive into pointers, customTypes and return you the
// underlying value and it's kind.
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
// GetStructFieldOK traverses the parent struct to retrieve a specific field denoted by the provided namespace
// in the param and returns the field, field kind and whether is was successful in retrieving
// the field at all.
//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
//
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
GetStructFieldOK() (reflect.Value, reflect.Kind, bool)
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
//
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool)
// GetStructFieldOK2 traverses the parent struct to retrieve a specific field denoted by the provided namespace
// in the param and returns the field, field kind, if it's a nullable type and whether is was successful in retrieving
// the field at all.
//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool)
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool)
}
var _ FieldLevel = new(validate)
// Field returns current field for validation
func (v *validate) Field() reflect.Value {
return v.flField
}
// FieldName returns the field's name with the tag
// name taking precedence over the fields actual name.
func (v *validate) FieldName() string {
return v.cf.altName
}
// GetTag returns the current validations tag name
func (v *validate) GetTag() string {
return v.ct.tag
}
// StructFieldName returns the struct field's name
func (v *validate) StructFieldName() string {
return v.cf.name
}
// Param returns param for validation against current field
func (v *validate) Param() string {
return v.ct.param
}
// GetStructFieldOK returns Param returns param for validation against current field
//
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) {
current, kind, _, found := v.getStructFieldOKInternal(v.slflParent, v.ct.param)
return current, kind, found
}
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
//
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
func (v *validate) GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {
current, kind, _, found := v.GetStructFieldOKAdvanced2(val, namespace)
return current, kind, found
}
// GetStructFieldOK2 returns Param returns param for validation against current field
func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) {
return v.getStructFieldOKInternal(v.slflParent, v.ct.param)
}
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) {
return v.getStructFieldOKInternal(val, namespace)
}
golang-github-go-playground-validator-v10-10.30.1/go.mod 0000664 0000000 0000000 00000000606 15124100770 0022664 0 ustar 00root root 0000000 0000000 module github.com/go-playground/validator/v10
go 1.24.0
require (
github.com/gabriel-vasile/mimetype v1.4.12
github.com/go-playground/assert/v2 v2.2.0
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/leodido/go-urn v1.4.0
golang.org/x/crypto v0.46.0
golang.org/x/text v0.32.0
)
require golang.org/x/sys v0.39.0 // indirect
golang-github-go-playground-validator-v10-10.30.1/go.sum 0000664 0000000 0000000 00000004040 15124100770 0022705 0 ustar 00root root 0000000 0000000 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
golang-github-go-playground-validator-v10-10.30.1/logo.png 0000664 0000000 0000000 00000032203 15124100770 0023222 0 ustar 00root root 0000000 0000000 PNG
IHDR <q sBIT|d pHYs ~ tEXtSoftware Adobe Fireworks CS6輲 IDATxwEǿ=yg6/,yQEATD1+S99';Sp(&T(y 8?gwfمe}>=5]ݿyz)!hkhcXhtbu]A:ՁvA:. V@Xhtbu]A:Ձvmww Y n H2, gA_5P ߀ŷTⱄ >ޜSdurgd32]4\TcD0a
jk"@xkAMi`;(Rw= PlgWV~=3x{ڥ+ޜN2px9]GhBD@H R"M#%&PVJu*6t*Y
E+~[X?C˒JF Gdxul
%#/Lt)%f4b&HEZlA4m6R,-bw?*PĊ#T8ov)}?!m݆ [wt#" #
cICw:9]DA,_ƪ9ۧ.+_F?,uٳEtGCNAM 0]4]Chz3
CXlN6
,}-5Ғ{O1eݓ(")e"v{k4붤s~>'N!WoZpȪ{Ӊ.^͵ls:ќ.TQS^:L2:uI!`CeKGg)tB'{,ᤦxk`ekW!:RJ+~)BRKȲ0ΙJȈRMB\AG{!Z63 tu5` Mqy}x|>tM#`D#먔\nE\Etrt"AqE[B9]7(zJÈ 0|]_:uv76}\4#BMVV_y~]Y[w\IE,K!>H7χSYX?X>}5꼋@$MQ/ث*M'jTv\={`D 4려F,U5|>`:uw
7/͏?SOzNH fqgo9dꍿ$͆ӗJ||ߢ?|{)03ɕ4IJHe&d̛vn5hv;`i*Eddr0cWcw: B,h+1vpƏ9!CpP[QNڵ|?>n<8k*]e;}հ3q/͗_!hލJsO<γ} Sg"?RR2X9S{Q{i2zAFF8>3k.I6?%C:
ޟy.н V+_PvG|~߭z@eeX2~gn~G\4&q)qgfGa[01<Y (K35ysy/~:YJYN#XIϾ2@Fw80#ay_u!/ PV+5?cgvϝ3a5{UrF!T]
2t'M۩~