mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
Grand test fixup (#138)
* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
This commit is contained in:
30
vendor/github.com/go-playground/validator/v10/.gitignore
generated
vendored
Normal file
30
vendor/github.com/go-playground/validator/v10/.gitignore
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# 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
|
||||
cover.html
|
||||
README.html
|
22
vendor/github.com/go-playground/validator/v10/LICENSE
generated
vendored
Normal file
22
vendor/github.com/go-playground/validator/v10/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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.
|
||||
|
16
vendor/github.com/go-playground/validator/v10/MAINTAINERS.md
generated
vendored
Normal file
16
vendor/github.com/go-playground/validator/v10/MAINTAINERS.md
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
## 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.
|
18
vendor/github.com/go-playground/validator/v10/Makefile
generated
vendored
Normal file
18
vendor/github.com/go-playground/validator/v10/Makefile
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
GOCMD=GO111MODULE=on 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 v1.39.0; \
|
||||
}
|
||||
|
||||
lint: linters-install
|
||||
golangci-lint run
|
||||
|
||||
test:
|
||||
$(GOCMD) test -cover -race ./...
|
||||
|
||||
bench:
|
||||
$(GOCMD) test -bench=. -benchmem ./...
|
||||
|
||||
.PHONY: test lint linters-install
|
304
vendor/github.com/go-playground/validator/v10/README.md
generated
vendored
Normal file
304
vendor/github.com/go-playground/validator/v10/README.md
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
Package validator
|
||||
=================
|
||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v9/logo.png">[](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||

|
||||
[](https://travis-ci.org/go-playground/validator)
|
||||
[](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)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Use go get.
|
||||
|
||||
go get github.com/go-playground/validator
|
||||
|
||||
Then import the validator package into your own code.
|
||||
|
||||
import "github.com/go-playground/validator"
|
||||
|
||||
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
|
||||
------
|
||||
|
||||
### Fields:
|
||||
|
||||
| Tag | Description |
|
||||
| - | - |
|
||||
| eqcsfield | Field Equals Another Field (relative)|
|
||||
| eqfield | Field Equals Another Field |
|
||||
| fieldcontains | NOT DOCUMENTED IN doc.go |
|
||||
| fieldexcludes | NOT DOCUMENTED IN doc.go |
|
||||
| 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_port | HostPort |
|
||||
| hostname_rfc1123 | Hostname RFC 1123 |
|
||||
| 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 |
|
||||
| uri | URI String |
|
||||
| url | URL String |
|
||||
| url_encoded | URL Encoded |
|
||||
| urn_rfc2141 | Urn RFC 2141 String |
|
||||
|
||||
### Strings:
|
||||
|
||||
| Tag | Description |
|
||||
| - | - |
|
||||
| alpha | Alpha Only |
|
||||
| alphanum | Alphanumeric |
|
||||
| alphanumunicode | Alphanumeric Unicode |
|
||||
| alphaunicode | Alpha Unicode |
|
||||
| ascii | ASCII |
|
||||
| contains | Contains |
|
||||
| containsany | Contains Any |
|
||||
| containsrune | Contains Rune |
|
||||
| endswith | Ends With |
|
||||
| lowercase | Lowercase |
|
||||
| multibyte | Multi-Byte Characters |
|
||||
| number | NOT DOCUMENTED IN doc.go |
|
||||
| numeric | Numeric |
|
||||
| printascii | Printable ASCII |
|
||||
| startswith | Starts With |
|
||||
| uppercase | Uppercase |
|
||||
|
||||
### Format:
|
||||
| Tag | Description |
|
||||
| - | - |
|
||||
| base64 | Base64 String |
|
||||
| base64url | Base64URL String |
|
||||
| btc_addr | Bitcoin Address |
|
||||
| btc_addr_bech32 | Bitcoin Bech32 Address (segwit) |
|
||||
| datetime | Datetime |
|
||||
| e164 | e164 formatted phone 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 |
|
||||
| json | JSON |
|
||||
| latitude | Latitude |
|
||||
| longitude | Longitude |
|
||||
| rgb | RGB String |
|
||||
| rgba | RGBA String |
|
||||
| ssn | Social Security Number SSN |
|
||||
| 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 |
|
||||
|
||||
### Comparisons:
|
||||
| Tag | Description |
|
||||
| - | - |
|
||||
| eq | Equals |
|
||||
| gt | Greater than|
|
||||
| gte |Greater than or equal |
|
||||
| lt | Less Than |
|
||||
| lte | Less Than or Equal |
|
||||
| ne | Not Equal |
|
||||
|
||||
### Other:
|
||||
| Tag | Description |
|
||||
| - | - |
|
||||
| dir | Directory |
|
||||
| endswith | Ends With |
|
||||
| excludes | Excludes |
|
||||
| excludesall | Excludes All |
|
||||
| excludesrune | Excludes Rune |
|
||||
| file | File path |
|
||||
| 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_with | Excluded With |
|
||||
| excluded_with_all | Excluded With All |
|
||||
| excluded_without | Excluded Without |
|
||||
| excluded_without_all | Excluded Without All |
|
||||
| unique | Unique |
|
||||
|
||||
Benchmarks
|
||||
------
|
||||
###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64
|
||||
```go
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
pkg: github.com/go-playground/validator
|
||||
BenchmarkFieldSuccess-8 20000000 83.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkFieldSuccessParallel-8 50000000 26.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkFieldFailure-8 5000000 291 ns/op 208 B/op 4 allocs/op
|
||||
BenchmarkFieldFailureParallel-8 20000000 107 ns/op 208 B/op 4 allocs/op
|
||||
BenchmarkFieldArrayDiveSuccess-8 2000000 623 ns/op 201 B/op 11 allocs/op
|
||||
BenchmarkFieldArrayDiveSuccessParallel-8 10000000 237 ns/op 201 B/op 11 allocs/op
|
||||
BenchmarkFieldArrayDiveFailure-8 2000000 859 ns/op 412 B/op 16 allocs/op
|
||||
BenchmarkFieldArrayDiveFailureParallel-8 5000000 335 ns/op 413 B/op 16 allocs/op
|
||||
BenchmarkFieldMapDiveSuccess-8 1000000 1292 ns/op 432 B/op 18 allocs/op
|
||||
BenchmarkFieldMapDiveSuccessParallel-8 3000000 467 ns/op 432 B/op 18 allocs/op
|
||||
BenchmarkFieldMapDiveFailure-8 1000000 1082 ns/op 512 B/op 16 allocs/op
|
||||
BenchmarkFieldMapDiveFailureParallel-8 5000000 425 ns/op 512 B/op 16 allocs/op
|
||||
BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1539 ns/op 480 B/op 21 allocs/op
|
||||
BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 613 ns/op 480 B/op 21 allocs/op
|
||||
BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1413 ns/op 721 B/op 21 allocs/op
|
||||
BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 575 ns/op 721 B/op 21 allocs/op
|
||||
BenchmarkFieldCustomTypeSuccess-8 10000000 216 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkFieldCustomTypeSuccessParallel-8 20000000 82.2 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkFieldCustomTypeFailure-8 5000000 274 ns/op 208 B/op 4 allocs/op
|
||||
BenchmarkFieldCustomTypeFailureParallel-8 20000000 116 ns/op 208 B/op 4 allocs/op
|
||||
BenchmarkFieldOrTagSuccess-8 2000000 740 ns/op 16 B/op 1 allocs/op
|
||||
BenchmarkFieldOrTagSuccessParallel-8 3000000 474 ns/op 16 B/op 1 allocs/op
|
||||
BenchmarkFieldOrTagFailure-8 3000000 471 ns/op 224 B/op 5 allocs/op
|
||||
BenchmarkFieldOrTagFailureParallel-8 3000000 414 ns/op 224 B/op 5 allocs/op
|
||||
BenchmarkStructLevelValidationSuccess-8 10000000 213 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkStructLevelValidationSuccessParallel-8 20000000 91.8 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkStructLevelValidationFailure-8 3000000 473 ns/op 304 B/op 8 allocs/op
|
||||
BenchmarkStructLevelValidationFailureParallel-8 10000000 234 ns/op 304 B/op 8 allocs/op
|
||||
BenchmarkStructSimpleCustomTypeSuccess-8 5000000 385 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 161 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkStructSimpleCustomTypeFailure-8 2000000 640 ns/op 424 B/op 9 allocs/op
|
||||
BenchmarkStructSimpleCustomTypeFailureParallel-8 5000000 318 ns/op 440 B/op 10 allocs/op
|
||||
BenchmarkStructFilteredSuccess-8 2000000 597 ns/op 288 B/op 9 allocs/op
|
||||
BenchmarkStructFilteredSuccessParallel-8 10000000 266 ns/op 288 B/op 9 allocs/op
|
||||
BenchmarkStructFilteredFailure-8 3000000 454 ns/op 256 B/op 7 allocs/op
|
||||
BenchmarkStructFilteredFailureParallel-8 10000000 214 ns/op 256 B/op 7 allocs/op
|
||||
BenchmarkStructPartialSuccess-8 3000000 502 ns/op 256 B/op 6 allocs/op
|
||||
BenchmarkStructPartialSuccessParallel-8 10000000 225 ns/op 256 B/op 6 allocs/op
|
||||
BenchmarkStructPartialFailure-8 2000000 702 ns/op 480 B/op 11 allocs/op
|
||||
BenchmarkStructPartialFailureParallel-8 5000000 329 ns/op 480 B/op 11 allocs/op
|
||||
BenchmarkStructExceptSuccess-8 2000000 793 ns/op 496 B/op 12 allocs/op
|
||||
BenchmarkStructExceptSuccessParallel-8 10000000 193 ns/op 240 B/op 5 allocs/op
|
||||
BenchmarkStructExceptFailure-8 2000000 639 ns/op 464 B/op 10 allocs/op
|
||||
BenchmarkStructExceptFailureParallel-8 5000000 300 ns/op 464 B/op 10 allocs/op
|
||||
BenchmarkStructSimpleCrossFieldSuccess-8 3000000 417 ns/op 72 B/op 3 allocs/op
|
||||
BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 163 ns/op 72 B/op 3 allocs/op
|
||||
BenchmarkStructSimpleCrossFieldFailure-8 2000000 645 ns/op 304 B/op 8 allocs/op
|
||||
BenchmarkStructSimpleCrossFieldFailureParallel-8 5000000 285 ns/op 304 B/op 8 allocs/op
|
||||
BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 588 ns/op 80 B/op 4 allocs/op
|
||||
BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 221 ns/op 80 B/op 4 allocs/op
|
||||
BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 868 ns/op 320 B/op 9 allocs/op
|
||||
BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 337 ns/op 320 B/op 9 allocs/op
|
||||
BenchmarkStructSimpleSuccess-8 5000000 260 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkStructSimpleSuccessParallel-8 20000000 90.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkStructSimpleFailure-8 2000000 619 ns/op 424 B/op 9 allocs/op
|
||||
BenchmarkStructSimpleFailureParallel-8 5000000 296 ns/op 424 B/op 9 allocs/op
|
||||
BenchmarkStructComplexSuccess-8 1000000 1454 ns/op 128 B/op 8 allocs/op
|
||||
BenchmarkStructComplexSuccessParallel-8 3000000 579 ns/op 128 B/op 8 allocs/op
|
||||
BenchmarkStructComplexFailure-8 300000 4140 ns/op 3041 B/op 53 allocs/op
|
||||
BenchmarkStructComplexFailureParallel-8 1000000 2127 ns/op 3041 B/op 53 allocs/op
|
||||
BenchmarkOneof-8 10000000 140 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkOneofParallel-8 20000000 70.1 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...
|
||||
|
||||
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
|
2372
vendor/github.com/go-playground/validator/v10/baked_in.go
generated
vendored
Normal file
2372
vendor/github.com/go-playground/validator/v10/baked_in.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
322
vendor/github.com/go-playground/validator/v10/cache.go
generated
vendored
Normal file
322
vendor/github.com/go-playground/validator/v10/cache.go
generated
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type tagType uint8
|
||||
|
||||
const (
|
||||
typeDefault tagType = iota
|
||||
typeOmitEmpty
|
||||
typeIsDefault
|
||||
typeNoStructLevel
|
||||
typeStructOnly
|
||||
typeDive
|
||||
typeOr
|
||||
typeKeys
|
||||
typeEndKeys
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
var ctag *cTag
|
||||
var fld reflect.StructField
|
||||
var tag string
|
||||
var customName string
|
||||
|
||||
for i := 0; i < numFields; i++ {
|
||||
|
||||
fld = typ.Field(i)
|
||||
|
||||
if !fld.Anonymous && len(fld.PkgPath) > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
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
|
||||
continue
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
current.typeof = typeKeys
|
||||
|
||||
// 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)
|
||||
continue
|
||||
|
||||
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 omitempty:
|
||||
current.typeof = typeOmitEmpty
|
||||
continue
|
||||
|
||||
case structOnlyTag:
|
||||
current.typeof = typeStructOnly
|
||||
continue
|
||||
|
||||
case noStructLevelTag:
|
||||
current.typeof = typeNoStructLevel
|
||||
continue
|
||||
|
||||
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.runValidatinOnNil
|
||||
} else {
|
||||
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
|
||||
}
|
||||
|
||||
if len(orVals) > 1 {
|
||||
current.typeof = typeOr
|
||||
}
|
||||
|
||||
if len(vals) > 1 {
|
||||
current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
1132
vendor/github.com/go-playground/validator/v10/country_codes.go
generated
vendored
Normal file
1132
vendor/github.com/go-playground/validator/v10/country_codes.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1322
vendor/github.com/go-playground/validator/v10/doc.go
generated
vendored
Normal file
1322
vendor/github.com/go-playground/validator/v10/doc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
275
vendor/github.com/go-playground/validator/v10/errors.go
generated
vendored
Normal file
275
vendor/github.com/go-playground/validator/v10/errors.go
generated
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
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("")
|
||||
|
||||
var fe *fieldError
|
||||
|
||||
for i := 0; i < len(ve); i++ {
|
||||
|
||||
fe = ve[i].(*fieldError)
|
||||
buff.WriteString(fe.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.
|
||||
//
|
||||
// eq. "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 fields name with the tag name taking precedence over the
|
||||
// field's actual name.
|
||||
//
|
||||
// eq. JSON name "fname"
|
||||
// see StructField for comparison
|
||||
Field() string
|
||||
|
||||
// StructField returns the field's actual name from the struct, when able to determine.
|
||||
//
|
||||
// eq. "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 {
|
||||
|
||||
m, ok := fe.v.transTagFunc[ut]
|
||||
if !ok {
|
||||
return fe.Error()
|
||||
}
|
||||
|
||||
fn, ok := m[fe.tag]
|
||||
if !ok {
|
||||
return fe.Error()
|
||||
}
|
||||
|
||||
return fn(ut, fe)
|
||||
}
|
120
vendor/github.com/go-playground/validator/v10/field_level.go
generated
vendored
Normal file
120
vendor/github.com/go-playground/validator/v10/field_level.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
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)
|
||||
}
|
12
vendor/github.com/go-playground/validator/v10/go.mod
generated
vendored
Normal file
12
vendor/github.com/go-playground/validator/v10/go.mod
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
module github.com/go-playground/validator/v10
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/go-playground/assert/v2 v2.0.1
|
||||
github.com/go-playground/locales v0.13.0
|
||||
github.com/go-playground/universal-translator v0.17.0
|
||||
github.com/leodido/go-urn v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/text v0.3.2 // indirect
|
||||
)
|
33
vendor/github.com/go-playground/validator/v10/go.sum
generated
vendored
Normal file
33
vendor/github.com/go-playground/validator/v10/go.sum
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
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/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
BIN
vendor/github.com/go-playground/validator/v10/logo.png
generated
vendored
Normal file
BIN
vendor/github.com/go-playground/validator/v10/logo.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
173
vendor/github.com/go-playground/validator/v10/postcode_regexes.go
generated
vendored
Normal file
173
vendor/github.com/go-playground/validator/v10/postcode_regexes.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
package validator
|
||||
|
||||
import "regexp"
|
||||
|
||||
var postCodePatternDict = map[string]string{
|
||||
"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`,
|
||||
"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
|
||||
"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
|
||||
"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
|
||||
"US": `^\d{5}([ \-]\d{4})?$`,
|
||||
"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`,
|
||||
"DE": `^\d{5}$`,
|
||||
"JP": `^\d{3}-\d{4}$`,
|
||||
"FR": `^\d{2}[ ]?\d{3}$`,
|
||||
"AU": `^\d{4}$`,
|
||||
"IT": `^\d{5}$`,
|
||||
"CH": `^\d{4}$`,
|
||||
"AT": `^\d{4}$`,
|
||||
"ES": `^\d{5}$`,
|
||||
"NL": `^\d{4}[ ]?[A-Z]{2}$`,
|
||||
"BE": `^\d{4}$`,
|
||||
"DK": `^\d{4}$`,
|
||||
"SE": `^\d{3}[ ]?\d{2}$`,
|
||||
"NO": `^\d{4}$`,
|
||||
"BR": `^\d{5}[\-]?\d{3}$`,
|
||||
"PT": `^\d{4}([\-]\d{3})?$`,
|
||||
"FI": `^\d{5}$`,
|
||||
"AX": `^22\d{3}$`,
|
||||
"KR": `^\d{3}[\-]\d{3}$`,
|
||||
"CN": `^\d{6}$`,
|
||||
"TW": `^\d{3}(\d{2})?$`,
|
||||
"SG": `^\d{6}$`,
|
||||
"DZ": `^\d{5}$`,
|
||||
"AD": `^AD\d{3}$`,
|
||||
"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`,
|
||||
"AM": `^(37)?\d{4}$`,
|
||||
"AZ": `^\d{4}$`,
|
||||
"BH": `^((1[0-2]|[2-9])\d{2})?$`,
|
||||
"BD": `^\d{4}$`,
|
||||
"BB": `^(BB\d{5})?$`,
|
||||
"BY": `^\d{6}$`,
|
||||
"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`,
|
||||
"BA": `^\d{5}$`,
|
||||
"IO": `^BBND 1ZZ$`,
|
||||
"BN": `^[A-Z]{2}[ ]?\d{4}$`,
|
||||
"BG": `^\d{4}$`,
|
||||
"KH": `^\d{5}$`,
|
||||
"CV": `^\d{4}$`,
|
||||
"CL": `^\d{7}$`,
|
||||
"CR": `^\d{4,5}|\d{3}-\d{4}$`,
|
||||
"HR": `^\d{5}$`,
|
||||
"CY": `^\d{4}$`,
|
||||
"CZ": `^\d{3}[ ]?\d{2}$`,
|
||||
"DO": `^\d{5}$`,
|
||||
"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`,
|
||||
"EG": `^\d{5}$`,
|
||||
"EE": `^\d{5}$`,
|
||||
"FO": `^\d{3}$`,
|
||||
"GE": `^\d{4}$`,
|
||||
"GR": `^\d{3}[ ]?\d{2}$`,
|
||||
"GL": `^39\d{2}$`,
|
||||
"GT": `^\d{5}$`,
|
||||
"HT": `^\d{4}$`,
|
||||
"HN": `^(?:\d{5})?$`,
|
||||
"HU": `^\d{4}$`,
|
||||
"IS": `^\d{3}$`,
|
||||
"IN": `^\d{6}$`,
|
||||
"ID": `^\d{5}$`,
|
||||
"IL": `^\d{5}$`,
|
||||
"JO": `^\d{5}$`,
|
||||
"KZ": `^\d{6}$`,
|
||||
"KE": `^\d{5}$`,
|
||||
"KW": `^\d{5}$`,
|
||||
"LA": `^\d{5}$`,
|
||||
"LV": `^\d{4}$`,
|
||||
"LB": `^(\d{4}([ ]?\d{4})?)?$`,
|
||||
"LI": `^(948[5-9])|(949[0-7])$`,
|
||||
"LT": `^\d{5}$`,
|
||||
"LU": `^\d{4}$`,
|
||||
"MK": `^\d{4}$`,
|
||||
"MY": `^\d{5}$`,
|
||||
"MV": `^\d{5}$`,
|
||||
"MT": `^[A-Z]{3}[ ]?\d{2,4}$`,
|
||||
"MU": `^(\d{3}[A-Z]{2}\d{3})?$`,
|
||||
"MX": `^\d{5}$`,
|
||||
"MD": `^\d{4}$`,
|
||||
"MC": `^980\d{2}$`,
|
||||
"MA": `^\d{5}$`,
|
||||
"NP": `^\d{5}$`,
|
||||
"NZ": `^\d{4}$`,
|
||||
"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`,
|
||||
"NG": `^(\d{6})?$`,
|
||||
"OM": `^(PC )?\d{3}$`,
|
||||
"PK": `^\d{5}$`,
|
||||
"PY": `^\d{4}$`,
|
||||
"PH": `^\d{4}$`,
|
||||
"PL": `^\d{2}-\d{3}$`,
|
||||
"PR": `^00[679]\d{2}([ \-]\d{4})?$`,
|
||||
"RO": `^\d{6}$`,
|
||||
"RU": `^\d{6}$`,
|
||||
"SM": `^4789\d$`,
|
||||
"SA": `^\d{5}$`,
|
||||
"SN": `^\d{5}$`,
|
||||
"SK": `^\d{3}[ ]?\d{2}$`,
|
||||
"SI": `^\d{4}$`,
|
||||
"ZA": `^\d{4}$`,
|
||||
"LK": `^\d{5}$`,
|
||||
"TJ": `^\d{6}$`,
|
||||
"TH": `^\d{5}$`,
|
||||
"TN": `^\d{4}$`,
|
||||
"TR": `^\d{5}$`,
|
||||
"TM": `^\d{6}$`,
|
||||
"UA": `^\d{5}$`,
|
||||
"UY": `^\d{5}$`,
|
||||
"UZ": `^\d{6}$`,
|
||||
"VA": `^00120$`,
|
||||
"VE": `^\d{4}$`,
|
||||
"ZM": `^\d{5}$`,
|
||||
"AS": `^96799$`,
|
||||
"CC": `^6799$`,
|
||||
"CK": `^\d{4}$`,
|
||||
"RS": `^\d{6}$`,
|
||||
"ME": `^8\d{4}$`,
|
||||
"CS": `^\d{5}$`,
|
||||
"YU": `^\d{5}$`,
|
||||
"CX": `^6798$`,
|
||||
"ET": `^\d{4}$`,
|
||||
"FK": `^FIQQ 1ZZ$`,
|
||||
"NF": `^2899$`,
|
||||
"FM": `^(9694[1-4])([ \-]\d{4})?$`,
|
||||
"GF": `^9[78]3\d{2}$`,
|
||||
"GN": `^\d{3}$`,
|
||||
"GP": `^9[78][01]\d{2}$`,
|
||||
"GS": `^SIQQ 1ZZ$`,
|
||||
"GU": `^969[123]\d([ \-]\d{4})?$`,
|
||||
"GW": `^\d{4}$`,
|
||||
"HM": `^\d{4}$`,
|
||||
"IQ": `^\d{5}$`,
|
||||
"KG": `^\d{6}$`,
|
||||
"LR": `^\d{4}$`,
|
||||
"LS": `^\d{3}$`,
|
||||
"MG": `^\d{3}$`,
|
||||
"MH": `^969[67]\d([ \-]\d{4})?$`,
|
||||
"MN": `^\d{6}$`,
|
||||
"MP": `^9695[012]([ \-]\d{4})?$`,
|
||||
"MQ": `^9[78]2\d{2}$`,
|
||||
"NC": `^988\d{2}$`,
|
||||
"NE": `^\d{4}$`,
|
||||
"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`,
|
||||
"VN": `^[0-9]{1,6}$`,
|
||||
"PF": `^987\d{2}$`,
|
||||
"PG": `^\d{3}$`,
|
||||
"PM": `^9[78]5\d{2}$`,
|
||||
"PN": `^PCRN 1ZZ$`,
|
||||
"PW": `^96940$`,
|
||||
"RE": `^9[78]4\d{2}$`,
|
||||
"SH": `^(ASCN|STHL) 1ZZ$`,
|
||||
"SJ": `^\d{4}$`,
|
||||
"SO": `^\d{5}$`,
|
||||
"SZ": `^[HLMS]\d{3}$`,
|
||||
"TC": `^TKCA 1ZZ$`,
|
||||
"WF": `^986\d{2}$`,
|
||||
"XK": `^\d{5}$`,
|
||||
"YT": `^976\d{2}$`,
|
||||
}
|
||||
|
||||
var postCodeRegexDict = map[string]*regexp.Regexp{}
|
||||
|
||||
func init() {
|
||||
for countryCode, pattern := range postCodePatternDict {
|
||||
postCodeRegexDict[countryCode] = regexp.MustCompile(pattern)
|
||||
}
|
||||
}
|
103
vendor/github.com/go-playground/validator/v10/regexes.go
generated
vendored
Normal file
103
vendor/github.com/go-playground/validator/v10/regexes.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
package validator
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
alphaRegexString = "^[a-zA-Z]+$"
|
||||
alphaNumericRegexString = "^[a-zA-Z0-9]+$"
|
||||
alphaUnicodeRegexString = "^[\\p{L}]+$"
|
||||
alphaUnicodeNumericRegexString = "^[\\p{L}\\p{N}]+$"
|
||||
numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
|
||||
numberRegexString = "^[0-9]+$"
|
||||
hexadecimalRegexString = "^(0[xX])?[0-9a-fA-F]+$"
|
||||
hexColorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
|
||||
rgbRegexString = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*\\)$"
|
||||
rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
|
||||
hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$"
|
||||
hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
|
||||
emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
||||
e164RegexString = "^\\+[1-9]?[0-9]{7,14}$"
|
||||
base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
|
||||
base64URLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2}==|[A-Za-z0-9-_]{3}=|[A-Za-z0-9-_]{4})$"
|
||||
iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$"
|
||||
iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$"
|
||||
uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
||||
uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
||||
uUIDRegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
uUID3RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-3[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
|
||||
uUID4RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
|
||||
uUID5RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
|
||||
uUIDRFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
|
||||
aSCIIRegexString = "^[\x00-\x7F]*$"
|
||||
printableASCIIRegexString = "^[\x20-\x7E]*$"
|
||||
multibyteRegexString = "[^\x00-\x7F]"
|
||||
dataURIRegexString = `^data:((?:\w+\/(?:([^;]|;[^;]).)+)?)`
|
||||
latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
||||
longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
||||
sSNRegexString = `^[0-9]{3}[ -]?(0[1-9]|[1-9][0-9])[ -]?([1-9][0-9]{3}|[0-9][1-9][0-9]{2}|[0-9]{2}[1-9][0-9]|[0-9]{3}[1-9])$`
|
||||
hostnameRegexStringRFC952 = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$` // https://tools.ietf.org/html/rfc952
|
||||
hostnameRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*?$` // accepts hostname starting with a digit https://tools.ietf.org/html/rfc1123
|
||||
fqdnRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{0,62})(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*?(\.[a-zA-Z]{1}[a-zA-Z0-9]{0,62})\.?$` // same as hostnameRegexStringRFC1123 but must contain a non numerical TLD (possibly ending with '.')
|
||||
btcAddressRegexString = `^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$` // bitcoin address
|
||||
btcAddressUpperRegexStringBech32 = `^BC1[02-9AC-HJ-NP-Z]{7,76}$` // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32
|
||||
btcAddressLowerRegexStringBech32 = `^bc1[02-9ac-hj-np-z]{7,76}$` // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32
|
||||
ethAddressRegexString = `^0x[0-9a-fA-F]{40}$`
|
||||
ethAddressUpperRegexString = `^0x[0-9A-F]{40}$`
|
||||
ethAddressLowerRegexString = `^0x[0-9a-f]{40}$`
|
||||
uRLEncodedRegexString = `^(?:[^%]|%[0-9A-Fa-f]{2})*$`
|
||||
hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(>)|(<)|(")|(&)+[;]?`
|
||||
hTMLRegexString = `<[/]?([a-zA-Z]+).*?>`
|
||||
splitParamsRegexString = `'[^']*'|\S+`
|
||||
bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
|
||||
)
|
||||
|
||||
var (
|
||||
alphaRegex = regexp.MustCompile(alphaRegexString)
|
||||
alphaNumericRegex = regexp.MustCompile(alphaNumericRegexString)
|
||||
alphaUnicodeRegex = regexp.MustCompile(alphaUnicodeRegexString)
|
||||
alphaUnicodeNumericRegex = regexp.MustCompile(alphaUnicodeNumericRegexString)
|
||||
numericRegex = regexp.MustCompile(numericRegexString)
|
||||
numberRegex = regexp.MustCompile(numberRegexString)
|
||||
hexadecimalRegex = regexp.MustCompile(hexadecimalRegexString)
|
||||
hexColorRegex = regexp.MustCompile(hexColorRegexString)
|
||||
rgbRegex = regexp.MustCompile(rgbRegexString)
|
||||
rgbaRegex = regexp.MustCompile(rgbaRegexString)
|
||||
hslRegex = regexp.MustCompile(hslRegexString)
|
||||
hslaRegex = regexp.MustCompile(hslaRegexString)
|
||||
e164Regex = regexp.MustCompile(e164RegexString)
|
||||
emailRegex = regexp.MustCompile(emailRegexString)
|
||||
base64Regex = regexp.MustCompile(base64RegexString)
|
||||
base64URLRegex = regexp.MustCompile(base64URLRegexString)
|
||||
iSBN10Regex = regexp.MustCompile(iSBN10RegexString)
|
||||
iSBN13Regex = regexp.MustCompile(iSBN13RegexString)
|
||||
uUID3Regex = regexp.MustCompile(uUID3RegexString)
|
||||
uUID4Regex = regexp.MustCompile(uUID4RegexString)
|
||||
uUID5Regex = regexp.MustCompile(uUID5RegexString)
|
||||
uUIDRegex = regexp.MustCompile(uUIDRegexString)
|
||||
uUID3RFC4122Regex = regexp.MustCompile(uUID3RFC4122RegexString)
|
||||
uUID4RFC4122Regex = regexp.MustCompile(uUID4RFC4122RegexString)
|
||||
uUID5RFC4122Regex = regexp.MustCompile(uUID5RFC4122RegexString)
|
||||
uUIDRFC4122Regex = regexp.MustCompile(uUIDRFC4122RegexString)
|
||||
aSCIIRegex = regexp.MustCompile(aSCIIRegexString)
|
||||
printableASCIIRegex = regexp.MustCompile(printableASCIIRegexString)
|
||||
multibyteRegex = regexp.MustCompile(multibyteRegexString)
|
||||
dataURIRegex = regexp.MustCompile(dataURIRegexString)
|
||||
latitudeRegex = regexp.MustCompile(latitudeRegexString)
|
||||
longitudeRegex = regexp.MustCompile(longitudeRegexString)
|
||||
sSNRegex = regexp.MustCompile(sSNRegexString)
|
||||
hostnameRegexRFC952 = regexp.MustCompile(hostnameRegexStringRFC952)
|
||||
hostnameRegexRFC1123 = regexp.MustCompile(hostnameRegexStringRFC1123)
|
||||
fqdnRegexRFC1123 = regexp.MustCompile(fqdnRegexStringRFC1123)
|
||||
btcAddressRegex = regexp.MustCompile(btcAddressRegexString)
|
||||
btcUpperAddressRegexBech32 = regexp.MustCompile(btcAddressUpperRegexStringBech32)
|
||||
btcLowerAddressRegexBech32 = regexp.MustCompile(btcAddressLowerRegexStringBech32)
|
||||
ethAddressRegex = regexp.MustCompile(ethAddressRegexString)
|
||||
ethAddressRegexUpper = regexp.MustCompile(ethAddressUpperRegexString)
|
||||
ethAddressRegexLower = regexp.MustCompile(ethAddressLowerRegexString)
|
||||
uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString)
|
||||
hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString)
|
||||
hTMLRegex = regexp.MustCompile(hTMLRegexString)
|
||||
splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
|
||||
bicRegex = regexp.MustCompile(bicRegexString)
|
||||
)
|
175
vendor/github.com/go-playground/validator/v10/struct_level.go
generated
vendored
Normal file
175
vendor/github.com/go-playground/validator/v10/struct_level.go
generated
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// StructLevelFunc accepts all values needed for struct level validation
|
||||
type StructLevelFunc func(sl StructLevel)
|
||||
|
||||
// StructLevelFuncCtx accepts all values needed for struct level validation
|
||||
// but also allows passing of contextual validation information via context.Context.
|
||||
type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)
|
||||
|
||||
// wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx
|
||||
func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx {
|
||||
return func(ctx context.Context, sl StructLevel) {
|
||||
fn(sl)
|
||||
}
|
||||
}
|
||||
|
||||
// StructLevel contains all the information and helper functions
|
||||
// to validate a struct
|
||||
type StructLevel interface {
|
||||
|
||||
// Validator returns the main validation object, in case one wants to call validations internally.
|
||||
// this is so you don't have to use anonymous functions to get access to the validate
|
||||
// instance.
|
||||
Validator() *Validate
|
||||
|
||||
// Top returns the top level struct, if any
|
||||
Top() reflect.Value
|
||||
|
||||
// Parent returns the current fields parent struct, if any
|
||||
Parent() reflect.Value
|
||||
|
||||
// Current returns the current struct.
|
||||
Current() reflect.Value
|
||||
|
||||
// ExtractType gets the actual underlying type of field value.
|
||||
// It will dive into pointers, customTypes and return you the
|
||||
// underlying value and its kind.
|
||||
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
|
||||
|
||||
// ReportError reports an error just by passing the field and tag information
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// fieldName and altName get appended to the existing namespace that
|
||||
// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending
|
||||
// on the nesting
|
||||
//
|
||||
// tag can be an existing validation tag or just something you make up
|
||||
// and process on the flip side it's up to you.
|
||||
ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
|
||||
|
||||
// ReportValidationErrors reports an error just by passing ValidationErrors
|
||||
//
|
||||
// NOTES:
|
||||
//
|
||||
// relativeNamespace and relativeActualNamespace get appended to the
|
||||
// existing namespace that validator is on.
|
||||
// e.g. pass 'User.FirstName' or 'Users[0].FirstName' depending
|
||||
// on the nesting. most of the time they will be blank, unless you validate
|
||||
// at a level lower the the current field depth
|
||||
ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
|
||||
}
|
||||
|
||||
var _ StructLevel = new(validate)
|
||||
|
||||
// Top returns the top level struct
|
||||
//
|
||||
// NOTE: this can be the same as the current struct being validated
|
||||
// if not is a nested struct.
|
||||
//
|
||||
// this is only called when within Struct and Field Level validation and
|
||||
// should not be relied upon for an acurate value otherwise.
|
||||
func (v *validate) Top() reflect.Value {
|
||||
return v.top
|
||||
}
|
||||
|
||||
// Parent returns the current structs parent
|
||||
//
|
||||
// NOTE: this can be the same as the current struct being validated
|
||||
// if not is a nested struct.
|
||||
//
|
||||
// this is only called when within Struct and Field Level validation and
|
||||
// should not be relied upon for an acurate value otherwise.
|
||||
func (v *validate) Parent() reflect.Value {
|
||||
return v.slflParent
|
||||
}
|
||||
|
||||
// Current returns the current struct.
|
||||
func (v *validate) Current() reflect.Value {
|
||||
return v.slCurrent
|
||||
}
|
||||
|
||||
// Validator returns the main validation object, in case one want to call validations internally.
|
||||
func (v *validate) Validator() *Validate {
|
||||
return v.v
|
||||
}
|
||||
|
||||
// ExtractType gets the actual underlying type of field value.
|
||||
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
|
||||
return v.extractTypeInternal(field, false)
|
||||
}
|
||||
|
||||
// ReportError reports an error just by passing the field and tag information
|
||||
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {
|
||||
|
||||
fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
|
||||
|
||||
if len(structFieldName) == 0 {
|
||||
structFieldName = fieldName
|
||||
}
|
||||
|
||||
v.str1 = string(append(v.ns, fieldName...))
|
||||
|
||||
if v.v.hasTagNameFunc || fieldName != structFieldName {
|
||||
v.str2 = string(append(v.actualNs, structFieldName...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
|
||||
if kind == reflect.Invalid {
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: tag,
|
||||
actualTag: tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(fieldName)),
|
||||
structfieldLen: uint8(len(structFieldName)),
|
||||
param: param,
|
||||
kind: kind,
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: tag,
|
||||
actualTag: tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(fieldName)),
|
||||
structfieldLen: uint8(len(structFieldName)),
|
||||
value: fv.Interface(),
|
||||
param: param,
|
||||
kind: kind,
|
||||
typ: fv.Type(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
|
||||
//
|
||||
// NOTE: this function prepends the current namespace to the relative ones.
|
||||
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {
|
||||
|
||||
var err *fieldError
|
||||
|
||||
for i := 0; i < len(errs); i++ {
|
||||
|
||||
err = errs[i].(*fieldError)
|
||||
err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
|
||||
err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))
|
||||
|
||||
v.errs = append(v.errs, err)
|
||||
}
|
||||
}
|
11
vendor/github.com/go-playground/validator/v10/translations.go
generated
vendored
Normal file
11
vendor/github.com/go-playground/validator/v10/translations.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package validator
|
||||
|
||||
import ut "github.com/go-playground/universal-translator"
|
||||
|
||||
// TranslationFunc is the function type used to register or override
|
||||
// custom translations
|
||||
type TranslationFunc func(ut ut.Translator, fe FieldError) string
|
||||
|
||||
// RegisterTranslationsFunc allows for registering of translations
|
||||
// for a 'ut.Translator' for use within the 'TranslationFunc'
|
||||
type RegisterTranslationsFunc func(ut ut.Translator) error
|
288
vendor/github.com/go-playground/validator/v10/util.go
generated
vendored
Normal file
288
vendor/github.com/go-playground/validator/v10/util.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// extractTypeInternal gets the actual underlying type of field value.
|
||||
// It will dive into pointers, customTypes and return you the
|
||||
// underlying value and it's kind.
|
||||
func (v *validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) {
|
||||
|
||||
BEGIN:
|
||||
switch current.Kind() {
|
||||
case reflect.Ptr:
|
||||
|
||||
nullable = true
|
||||
|
||||
if current.IsNil() {
|
||||
return current, reflect.Ptr, nullable
|
||||
}
|
||||
|
||||
current = current.Elem()
|
||||
goto BEGIN
|
||||
|
||||
case reflect.Interface:
|
||||
|
||||
nullable = true
|
||||
|
||||
if current.IsNil() {
|
||||
return current, reflect.Interface, nullable
|
||||
}
|
||||
|
||||
current = current.Elem()
|
||||
goto BEGIN
|
||||
|
||||
case reflect.Invalid:
|
||||
return current, reflect.Invalid, nullable
|
||||
|
||||
default:
|
||||
|
||||
if v.v.hasCustomFuncs {
|
||||
|
||||
if fn, ok := v.v.customFuncs[current.Type()]; ok {
|
||||
current = reflect.ValueOf(fn(current))
|
||||
goto BEGIN
|
||||
}
|
||||
}
|
||||
|
||||
return current, current.Kind(), nullable
|
||||
}
|
||||
}
|
||||
|
||||
// getStructFieldOKInternal traverses a struct to retrieve a specific field denoted by the provided namespace 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.
|
||||
func (v *validate) getStructFieldOKInternal(val reflect.Value, namespace string) (current reflect.Value, kind reflect.Kind, nullable bool, found bool) {
|
||||
|
||||
BEGIN:
|
||||
current, kind, nullable = v.ExtractType(val)
|
||||
if kind == reflect.Invalid {
|
||||
return
|
||||
}
|
||||
|
||||
if namespace == "" {
|
||||
found = true
|
||||
return
|
||||
}
|
||||
|
||||
switch kind {
|
||||
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
typ := current.Type()
|
||||
fld := namespace
|
||||
var ns string
|
||||
|
||||
if typ != timeType {
|
||||
|
||||
idx := strings.Index(namespace, namespaceSeparator)
|
||||
|
||||
if idx != -1 {
|
||||
fld = namespace[:idx]
|
||||
ns = namespace[idx+1:]
|
||||
} else {
|
||||
ns = ""
|
||||
}
|
||||
|
||||
bracketIdx := strings.Index(fld, leftBracket)
|
||||
if bracketIdx != -1 {
|
||||
fld = fld[:bracketIdx]
|
||||
|
||||
ns = namespace[bracketIdx:]
|
||||
}
|
||||
|
||||
val = current.FieldByName(fld)
|
||||
namespace = ns
|
||||
goto BEGIN
|
||||
}
|
||||
|
||||
case reflect.Array, reflect.Slice:
|
||||
idx := strings.Index(namespace, leftBracket)
|
||||
idx2 := strings.Index(namespace, rightBracket)
|
||||
|
||||
arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])
|
||||
|
||||
if arrIdx >= current.Len() {
|
||||
return
|
||||
}
|
||||
|
||||
startIdx := idx2 + 1
|
||||
|
||||
if startIdx < len(namespace) {
|
||||
if namespace[startIdx:startIdx+1] == namespaceSeparator {
|
||||
startIdx++
|
||||
}
|
||||
}
|
||||
|
||||
val = current.Index(arrIdx)
|
||||
namespace = namespace[startIdx:]
|
||||
goto BEGIN
|
||||
|
||||
case reflect.Map:
|
||||
idx := strings.Index(namespace, leftBracket) + 1
|
||||
idx2 := strings.Index(namespace, rightBracket)
|
||||
|
||||
endIdx := idx2
|
||||
|
||||
if endIdx+1 < len(namespace) {
|
||||
if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
|
||||
endIdx++
|
||||
}
|
||||
}
|
||||
|
||||
key := namespace[idx:idx2]
|
||||
|
||||
switch current.Type().Key().Kind() {
|
||||
case reflect.Int:
|
||||
i, _ := strconv.Atoi(key)
|
||||
val = current.MapIndex(reflect.ValueOf(i))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Int8:
|
||||
i, _ := strconv.ParseInt(key, 10, 8)
|
||||
val = current.MapIndex(reflect.ValueOf(int8(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Int16:
|
||||
i, _ := strconv.ParseInt(key, 10, 16)
|
||||
val = current.MapIndex(reflect.ValueOf(int16(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Int32:
|
||||
i, _ := strconv.ParseInt(key, 10, 32)
|
||||
val = current.MapIndex(reflect.ValueOf(int32(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Int64:
|
||||
i, _ := strconv.ParseInt(key, 10, 64)
|
||||
val = current.MapIndex(reflect.ValueOf(i))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Uint:
|
||||
i, _ := strconv.ParseUint(key, 10, 0)
|
||||
val = current.MapIndex(reflect.ValueOf(uint(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Uint8:
|
||||
i, _ := strconv.ParseUint(key, 10, 8)
|
||||
val = current.MapIndex(reflect.ValueOf(uint8(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Uint16:
|
||||
i, _ := strconv.ParseUint(key, 10, 16)
|
||||
val = current.MapIndex(reflect.ValueOf(uint16(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Uint32:
|
||||
i, _ := strconv.ParseUint(key, 10, 32)
|
||||
val = current.MapIndex(reflect.ValueOf(uint32(i)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Uint64:
|
||||
i, _ := strconv.ParseUint(key, 10, 64)
|
||||
val = current.MapIndex(reflect.ValueOf(i))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Float32:
|
||||
f, _ := strconv.ParseFloat(key, 32)
|
||||
val = current.MapIndex(reflect.ValueOf(float32(f)))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Float64:
|
||||
f, _ := strconv.ParseFloat(key, 64)
|
||||
val = current.MapIndex(reflect.ValueOf(f))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
case reflect.Bool:
|
||||
b, _ := strconv.ParseBool(key)
|
||||
val = current.MapIndex(reflect.ValueOf(b))
|
||||
namespace = namespace[endIdx+1:]
|
||||
|
||||
// reflect.Type = string
|
||||
default:
|
||||
val = current.MapIndex(reflect.ValueOf(key))
|
||||
namespace = namespace[endIdx+1:]
|
||||
}
|
||||
|
||||
goto BEGIN
|
||||
}
|
||||
|
||||
// if got here there was more namespace, cannot go any deeper
|
||||
panic("Invalid field namespace")
|
||||
}
|
||||
|
||||
// asInt returns the parameter as a int64
|
||||
// or panics if it can't convert
|
||||
func asInt(param string) int64 {
|
||||
i, err := strconv.ParseInt(param, 0, 64)
|
||||
panicIf(err)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// asIntFromTimeDuration parses param as time.Duration and returns it as int64
|
||||
// or panics on error.
|
||||
func asIntFromTimeDuration(param string) int64 {
|
||||
d, err := time.ParseDuration(param)
|
||||
if err != nil {
|
||||
// attempt parsing as an an integer assuming nanosecond precision
|
||||
return asInt(param)
|
||||
}
|
||||
return int64(d)
|
||||
}
|
||||
|
||||
// asIntFromType calls the proper function to parse param as int64,
|
||||
// given a field's Type t.
|
||||
func asIntFromType(t reflect.Type, param string) int64 {
|
||||
switch t {
|
||||
case timeDurationType:
|
||||
return asIntFromTimeDuration(param)
|
||||
default:
|
||||
return asInt(param)
|
||||
}
|
||||
}
|
||||
|
||||
// asUint returns the parameter as a uint64
|
||||
// or panics if it can't convert
|
||||
func asUint(param string) uint64 {
|
||||
|
||||
i, err := strconv.ParseUint(param, 0, 64)
|
||||
panicIf(err)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// asFloat returns the parameter as a float64
|
||||
// or panics if it can't convert
|
||||
func asFloat(param string) float64 {
|
||||
|
||||
i, err := strconv.ParseFloat(param, 64)
|
||||
panicIf(err)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// asBool returns the parameter as a bool
|
||||
// or panics if it can't convert
|
||||
func asBool(param string) bool {
|
||||
|
||||
i, err := strconv.ParseBool(param)
|
||||
panicIf(err)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
func panicIf(err error) {
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
477
vendor/github.com/go-playground/validator/v10/validator.go
generated
vendored
Normal file
477
vendor/github.com/go-playground/validator/v10/validator.go
generated
vendored
Normal file
@ -0,0 +1,477 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// per validate construct
|
||||
type validate struct {
|
||||
v *Validate
|
||||
top reflect.Value
|
||||
ns []byte
|
||||
actualNs []byte
|
||||
errs ValidationErrors
|
||||
includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
|
||||
ffn FilterFunc
|
||||
slflParent reflect.Value // StructLevel & FieldLevel
|
||||
slCurrent reflect.Value // StructLevel & FieldLevel
|
||||
flField reflect.Value // StructLevel & FieldLevel
|
||||
cf *cField // StructLevel & FieldLevel
|
||||
ct *cTag // StructLevel & FieldLevel
|
||||
misc []byte // misc reusable
|
||||
str1 string // misc reusable
|
||||
str2 string // misc reusable
|
||||
fldIsPointer bool // StructLevel & FieldLevel
|
||||
isPartial bool
|
||||
hasExcludes bool
|
||||
}
|
||||
|
||||
// parent and current will be the same the first run of validateStruct
|
||||
func (v *validate) validateStruct(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) {
|
||||
|
||||
cs, ok := v.v.structCache.Get(typ)
|
||||
if !ok {
|
||||
cs = v.v.extractStructCache(current, typ.Name())
|
||||
}
|
||||
|
||||
if len(ns) == 0 && len(cs.name) != 0 {
|
||||
|
||||
ns = append(ns, cs.name...)
|
||||
ns = append(ns, '.')
|
||||
|
||||
structNs = append(structNs, cs.name...)
|
||||
structNs = append(structNs, '.')
|
||||
}
|
||||
|
||||
// ct is nil on top level struct, and structs as fields that have no tag info
|
||||
// so if nil or if not nil and the structonly tag isn't present
|
||||
if ct == nil || ct.typeof != typeStructOnly {
|
||||
|
||||
var f *cField
|
||||
|
||||
for i := 0; i < len(cs.fields); i++ {
|
||||
|
||||
f = cs.fields[i]
|
||||
|
||||
if v.isPartial {
|
||||
|
||||
if v.ffn != nil {
|
||||
// used with StructFiltered
|
||||
if v.ffn(append(structNs, f.name...)) {
|
||||
continue
|
||||
}
|
||||
|
||||
} else {
|
||||
// used with StructPartial & StructExcept
|
||||
_, ok = v.includeExclude[string(append(structNs, f.name...))]
|
||||
|
||||
if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags)
|
||||
}
|
||||
}
|
||||
|
||||
// check if any struct level validations, after all field validations already checked.
|
||||
// first iteration will have no info about nostructlevel tag, and is checked prior to
|
||||
// calling the next iteration of validateStruct called from traverseField.
|
||||
if cs.fn != nil {
|
||||
|
||||
v.slflParent = parent
|
||||
v.slCurrent = current
|
||||
v.ns = ns
|
||||
v.actualNs = structNs
|
||||
|
||||
cs.fn(ctx, v)
|
||||
}
|
||||
}
|
||||
|
||||
// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
|
||||
func (v *validate) traverseField(ctx context.Context, parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) {
|
||||
var typ reflect.Type
|
||||
var kind reflect.Kind
|
||||
|
||||
current, kind, v.fldIsPointer = v.extractTypeInternal(current, false)
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr, reflect.Interface, reflect.Invalid:
|
||||
|
||||
if ct == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault {
|
||||
return
|
||||
}
|
||||
|
||||
if ct.hasTag {
|
||||
if kind == reflect.Invalid {
|
||||
v.str1 = string(append(ns, cf.altName...))
|
||||
if v.v.hasTagNameFunc {
|
||||
v.str2 = string(append(structNs, cf.name...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: ct.aliasTag,
|
||||
actualTag: ct.tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
v.str1 = string(append(ns, cf.altName...))
|
||||
if v.v.hasTagNameFunc {
|
||||
v.str2 = string(append(structNs, cf.name...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
if !ct.runValidationWhenNil {
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: ct.aliasTag,
|
||||
actualTag: ct.tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
value: current.Interface(),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
typ: current.Type(),
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
typ = current.Type()
|
||||
|
||||
if typ != timeType {
|
||||
|
||||
if ct != nil {
|
||||
|
||||
if ct.typeof == typeStructOnly {
|
||||
goto CONTINUE
|
||||
} else if ct.typeof == typeIsDefault {
|
||||
// set Field Level fields
|
||||
v.slflParent = parent
|
||||
v.flField = current
|
||||
v.cf = cf
|
||||
v.ct = ct
|
||||
|
||||
if !ct.fn(ctx, v) {
|
||||
v.str1 = string(append(ns, cf.altName...))
|
||||
|
||||
if v.v.hasTagNameFunc {
|
||||
v.str2 = string(append(structNs, cf.name...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: ct.aliasTag,
|
||||
actualTag: ct.tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
value: current.Interface(),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
typ: typ,
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ct = ct.next
|
||||
}
|
||||
|
||||
if ct != nil && ct.typeof == typeNoStructLevel {
|
||||
return
|
||||
}
|
||||
|
||||
CONTINUE:
|
||||
// if len == 0 then validating using 'Var' or 'VarWithValue'
|
||||
// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm...
|
||||
// VarWithField - this allows for validating against each field within the struct against a specific value
|
||||
// pretty handy in certain situations
|
||||
if len(cf.name) > 0 {
|
||||
ns = append(append(ns, cf.altName...), '.')
|
||||
structNs = append(append(structNs, cf.name...), '.')
|
||||
}
|
||||
|
||||
v.validateStruct(ctx, parent, current, typ, ns, structNs, ct)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ct == nil || !ct.hasTag {
|
||||
return
|
||||
}
|
||||
|
||||
typ = current.Type()
|
||||
|
||||
OUTER:
|
||||
for {
|
||||
if ct == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch ct.typeof {
|
||||
|
||||
case typeOmitEmpty:
|
||||
|
||||
// set Field Level fields
|
||||
v.slflParent = parent
|
||||
v.flField = current
|
||||
v.cf = cf
|
||||
v.ct = ct
|
||||
|
||||
if !hasValue(v) {
|
||||
return
|
||||
}
|
||||
|
||||
ct = ct.next
|
||||
continue
|
||||
|
||||
case typeEndKeys:
|
||||
return
|
||||
|
||||
case typeDive:
|
||||
|
||||
ct = ct.next
|
||||
|
||||
// traverse slice or map here
|
||||
// or panic ;)
|
||||
switch kind {
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
||||
var i64 int64
|
||||
reusableCF := &cField{}
|
||||
|
||||
for i := 0; i < current.Len(); i++ {
|
||||
|
||||
i64 = int64(i)
|
||||
|
||||
v.misc = append(v.misc[0:0], cf.name...)
|
||||
v.misc = append(v.misc, '[')
|
||||
v.misc = strconv.AppendInt(v.misc, i64, 10)
|
||||
v.misc = append(v.misc, ']')
|
||||
|
||||
reusableCF.name = string(v.misc)
|
||||
|
||||
if cf.namesEqual {
|
||||
reusableCF.altName = reusableCF.name
|
||||
} else {
|
||||
|
||||
v.misc = append(v.misc[0:0], cf.altName...)
|
||||
v.misc = append(v.misc, '[')
|
||||
v.misc = strconv.AppendInt(v.misc, i64, 10)
|
||||
v.misc = append(v.misc, ']')
|
||||
|
||||
reusableCF.altName = string(v.misc)
|
||||
}
|
||||
v.traverseField(ctx, parent, current.Index(i), ns, structNs, reusableCF, ct)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
|
||||
var pv string
|
||||
reusableCF := &cField{}
|
||||
|
||||
for _, key := range current.MapKeys() {
|
||||
|
||||
pv = fmt.Sprintf("%v", key.Interface())
|
||||
|
||||
v.misc = append(v.misc[0:0], cf.name...)
|
||||
v.misc = append(v.misc, '[')
|
||||
v.misc = append(v.misc, pv...)
|
||||
v.misc = append(v.misc, ']')
|
||||
|
||||
reusableCF.name = string(v.misc)
|
||||
|
||||
if cf.namesEqual {
|
||||
reusableCF.altName = reusableCF.name
|
||||
} else {
|
||||
v.misc = append(v.misc[0:0], cf.altName...)
|
||||
v.misc = append(v.misc, '[')
|
||||
v.misc = append(v.misc, pv...)
|
||||
v.misc = append(v.misc, ']')
|
||||
|
||||
reusableCF.altName = string(v.misc)
|
||||
}
|
||||
|
||||
if ct != nil && ct.typeof == typeKeys && ct.keys != nil {
|
||||
v.traverseField(ctx, parent, key, ns, structNs, reusableCF, ct.keys)
|
||||
// can be nil when just keys being validated
|
||||
if ct.next != nil {
|
||||
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct.next)
|
||||
}
|
||||
} else {
|
||||
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
// throw error, if not a slice or map then should not have gotten here
|
||||
// bad dive tag
|
||||
panic("dive error! can't dive on a non slice or map")
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
case typeOr:
|
||||
|
||||
v.misc = v.misc[0:0]
|
||||
|
||||
for {
|
||||
|
||||
// set Field Level fields
|
||||
v.slflParent = parent
|
||||
v.flField = current
|
||||
v.cf = cf
|
||||
v.ct = ct
|
||||
|
||||
if ct.fn(ctx, v) {
|
||||
|
||||
// drain rest of the 'or' values, then continue or leave
|
||||
for {
|
||||
|
||||
ct = ct.next
|
||||
|
||||
if ct == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ct.typeof != typeOr {
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.misc = append(v.misc, '|')
|
||||
v.misc = append(v.misc, ct.tag...)
|
||||
|
||||
if ct.hasParam {
|
||||
v.misc = append(v.misc, '=')
|
||||
v.misc = append(v.misc, ct.param...)
|
||||
}
|
||||
|
||||
if ct.isBlockEnd || ct.next == nil {
|
||||
// if we get here, no valid 'or' value and no more tags
|
||||
v.str1 = string(append(ns, cf.altName...))
|
||||
|
||||
if v.v.hasTagNameFunc {
|
||||
v.str2 = string(append(structNs, cf.name...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
|
||||
if ct.hasAlias {
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: ct.aliasTag,
|
||||
actualTag: ct.actualAliasTag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
value: current.Interface(),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
typ: typ,
|
||||
},
|
||||
)
|
||||
|
||||
} else {
|
||||
|
||||
tVal := string(v.misc)[1:]
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: tVal,
|
||||
actualTag: tVal,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
value: current.Interface(),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
typ: typ,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
ct = ct.next
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
// set Field Level fields
|
||||
v.slflParent = parent
|
||||
v.flField = current
|
||||
v.cf = cf
|
||||
v.ct = ct
|
||||
|
||||
if !ct.fn(ctx, v) {
|
||||
|
||||
v.str1 = string(append(ns, cf.altName...))
|
||||
|
||||
if v.v.hasTagNameFunc {
|
||||
v.str2 = string(append(structNs, cf.name...))
|
||||
} else {
|
||||
v.str2 = v.str1
|
||||
}
|
||||
|
||||
v.errs = append(v.errs,
|
||||
&fieldError{
|
||||
v: v.v,
|
||||
tag: ct.aliasTag,
|
||||
actualTag: ct.tag,
|
||||
ns: v.str1,
|
||||
structNs: v.str2,
|
||||
fieldLen: uint8(len(cf.altName)),
|
||||
structfieldLen: uint8(len(cf.name)),
|
||||
value: current.Interface(),
|
||||
param: ct.param,
|
||||
kind: kind,
|
||||
typ: typ,
|
||||
},
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
ct = ct.next
|
||||
}
|
||||
}
|
||||
|
||||
}
|
654
vendor/github.com/go-playground/validator/v10/validator_instance.go
generated
vendored
Normal file
654
vendor/github.com/go-playground/validator/v10/validator_instance.go
generated
vendored
Normal file
@ -0,0 +1,654 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ut "github.com/go-playground/universal-translator"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTagName = "validate"
|
||||
utf8HexComma = "0x2C"
|
||||
utf8Pipe = "0x7C"
|
||||
tagSeparator = ","
|
||||
orSeparator = "|"
|
||||
tagKeySeparator = "="
|
||||
structOnlyTag = "structonly"
|
||||
noStructLevelTag = "nostructlevel"
|
||||
omitempty = "omitempty"
|
||||
isdefault = "isdefault"
|
||||
requiredWithoutAllTag = "required_without_all"
|
||||
requiredWithoutTag = "required_without"
|
||||
requiredWithTag = "required_with"
|
||||
requiredWithAllTag = "required_with_all"
|
||||
requiredIfTag = "required_if"
|
||||
requiredUnlessTag = "required_unless"
|
||||
excludedWithoutAllTag = "excluded_without_all"
|
||||
excludedWithoutTag = "excluded_without"
|
||||
excludedWithTag = "excluded_with"
|
||||
excludedWithAllTag = "excluded_with_all"
|
||||
skipValidationTag = "-"
|
||||
diveTag = "dive"
|
||||
keysTag = "keys"
|
||||
endKeysTag = "endkeys"
|
||||
requiredTag = "required"
|
||||
namespaceSeparator = "."
|
||||
leftBracket = "["
|
||||
rightBracket = "]"
|
||||
restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
|
||||
restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
|
||||
restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
|
||||
)
|
||||
|
||||
var (
|
||||
timeDurationType = reflect.TypeOf(time.Duration(0))
|
||||
timeType = reflect.TypeOf(time.Time{})
|
||||
|
||||
defaultCField = &cField{namesEqual: true}
|
||||
)
|
||||
|
||||
// FilterFunc is the type used to filter fields using
|
||||
// StructFiltered(...) function.
|
||||
// returning true results in the field being filtered/skiped from
|
||||
// validation
|
||||
type FilterFunc func(ns []byte) bool
|
||||
|
||||
// CustomTypeFunc allows for overriding or adding custom field type handler functions
|
||||
// field = field value of the type to return a value to be validated
|
||||
// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
|
||||
type CustomTypeFunc func(field reflect.Value) interface{}
|
||||
|
||||
// TagNameFunc allows for adding of a custom tag name parser
|
||||
type TagNameFunc func(field reflect.StructField) string
|
||||
|
||||
type internalValidationFuncWrapper struct {
|
||||
fn FuncCtx
|
||||
runValidatinOnNil bool
|
||||
}
|
||||
|
||||
// Validate contains the validator settings and cache
|
||||
type Validate struct {
|
||||
tagName string
|
||||
pool *sync.Pool
|
||||
hasCustomFuncs bool
|
||||
hasTagNameFunc bool
|
||||
tagNameFunc TagNameFunc
|
||||
structLevelFuncs map[reflect.Type]StructLevelFuncCtx
|
||||
customFuncs map[reflect.Type]CustomTypeFunc
|
||||
aliases map[string]string
|
||||
validations map[string]internalValidationFuncWrapper
|
||||
transTagFunc map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
|
||||
tagCache *tagCache
|
||||
structCache *structCache
|
||||
}
|
||||
|
||||
// New returns a new instance of 'validate' with sane defaults.
|
||||
func New() *Validate {
|
||||
|
||||
tc := new(tagCache)
|
||||
tc.m.Store(make(map[string]*cTag))
|
||||
|
||||
sc := new(structCache)
|
||||
sc.m.Store(make(map[reflect.Type]*cStruct))
|
||||
|
||||
v := &Validate{
|
||||
tagName: defaultTagName,
|
||||
aliases: make(map[string]string, len(bakedInAliases)),
|
||||
validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)),
|
||||
tagCache: tc,
|
||||
structCache: sc,
|
||||
}
|
||||
|
||||
// must copy alias validators for separate validations to be used in each validator instance
|
||||
for k, val := range bakedInAliases {
|
||||
v.RegisterAlias(k, val)
|
||||
}
|
||||
|
||||
// must copy validators for separate validations to be used in each instance
|
||||
for k, val := range bakedInValidators {
|
||||
|
||||
switch k {
|
||||
// these require that even if the value is nil that the validation should run, omitempty still overrides this behaviour
|
||||
case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag,
|
||||
excludedWithTag, excludedWithAllTag, excludedWithoutTag, excludedWithoutAllTag:
|
||||
_ = v.registerValidation(k, wrapFunc(val), true, true)
|
||||
default:
|
||||
// no need to error check here, baked in will always be valid
|
||||
_ = v.registerValidation(k, wrapFunc(val), true, false)
|
||||
}
|
||||
}
|
||||
|
||||
v.pool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &validate{
|
||||
v: v,
|
||||
ns: make([]byte, 0, 64),
|
||||
actualNs: make([]byte, 0, 64),
|
||||
misc: make([]byte, 32),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// SetTagName allows for changing of the default tag name of 'validate'
|
||||
func (v *Validate) SetTagName(name string) {
|
||||
v.tagName = name
|
||||
}
|
||||
|
||||
// ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual
|
||||
// validation validation information via context.Context.
|
||||
func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
|
||||
errs := make(map[string]interface{})
|
||||
for field, rule := range rules {
|
||||
if reflect.ValueOf(rule).Kind() == reflect.Map && reflect.ValueOf(data[field]).Kind() == reflect.Map {
|
||||
err := v.ValidateMapCtx(ctx, data[field].(map[string]interface{}), rule.(map[string]interface{}))
|
||||
if len(err) > 0 {
|
||||
errs[field] = err
|
||||
}
|
||||
} else if reflect.ValueOf(rule).Kind() == reflect.Map {
|
||||
errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
|
||||
} else {
|
||||
err := v.VarCtx(ctx, data[field], rule.(string))
|
||||
if err != nil {
|
||||
errs[field] = err
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// ValidateMap validates map data form a map of tags
|
||||
func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
|
||||
return v.ValidateMapCtx(context.Background(), data, rules)
|
||||
}
|
||||
|
||||
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
|
||||
//
|
||||
// eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names:
|
||||
//
|
||||
// validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||
// name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
|
||||
// if name == "-" {
|
||||
// return ""
|
||||
// }
|
||||
// return name
|
||||
// })
|
||||
func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
|
||||
v.tagNameFunc = fn
|
||||
v.hasTagNameFunc = true
|
||||
}
|
||||
|
||||
// RegisterValidation adds a validation with the given tag
|
||||
//
|
||||
// NOTES:
|
||||
// - if the key already exists, the previous validation function will be replaced.
|
||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error {
|
||||
return v.RegisterValidationCtx(tag, wrapFunc(fn), callValidationEvenIfNull...)
|
||||
}
|
||||
|
||||
// RegisterValidationCtx does the same as RegisterValidation on accepts a FuncCtx validation
|
||||
// allowing context.Context validation support.
|
||||
func (v *Validate) RegisterValidationCtx(tag string, fn FuncCtx, callValidationEvenIfNull ...bool) error {
|
||||
var nilCheckable bool
|
||||
if len(callValidationEvenIfNull) > 0 {
|
||||
nilCheckable = callValidationEvenIfNull[0]
|
||||
}
|
||||
return v.registerValidation(tag, fn, false, nilCheckable)
|
||||
}
|
||||
|
||||
func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool, nilCheckable bool) error {
|
||||
if len(tag) == 0 {
|
||||
return errors.New("Function Key cannot be empty")
|
||||
}
|
||||
|
||||
if fn == nil {
|
||||
return errors.New("Function cannot be empty")
|
||||
}
|
||||
|
||||
_, ok := restrictedTags[tag]
|
||||
if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) {
|
||||
panic(fmt.Sprintf(restrictedTagErr, tag))
|
||||
}
|
||||
v.validations[tag] = internalValidationFuncWrapper{fn: fn, runValidatinOnNil: nilCheckable}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterAlias registers a mapping of a single validation tag that
|
||||
// defines a common or complex set of validation(s) to simplify adding validation
|
||||
// to structs.
|
||||
//
|
||||
// NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterAlias(alias, tags string) {
|
||||
|
||||
_, ok := restrictedTags[alias]
|
||||
|
||||
if ok || strings.ContainsAny(alias, restrictedTagChars) {
|
||||
panic(fmt.Sprintf(restrictedAliasErr, alias))
|
||||
}
|
||||
|
||||
v.aliases[alias] = tags
|
||||
}
|
||||
|
||||
// RegisterStructValidation registers a StructLevelFunc against a number of types.
|
||||
//
|
||||
// NOTE:
|
||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
|
||||
v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...)
|
||||
}
|
||||
|
||||
// RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing
|
||||
// of contextual validation information via context.Context.
|
||||
//
|
||||
// NOTE:
|
||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) {
|
||||
|
||||
if v.structLevelFuncs == nil {
|
||||
v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx)
|
||||
}
|
||||
|
||||
for _, t := range types {
|
||||
tv := reflect.ValueOf(t)
|
||||
if tv.Kind() == reflect.Ptr {
|
||||
t = reflect.Indirect(tv).Interface()
|
||||
}
|
||||
|
||||
v.structLevelFuncs[reflect.TypeOf(t)] = fn
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
|
||||
//
|
||||
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
|
||||
func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
|
||||
|
||||
if v.customFuncs == nil {
|
||||
v.customFuncs = make(map[reflect.Type]CustomTypeFunc)
|
||||
}
|
||||
|
||||
for _, t := range types {
|
||||
v.customFuncs[reflect.TypeOf(t)] = fn
|
||||
}
|
||||
|
||||
v.hasCustomFuncs = true
|
||||
}
|
||||
|
||||
// RegisterTranslation registers translations against the provided tag.
|
||||
func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) (err error) {
|
||||
|
||||
if v.transTagFunc == nil {
|
||||
v.transTagFunc = make(map[ut.Translator]map[string]TranslationFunc)
|
||||
}
|
||||
|
||||
if err = registerFn(trans); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
m, ok := v.transTagFunc[trans]
|
||||
if !ok {
|
||||
m = make(map[string]TranslationFunc)
|
||||
v.transTagFunc[trans] = m
|
||||
}
|
||||
|
||||
m[tag] = translationFn
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) Struct(s interface{}) error {
|
||||
return v.StructCtx(context.Background(), s)
|
||||
}
|
||||
|
||||
// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
|
||||
// and also allows passing of context.Context for contextual validation information.
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
|
||||
|
||||
val := reflect.ValueOf(s)
|
||||
top := val
|
||||
|
||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
// good to validate
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = top
|
||||
vd.isPartial = false
|
||||
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
|
||||
|
||||
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
|
||||
v.pool.Put(vd)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates
|
||||
// nested structs, unless otherwise specified.
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructFiltered(s interface{}, fn FilterFunc) error {
|
||||
return v.StructFilteredCtx(context.Background(), s, fn)
|
||||
}
|
||||
|
||||
// StructFilteredCtx validates a structs exposed fields, that pass the FilterFunc check and automatically validates
|
||||
// nested structs, unless otherwise specified and also allows passing of contextual validation information via
|
||||
// context.Context
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn FilterFunc) (err error) {
|
||||
val := reflect.ValueOf(s)
|
||||
top := val
|
||||
|
||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
// good to validate
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = top
|
||||
vd.isPartial = true
|
||||
vd.ffn = fn
|
||||
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
|
||||
|
||||
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
|
||||
v.pool.Put(vd)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StructPartial validates the fields passed in only, ignoring all others.
|
||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
||||
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructPartial(s interface{}, fields ...string) error {
|
||||
return v.StructPartialCtx(context.Background(), s, fields...)
|
||||
}
|
||||
|
||||
// StructPartialCtx validates the fields passed in only, ignoring all others and allows passing of contextual
|
||||
// validation validation information via context.Context
|
||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
||||
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
|
||||
val := reflect.ValueOf(s)
|
||||
top := val
|
||||
|
||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
// good to validate
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = top
|
||||
vd.isPartial = true
|
||||
vd.ffn = nil
|
||||
vd.hasExcludes = false
|
||||
vd.includeExclude = make(map[string]struct{})
|
||||
|
||||
typ := val.Type()
|
||||
name := typ.Name()
|
||||
|
||||
for _, k := range fields {
|
||||
|
||||
flds := strings.Split(k, namespaceSeparator)
|
||||
if len(flds) > 0 {
|
||||
|
||||
vd.misc = append(vd.misc[0:0], name...)
|
||||
// Don't append empty name for unnamed structs
|
||||
if len(vd.misc) != 0 {
|
||||
vd.misc = append(vd.misc, '.')
|
||||
}
|
||||
|
||||
for _, s := range flds {
|
||||
|
||||
idx := strings.Index(s, leftBracket)
|
||||
|
||||
if idx != -1 {
|
||||
for idx != -1 {
|
||||
vd.misc = append(vd.misc, s[:idx]...)
|
||||
vd.includeExclude[string(vd.misc)] = struct{}{}
|
||||
|
||||
idx2 := strings.Index(s, rightBracket)
|
||||
idx2++
|
||||
vd.misc = append(vd.misc, s[idx:idx2]...)
|
||||
vd.includeExclude[string(vd.misc)] = struct{}{}
|
||||
s = s[idx2:]
|
||||
idx = strings.Index(s, leftBracket)
|
||||
}
|
||||
} else {
|
||||
|
||||
vd.misc = append(vd.misc, s...)
|
||||
vd.includeExclude[string(vd.misc)] = struct{}{}
|
||||
}
|
||||
|
||||
vd.misc = append(vd.misc, '.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
|
||||
v.pool.Put(vd)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StructExcept validates all fields except the ones passed in.
|
||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
||||
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructExcept(s interface{}, fields ...string) error {
|
||||
return v.StructExceptCtx(context.Background(), s, fields...)
|
||||
}
|
||||
|
||||
// StructExceptCtx validates all fields except the ones passed in and allows passing of contextual
|
||||
// validation validation information via context.Context
|
||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
||||
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
|
||||
val := reflect.ValueOf(s)
|
||||
top := val
|
||||
|
||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Struct || val.Type() == timeType {
|
||||
return &InvalidValidationError{Type: reflect.TypeOf(s)}
|
||||
}
|
||||
|
||||
// good to validate
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = top
|
||||
vd.isPartial = true
|
||||
vd.ffn = nil
|
||||
vd.hasExcludes = true
|
||||
vd.includeExclude = make(map[string]struct{})
|
||||
|
||||
typ := val.Type()
|
||||
name := typ.Name()
|
||||
|
||||
for _, key := range fields {
|
||||
|
||||
vd.misc = vd.misc[0:0]
|
||||
|
||||
if len(name) > 0 {
|
||||
vd.misc = append(vd.misc, name...)
|
||||
vd.misc = append(vd.misc, '.')
|
||||
}
|
||||
|
||||
vd.misc = append(vd.misc, key...)
|
||||
vd.includeExclude[string(vd.misc)] = struct{}{}
|
||||
}
|
||||
|
||||
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
|
||||
v.pool.Put(vd)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Var validates a single variable using tag style validation.
|
||||
// eg.
|
||||
// var i int
|
||||
// validate.Var(i, "gt=1,lt=10")
|
||||
//
|
||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
||||
// if you have a custom type and have registered a custom type handler, so must
|
||||
// allow it; however unforeseen validations will occur if trying to validate a
|
||||
// struct that is meant to be passed to 'validate.Struct'
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
// validate Array, Slice and maps fields which may contain more than one error
|
||||
func (v *Validate) Var(field interface{}, tag string) error {
|
||||
return v.VarCtx(context.Background(), field, tag)
|
||||
}
|
||||
|
||||
// VarCtx validates a single variable using tag style validation and allows passing of contextual
|
||||
// validation validation information via context.Context.
|
||||
// eg.
|
||||
// var i int
|
||||
// validate.Var(i, "gt=1,lt=10")
|
||||
//
|
||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
||||
// if you have a custom type and have registered a custom type handler, so must
|
||||
// allow it; however unforeseen validations will occur if trying to validate a
|
||||
// struct that is meant to be passed to 'validate.Struct'
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
// validate Array, Slice and maps fields which may contain more than one error
|
||||
func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (err error) {
|
||||
if len(tag) == 0 || tag == skipValidationTag {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctag := v.fetchCacheTag(tag)
|
||||
val := reflect.ValueOf(field)
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = val
|
||||
vd.isPartial = false
|
||||
vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
v.pool.Put(vd)
|
||||
return
|
||||
}
|
||||
|
||||
// VarWithValue validates a single variable, against another variable/field's value using tag style validation
|
||||
// eg.
|
||||
// s1 := "abcd"
|
||||
// s2 := "abcd"
|
||||
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
|
||||
//
|
||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
||||
// if you have a custom type and have registered a custom type handler, so must
|
||||
// allow it; however unforeseen validations will occur if trying to validate a
|
||||
// struct that is meant to be passed to 'validate.Struct'
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
// validate Array, Slice and maps fields which may contain more than one error
|
||||
func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error {
|
||||
return v.VarWithValueCtx(context.Background(), field, other, tag)
|
||||
}
|
||||
|
||||
// VarWithValueCtx validates a single variable, against another variable/field's value using tag style validation and
|
||||
// allows passing of contextual validation validation information via context.Context.
|
||||
// eg.
|
||||
// s1 := "abcd"
|
||||
// s2 := "abcd"
|
||||
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
|
||||
//
|
||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
||||
// if you have a custom type and have registered a custom type handler, so must
|
||||
// allow it; however unforeseen validations will occur if trying to validate a
|
||||
// struct that is meant to be passed to 'validate.Struct'
|
||||
//
|
||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
||||
// validate Array, Slice and maps fields which may contain more than one error
|
||||
func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other interface{}, tag string) (err error) {
|
||||
if len(tag) == 0 || tag == skipValidationTag {
|
||||
return nil
|
||||
}
|
||||
ctag := v.fetchCacheTag(tag)
|
||||
otherVal := reflect.ValueOf(other)
|
||||
vd := v.pool.Get().(*validate)
|
||||
vd.top = otherVal
|
||||
vd.isPartial = false
|
||||
vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
|
||||
|
||||
if len(vd.errs) > 0 {
|
||||
err = vd.errs
|
||||
vd.errs = nil
|
||||
}
|
||||
v.pool.Put(vd)
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user