You've already forked golang-base-project
Initial commit
This commit is contained in:
24
vendor/github.com/go-playground/locales/.gitignore
generated
vendored
Normal file
24
vendor/github.com/go-playground/locales/.gitignore
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
26
vendor/github.com/go-playground/locales/.travis.yml
generated
vendored
Normal file
26
vendor/github.com/go-playground/locales/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.13.1
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients: dean.karn@gmail.com
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
before_install:
|
||||
- go install github.com/mattn/goveralls
|
||||
|
||||
# Only clone the most recent commit.
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
script:
|
||||
- go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
|
||||
|
||||
after_success: |
|
||||
goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
|
21
vendor/github.com/go-playground/locales/LICENSE
generated
vendored
Normal file
21
vendor/github.com/go-playground/locales/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Go Playground
|
||||
|
||||
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.
|
172
vendor/github.com/go-playground/locales/README.md
generated
vendored
Normal file
172
vendor/github.com/go-playground/locales/README.md
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
## locales
|
||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/locales/master/logo.png">
|
||||
[](https://travis-ci.org/go-playground/locales)
|
||||
[](https://goreportcard.com/report/github.com/go-playground/locales)
|
||||
[](https://godoc.org/github.com/go-playground/locales)
|
||||

|
||||
[](https://gitter.im/go-playground/locales?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
Locales is a set of locales generated from the [Unicode CLDR Project](http://cldr.unicode.org/) which can be used independently or within
|
||||
an i18n package; these were built for use with, but not exclusive to, [Universal Translator](https://github.com/go-playground/universal-translator).
|
||||
|
||||
Features
|
||||
--------
|
||||
- [x] Rules generated from the latest [CLDR](http://cldr.unicode.org/index/downloads) data, v31.0.1
|
||||
- [x] Contains Cardinal, Ordinal and Range Plural Rules
|
||||
- [x] Contains Month, Weekday and Timezone translations built in
|
||||
- [x] Contains Date & Time formatting functions
|
||||
- [x] Contains Number, Currency, Accounting and Percent formatting functions
|
||||
- [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere )
|
||||
|
||||
Full Tests
|
||||
--------------------
|
||||
I could sure use your help adding tests for every locale, it is a huge undertaking and I just don't have the free time to do it all at the moment;
|
||||
any help would be **greatly appreciated!!!!** please see [issue](https://github.com/go-playground/locales/issues/1) for details.
|
||||
|
||||
Installation
|
||||
-----------
|
||||
|
||||
Use go get
|
||||
|
||||
```shell
|
||||
go get github.com/go-playground/locales
|
||||
```
|
||||
|
||||
NOTES
|
||||
--------
|
||||
You'll notice most return types are []byte, this is because most of the time the results will be concatenated with a larger body
|
||||
of text and can avoid some allocations if already appending to a byte array, otherwise just cast as string.
|
||||
|
||||
Usage
|
||||
-------
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/locales/currency"
|
||||
"github.com/go-playground/locales/en_CA"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
loc, _ := time.LoadLocation("America/Toronto")
|
||||
datetime := time.Date(2016, 02, 03, 9, 0, 1, 0, loc)
|
||||
|
||||
l := en_CA.New()
|
||||
|
||||
// Dates
|
||||
fmt.Println(l.FmtDateFull(datetime))
|
||||
fmt.Println(l.FmtDateLong(datetime))
|
||||
fmt.Println(l.FmtDateMedium(datetime))
|
||||
fmt.Println(l.FmtDateShort(datetime))
|
||||
|
||||
// Times
|
||||
fmt.Println(l.FmtTimeFull(datetime))
|
||||
fmt.Println(l.FmtTimeLong(datetime))
|
||||
fmt.Println(l.FmtTimeMedium(datetime))
|
||||
fmt.Println(l.FmtTimeShort(datetime))
|
||||
|
||||
// Months Wide
|
||||
fmt.Println(l.MonthWide(time.January))
|
||||
fmt.Println(l.MonthWide(time.February))
|
||||
fmt.Println(l.MonthWide(time.March))
|
||||
// ...
|
||||
|
||||
// Months Abbreviated
|
||||
fmt.Println(l.MonthAbbreviated(time.January))
|
||||
fmt.Println(l.MonthAbbreviated(time.February))
|
||||
fmt.Println(l.MonthAbbreviated(time.March))
|
||||
// ...
|
||||
|
||||
// Months Narrow
|
||||
fmt.Println(l.MonthNarrow(time.January))
|
||||
fmt.Println(l.MonthNarrow(time.February))
|
||||
fmt.Println(l.MonthNarrow(time.March))
|
||||
// ...
|
||||
|
||||
// Weekdays Wide
|
||||
fmt.Println(l.WeekdayWide(time.Sunday))
|
||||
fmt.Println(l.WeekdayWide(time.Monday))
|
||||
fmt.Println(l.WeekdayWide(time.Tuesday))
|
||||
// ...
|
||||
|
||||
// Weekdays Abbreviated
|
||||
fmt.Println(l.WeekdayAbbreviated(time.Sunday))
|
||||
fmt.Println(l.WeekdayAbbreviated(time.Monday))
|
||||
fmt.Println(l.WeekdayAbbreviated(time.Tuesday))
|
||||
// ...
|
||||
|
||||
// Weekdays Short
|
||||
fmt.Println(l.WeekdayShort(time.Sunday))
|
||||
fmt.Println(l.WeekdayShort(time.Monday))
|
||||
fmt.Println(l.WeekdayShort(time.Tuesday))
|
||||
// ...
|
||||
|
||||
// Weekdays Narrow
|
||||
fmt.Println(l.WeekdayNarrow(time.Sunday))
|
||||
fmt.Println(l.WeekdayNarrow(time.Monday))
|
||||
fmt.Println(l.WeekdayNarrow(time.Tuesday))
|
||||
// ...
|
||||
|
||||
var f64 float64
|
||||
|
||||
f64 = -10356.4523
|
||||
|
||||
// Number
|
||||
fmt.Println(l.FmtNumber(f64, 2))
|
||||
|
||||
// Currency
|
||||
fmt.Println(l.FmtCurrency(f64, 2, currency.CAD))
|
||||
fmt.Println(l.FmtCurrency(f64, 2, currency.USD))
|
||||
|
||||
// Accounting
|
||||
fmt.Println(l.FmtAccounting(f64, 2, currency.CAD))
|
||||
fmt.Println(l.FmtAccounting(f64, 2, currency.USD))
|
||||
|
||||
f64 = 78.12
|
||||
|
||||
// Percent
|
||||
fmt.Println(l.FmtPercent(f64, 0))
|
||||
|
||||
// Plural Rules for locale, so you know what rules you must cover
|
||||
fmt.Println(l.PluralsCardinal())
|
||||
fmt.Println(l.PluralsOrdinal())
|
||||
|
||||
// Cardinal Plural Rules
|
||||
fmt.Println(l.CardinalPluralRule(1, 0))
|
||||
fmt.Println(l.CardinalPluralRule(1.0, 0))
|
||||
fmt.Println(l.CardinalPluralRule(1.0, 1))
|
||||
fmt.Println(l.CardinalPluralRule(3, 0))
|
||||
|
||||
// Ordinal Plural Rules
|
||||
fmt.Println(l.OrdinalPluralRule(21, 0)) // 21st
|
||||
fmt.Println(l.OrdinalPluralRule(22, 0)) // 22nd
|
||||
fmt.Println(l.OrdinalPluralRule(33, 0)) // 33rd
|
||||
fmt.Println(l.OrdinalPluralRule(34, 0)) // 34th
|
||||
|
||||
// Range Plural Rules
|
||||
fmt.Println(l.RangePluralRule(1, 0, 1, 0)) // 1-1
|
||||
fmt.Println(l.RangePluralRule(1, 0, 2, 0)) // 1-2
|
||||
fmt.Println(l.RangePluralRule(5, 0, 8, 0)) // 5-8
|
||||
}
|
||||
```
|
||||
|
||||
NOTES:
|
||||
-------
|
||||
These rules were generated from the [Unicode CLDR Project](http://cldr.unicode.org/), if you encounter any issues
|
||||
I strongly encourage contributing to the CLDR project to get the locale information corrected and the next time
|
||||
these locales are regenerated the fix will come with.
|
||||
|
||||
I do however realize that time constraints are often important and so there are two options:
|
||||
|
||||
1. Create your own locale, copy, paste and modify, and ensure it complies with the `Translator` interface.
|
||||
2. Add an exception in the locale generation code directly and once regenerated, fix will be in place.
|
||||
|
||||
Please to not make fixes inside the locale files, they WILL get overwritten when the locales are regenerated.
|
||||
|
||||
License
|
||||
------
|
||||
Distributed under MIT License, please see license file in code for more details.
|
308
vendor/github.com/go-playground/locales/currency/currency.go
generated
vendored
Normal file
308
vendor/github.com/go-playground/locales/currency/currency.go
generated
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
package currency
|
||||
|
||||
// Type is the currency type associated with the locales currency enum
|
||||
type Type int
|
||||
|
||||
// locale currencies
|
||||
const (
|
||||
ADP Type = iota
|
||||
AED
|
||||
AFA
|
||||
AFN
|
||||
ALK
|
||||
ALL
|
||||
AMD
|
||||
ANG
|
||||
AOA
|
||||
AOK
|
||||
AON
|
||||
AOR
|
||||
ARA
|
||||
ARL
|
||||
ARM
|
||||
ARP
|
||||
ARS
|
||||
ATS
|
||||
AUD
|
||||
AWG
|
||||
AZM
|
||||
AZN
|
||||
BAD
|
||||
BAM
|
||||
BAN
|
||||
BBD
|
||||
BDT
|
||||
BEC
|
||||
BEF
|
||||
BEL
|
||||
BGL
|
||||
BGM
|
||||
BGN
|
||||
BGO
|
||||
BHD
|
||||
BIF
|
||||
BMD
|
||||
BND
|
||||
BOB
|
||||
BOL
|
||||
BOP
|
||||
BOV
|
||||
BRB
|
||||
BRC
|
||||
BRE
|
||||
BRL
|
||||
BRN
|
||||
BRR
|
||||
BRZ
|
||||
BSD
|
||||
BTN
|
||||
BUK
|
||||
BWP
|
||||
BYB
|
||||
BYN
|
||||
BYR
|
||||
BZD
|
||||
CAD
|
||||
CDF
|
||||
CHE
|
||||
CHF
|
||||
CHW
|
||||
CLE
|
||||
CLF
|
||||
CLP
|
||||
CNH
|
||||
CNX
|
||||
CNY
|
||||
COP
|
||||
COU
|
||||
CRC
|
||||
CSD
|
||||
CSK
|
||||
CUC
|
||||
CUP
|
||||
CVE
|
||||
CYP
|
||||
CZK
|
||||
DDM
|
||||
DEM
|
||||
DJF
|
||||
DKK
|
||||
DOP
|
||||
DZD
|
||||
ECS
|
||||
ECV
|
||||
EEK
|
||||
EGP
|
||||
ERN
|
||||
ESA
|
||||
ESB
|
||||
ESP
|
||||
ETB
|
||||
EUR
|
||||
FIM
|
||||
FJD
|
||||
FKP
|
||||
FRF
|
||||
GBP
|
||||
GEK
|
||||
GEL
|
||||
GHC
|
||||
GHS
|
||||
GIP
|
||||
GMD
|
||||
GNF
|
||||
GNS
|
||||
GQE
|
||||
GRD
|
||||
GTQ
|
||||
GWE
|
||||
GWP
|
||||
GYD
|
||||
HKD
|
||||
HNL
|
||||
HRD
|
||||
HRK
|
||||
HTG
|
||||
HUF
|
||||
IDR
|
||||
IEP
|
||||
ILP
|
||||
ILR
|
||||
ILS
|
||||
INR
|
||||
IQD
|
||||
IRR
|
||||
ISJ
|
||||
ISK
|
||||
ITL
|
||||
JMD
|
||||
JOD
|
||||
JPY
|
||||
KES
|
||||
KGS
|
||||
KHR
|
||||
KMF
|
||||
KPW
|
||||
KRH
|
||||
KRO
|
||||
KRW
|
||||
KWD
|
||||
KYD
|
||||
KZT
|
||||
LAK
|
||||
LBP
|
||||
LKR
|
||||
LRD
|
||||
LSL
|
||||
LTL
|
||||
LTT
|
||||
LUC
|
||||
LUF
|
||||
LUL
|
||||
LVL
|
||||
LVR
|
||||
LYD
|
||||
MAD
|
||||
MAF
|
||||
MCF
|
||||
MDC
|
||||
MDL
|
||||
MGA
|
||||
MGF
|
||||
MKD
|
||||
MKN
|
||||
MLF
|
||||
MMK
|
||||
MNT
|
||||
MOP
|
||||
MRO
|
||||
MTL
|
||||
MTP
|
||||
MUR
|
||||
MVP
|
||||
MVR
|
||||
MWK
|
||||
MXN
|
||||
MXP
|
||||
MXV
|
||||
MYR
|
||||
MZE
|
||||
MZM
|
||||
MZN
|
||||
NAD
|
||||
NGN
|
||||
NIC
|
||||
NIO
|
||||
NLG
|
||||
NOK
|
||||
NPR
|
||||
NZD
|
||||
OMR
|
||||
PAB
|
||||
PEI
|
||||
PEN
|
||||
PES
|
||||
PGK
|
||||
PHP
|
||||
PKR
|
||||
PLN
|
||||
PLZ
|
||||
PTE
|
||||
PYG
|
||||
QAR
|
||||
RHD
|
||||
ROL
|
||||
RON
|
||||
RSD
|
||||
RUB
|
||||
RUR
|
||||
RWF
|
||||
SAR
|
||||
SBD
|
||||
SCR
|
||||
SDD
|
||||
SDG
|
||||
SDP
|
||||
SEK
|
||||
SGD
|
||||
SHP
|
||||
SIT
|
||||
SKK
|
||||
SLL
|
||||
SOS
|
||||
SRD
|
||||
SRG
|
||||
SSP
|
||||
STD
|
||||
STN
|
||||
SUR
|
||||
SVC
|
||||
SYP
|
||||
SZL
|
||||
THB
|
||||
TJR
|
||||
TJS
|
||||
TMM
|
||||
TMT
|
||||
TND
|
||||
TOP
|
||||
TPE
|
||||
TRL
|
||||
TRY
|
||||
TTD
|
||||
TWD
|
||||
TZS
|
||||
UAH
|
||||
UAK
|
||||
UGS
|
||||
UGX
|
||||
USD
|
||||
USN
|
||||
USS
|
||||
UYI
|
||||
UYP
|
||||
UYU
|
||||
UZS
|
||||
VEB
|
||||
VEF
|
||||
VND
|
||||
VNN
|
||||
VUV
|
||||
WST
|
||||
XAF
|
||||
XAG
|
||||
XAU
|
||||
XBA
|
||||
XBB
|
||||
XBC
|
||||
XBD
|
||||
XCD
|
||||
XDR
|
||||
XEU
|
||||
XFO
|
||||
XFU
|
||||
XOF
|
||||
XPD
|
||||
XPF
|
||||
XPT
|
||||
XRE
|
||||
XSU
|
||||
XTS
|
||||
XUA
|
||||
XXX
|
||||
YDD
|
||||
YER
|
||||
YUD
|
||||
YUM
|
||||
YUN
|
||||
YUR
|
||||
ZAL
|
||||
ZAR
|
||||
ZMK
|
||||
ZMW
|
||||
ZRN
|
||||
ZRZ
|
||||
ZWD
|
||||
ZWL
|
||||
ZWR
|
||||
)
|
5
vendor/github.com/go-playground/locales/go.mod
generated
vendored
Normal file
5
vendor/github.com/go-playground/locales/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/go-playground/locales
|
||||
|
||||
go 1.13
|
||||
|
||||
require golang.org/x/text v0.3.2
|
3
vendor/github.com/go-playground/locales/go.sum
generated
vendored
Normal file
3
vendor/github.com/go-playground/locales/go.sum
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
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/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
BIN
vendor/github.com/go-playground/locales/logo.png
generated
vendored
Normal file
BIN
vendor/github.com/go-playground/locales/logo.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
293
vendor/github.com/go-playground/locales/rules.go
generated
vendored
Normal file
293
vendor/github.com/go-playground/locales/rules.go
generated
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
package locales
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/locales/currency"
|
||||
)
|
||||
|
||||
// // ErrBadNumberValue is returned when the number passed for
|
||||
// // plural rule determination cannot be parsed
|
||||
// type ErrBadNumberValue struct {
|
||||
// NumberValue string
|
||||
// InnerError error
|
||||
// }
|
||||
|
||||
// // Error returns ErrBadNumberValue error string
|
||||
// func (e *ErrBadNumberValue) Error() string {
|
||||
// return fmt.Sprintf("Invalid Number Value '%s' %s", e.NumberValue, e.InnerError)
|
||||
// }
|
||||
|
||||
// var _ error = new(ErrBadNumberValue)
|
||||
|
||||
// PluralRule denotes the type of plural rules
|
||||
type PluralRule int
|
||||
|
||||
// PluralRule's
|
||||
const (
|
||||
PluralRuleUnknown PluralRule = iota
|
||||
PluralRuleZero // zero
|
||||
PluralRuleOne // one - singular
|
||||
PluralRuleTwo // two - dual
|
||||
PluralRuleFew // few - paucal
|
||||
PluralRuleMany // many - also used for fractions if they have a separate class
|
||||
PluralRuleOther // other - required—general plural form—also used if the language only has a single form
|
||||
)
|
||||
|
||||
const (
|
||||
pluralsString = "UnknownZeroOneTwoFewManyOther"
|
||||
)
|
||||
|
||||
// Translator encapsulates an instance of a locale
|
||||
// NOTE: some values are returned as a []byte just in case the caller
|
||||
// wishes to add more and can help avoid allocations; otherwise just cast as string
|
||||
type Translator interface {
|
||||
|
||||
// The following Functions are for overriding, debugging or developing
|
||||
// with a Translator Locale
|
||||
|
||||
// Locale returns the string value of the translator
|
||||
Locale() string
|
||||
|
||||
// returns an array of cardinal plural rules associated
|
||||
// with this translator
|
||||
PluralsCardinal() []PluralRule
|
||||
|
||||
// returns an array of ordinal plural rules associated
|
||||
// with this translator
|
||||
PluralsOrdinal() []PluralRule
|
||||
|
||||
// returns an array of range plural rules associated
|
||||
// with this translator
|
||||
PluralsRange() []PluralRule
|
||||
|
||||
// returns the cardinal PluralRule given 'num' and digits/precision of 'v' for locale
|
||||
CardinalPluralRule(num float64, v uint64) PluralRule
|
||||
|
||||
// returns the ordinal PluralRule given 'num' and digits/precision of 'v' for locale
|
||||
OrdinalPluralRule(num float64, v uint64) PluralRule
|
||||
|
||||
// returns the ordinal PluralRule given 'num1', 'num2' and digits/precision of 'v1' and 'v2' for locale
|
||||
RangePluralRule(num1 float64, v1 uint64, num2 float64, v2 uint64) PluralRule
|
||||
|
||||
// returns the locales abbreviated month given the 'month' provided
|
||||
MonthAbbreviated(month time.Month) string
|
||||
|
||||
// returns the locales abbreviated months
|
||||
MonthsAbbreviated() []string
|
||||
|
||||
// returns the locales narrow month given the 'month' provided
|
||||
MonthNarrow(month time.Month) string
|
||||
|
||||
// returns the locales narrow months
|
||||
MonthsNarrow() []string
|
||||
|
||||
// returns the locales wide month given the 'month' provided
|
||||
MonthWide(month time.Month) string
|
||||
|
||||
// returns the locales wide months
|
||||
MonthsWide() []string
|
||||
|
||||
// returns the locales abbreviated weekday given the 'weekday' provided
|
||||
WeekdayAbbreviated(weekday time.Weekday) string
|
||||
|
||||
// returns the locales abbreviated weekdays
|
||||
WeekdaysAbbreviated() []string
|
||||
|
||||
// returns the locales narrow weekday given the 'weekday' provided
|
||||
WeekdayNarrow(weekday time.Weekday) string
|
||||
|
||||
// WeekdaysNarrowreturns the locales narrow weekdays
|
||||
WeekdaysNarrow() []string
|
||||
|
||||
// returns the locales short weekday given the 'weekday' provided
|
||||
WeekdayShort(weekday time.Weekday) string
|
||||
|
||||
// returns the locales short weekdays
|
||||
WeekdaysShort() []string
|
||||
|
||||
// returns the locales wide weekday given the 'weekday' provided
|
||||
WeekdayWide(weekday time.Weekday) string
|
||||
|
||||
// returns the locales wide weekdays
|
||||
WeekdaysWide() []string
|
||||
|
||||
// The following Functions are common Formatting functionsfor the Translator's Locale
|
||||
|
||||
// returns 'num' with digits/precision of 'v' for locale and handles both Whole and Real numbers based on 'v'
|
||||
FmtNumber(num float64, v uint64) string
|
||||
|
||||
// returns 'num' with digits/precision of 'v' for locale and handles both Whole and Real numbers based on 'v'
|
||||
// NOTE: 'num' passed into FmtPercent is assumed to be in percent already
|
||||
FmtPercent(num float64, v uint64) string
|
||||
|
||||
// returns the currency representation of 'num' with digits/precision of 'v' for locale
|
||||
FmtCurrency(num float64, v uint64, currency currency.Type) string
|
||||
|
||||
// returns the currency representation of 'num' with digits/precision of 'v' for locale
|
||||
// in accounting notation.
|
||||
FmtAccounting(num float64, v uint64, currency currency.Type) string
|
||||
|
||||
// returns the short date representation of 't' for locale
|
||||
FmtDateShort(t time.Time) string
|
||||
|
||||
// returns the medium date representation of 't' for locale
|
||||
FmtDateMedium(t time.Time) string
|
||||
|
||||
// returns the long date representation of 't' for locale
|
||||
FmtDateLong(t time.Time) string
|
||||
|
||||
// returns the full date representation of 't' for locale
|
||||
FmtDateFull(t time.Time) string
|
||||
|
||||
// returns the short time representation of 't' for locale
|
||||
FmtTimeShort(t time.Time) string
|
||||
|
||||
// returns the medium time representation of 't' for locale
|
||||
FmtTimeMedium(t time.Time) string
|
||||
|
||||
// returns the long time representation of 't' for locale
|
||||
FmtTimeLong(t time.Time) string
|
||||
|
||||
// returns the full time representation of 't' for locale
|
||||
FmtTimeFull(t time.Time) string
|
||||
}
|
||||
|
||||
// String returns the string value of PluralRule
|
||||
func (p PluralRule) String() string {
|
||||
|
||||
switch p {
|
||||
case PluralRuleZero:
|
||||
return pluralsString[7:11]
|
||||
case PluralRuleOne:
|
||||
return pluralsString[11:14]
|
||||
case PluralRuleTwo:
|
||||
return pluralsString[14:17]
|
||||
case PluralRuleFew:
|
||||
return pluralsString[17:20]
|
||||
case PluralRuleMany:
|
||||
return pluralsString[20:24]
|
||||
case PluralRuleOther:
|
||||
return pluralsString[24:]
|
||||
default:
|
||||
return pluralsString[:7]
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Precision Notes:
|
||||
//
|
||||
// must specify a precision >= 0, and here is why https://play.golang.org/p/LyL90U0Vyh
|
||||
//
|
||||
// v := float64(3.141)
|
||||
// i := float64(int64(v))
|
||||
//
|
||||
// fmt.Println(v - i)
|
||||
//
|
||||
// or
|
||||
//
|
||||
// s := strconv.FormatFloat(v-i, 'f', -1, 64)
|
||||
// fmt.Println(s)
|
||||
//
|
||||
// these will not print what you'd expect: 0.14100000000000001
|
||||
// and so this library requires a precision to be specified, or
|
||||
// inaccurate plural rules could be applied.
|
||||
//
|
||||
//
|
||||
//
|
||||
// n - absolute value of the source number (integer and decimals).
|
||||
// i - integer digits of n.
|
||||
// v - number of visible fraction digits in n, with trailing zeros.
|
||||
// w - number of visible fraction digits in n, without trailing zeros.
|
||||
// f - visible fractional digits in n, with trailing zeros.
|
||||
// t - visible fractional digits in n, without trailing zeros.
|
||||
//
|
||||
//
|
||||
// Func(num float64, v uint64) // v = digits/precision and prevents -1 as a special case as this can lead to very unexpected behaviour, see precision note's above.
|
||||
//
|
||||
// n := math.Abs(num)
|
||||
// i := int64(n)
|
||||
// v := v
|
||||
//
|
||||
//
|
||||
// w := strconv.FormatFloat(num-float64(i), 'f', int(v), 64) // then parse backwards on string until no more zero's....
|
||||
// f := strconv.FormatFloat(n, 'f', int(v), 64) // then turn everything after decimal into an int64
|
||||
// t := strconv.FormatFloat(n, 'f', int(v), 64) // then parse backwards on string until no more zero's....
|
||||
//
|
||||
//
|
||||
//
|
||||
// General Inclusion Rules
|
||||
// - v will always be available inherently
|
||||
// - all require n
|
||||
// - w requires i
|
||||
//
|
||||
|
||||
// W returns the number of visible fraction digits in N, without trailing zeros.
|
||||
func W(n float64, v uint64) (w int64) {
|
||||
|
||||
s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
|
||||
|
||||
// with either be '0' or '0.xxxx', so if 1 then w will be zero
|
||||
// otherwise need to parse
|
||||
if len(s) != 1 {
|
||||
|
||||
s = s[2:]
|
||||
end := len(s) + 1
|
||||
|
||||
for i := end; i >= 0; i-- {
|
||||
if s[i] != '0' {
|
||||
end = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
w = int64(len(s[:end]))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// F returns the visible fractional digits in N, with trailing zeros.
|
||||
func F(n float64, v uint64) (f int64) {
|
||||
|
||||
s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
|
||||
|
||||
// with either be '0' or '0.xxxx', so if 1 then f will be zero
|
||||
// otherwise need to parse
|
||||
if len(s) != 1 {
|
||||
|
||||
// ignoring error, because it can't fail as we generated
|
||||
// the string internally from a real number
|
||||
f, _ = strconv.ParseInt(s[2:], 10, 64)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// T returns the visible fractional digits in N, without trailing zeros.
|
||||
func T(n float64, v uint64) (t int64) {
|
||||
|
||||
s := strconv.FormatFloat(n-float64(int64(n)), 'f', int(v), 64)
|
||||
|
||||
// with either be '0' or '0.xxxx', so if 1 then t will be zero
|
||||
// otherwise need to parse
|
||||
if len(s) != 1 {
|
||||
|
||||
s = s[2:]
|
||||
end := len(s) + 1
|
||||
|
||||
for i := end; i >= 0; i-- {
|
||||
if s[i] != '0' {
|
||||
end = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// ignoring error, because it can't fail as we generated
|
||||
// the string internally from a real number
|
||||
t, _ = strconv.ParseInt(s[:end], 10, 64)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
25
vendor/github.com/go-playground/universal-translator/.gitignore
generated
vendored
Normal file
25
vendor/github.com/go-playground/universal-translator/.gitignore
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
*.coverprofile
|
27
vendor/github.com/go-playground/universal-translator/.travis.yml
generated
vendored
Normal file
27
vendor/github.com/go-playground/universal-translator/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.13.4
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients: dean.karn@gmail.com
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
before_install:
|
||||
- go install github.com/mattn/goveralls
|
||||
|
||||
# Only clone the most recent commit.
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
script:
|
||||
- go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
|
||||
|
||||
after_success: |
|
||||
[ $TRAVIS_GO_VERSION = 1.13.4 ] &&
|
||||
goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
|
21
vendor/github.com/go-playground/universal-translator/LICENSE
generated
vendored
Normal file
21
vendor/github.com/go-playground/universal-translator/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Go Playground
|
||||
|
||||
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.
|
89
vendor/github.com/go-playground/universal-translator/README.md
generated
vendored
Normal file
89
vendor/github.com/go-playground/universal-translator/README.md
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
## universal-translator
|
||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png">
|
||||
[](https://travis-ci.org/go-playground/universal-translator)
|
||||
[](https://coveralls.io/github/go-playground/universal-translator)
|
||||
[](https://goreportcard.com/report/github.com/go-playground/universal-translator)
|
||||
[](https://godoc.org/github.com/go-playground/universal-translator)
|
||||

|
||||
[](https://gitter.im/go-playground/universal-translator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
Universal Translator is an i18n Translator for Go/Golang using CLDR data + pluralization rules
|
||||
|
||||
Why another i18n library?
|
||||
--------------------------
|
||||
Because none of the plural rules seem to be correct out there, including the previous implementation of this package,
|
||||
so I took it upon myself to create [locales](https://github.com/go-playground/locales) for everyone to use; this package
|
||||
is a thin wrapper around [locales](https://github.com/go-playground/locales) in order to store and translate text for
|
||||
use in your applications.
|
||||
|
||||
Features
|
||||
--------
|
||||
- [x] Rules generated from the [CLDR](http://cldr.unicode.org/index/downloads) data, v30.0.3
|
||||
- [x] Contains Cardinal, Ordinal and Range Plural Rules
|
||||
- [x] Contains Month, Weekday and Timezone translations built in
|
||||
- [x] Contains Date & Time formatting functions
|
||||
- [x] Contains Number, Currency, Accounting and Percent formatting functions
|
||||
- [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere )
|
||||
- [x] Support loading translations from files
|
||||
- [x] Exporting translations to file(s), mainly for getting them professionally translated
|
||||
- [ ] Code Generation for translation files -> Go code.. i.e. after it has been professionally translated
|
||||
- [ ] Tests for all languages, I need help with this, please see [here](https://github.com/go-playground/locales/issues/1)
|
||||
|
||||
Installation
|
||||
-----------
|
||||
|
||||
Use go get
|
||||
|
||||
```shell
|
||||
go get github.com/go-playground/universal-translator
|
||||
```
|
||||
|
||||
Usage & Documentation
|
||||
-------
|
||||
|
||||
Please see https://godoc.org/github.com/go-playground/universal-translator for usage docs
|
||||
|
||||
##### Examples:
|
||||
|
||||
- [Basic](https://github.com/go-playground/universal-translator/tree/master/_examples/basic)
|
||||
- [Full - no files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-no-files)
|
||||
- [Full - with files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-with-files)
|
||||
|
||||
File formatting
|
||||
--------------
|
||||
All types, Plain substitution, Cardinal, Ordinal and Range translations can all be contained withing the same file(s);
|
||||
they are only separated for easy viewing.
|
||||
|
||||
##### Examples:
|
||||
|
||||
- [Formats](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats)
|
||||
|
||||
##### Basic Makeup
|
||||
NOTE: not all fields are needed for all translation types, see [examples](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats)
|
||||
```json
|
||||
{
|
||||
"locale": "en",
|
||||
"key": "days-left",
|
||||
"trans": "You have {0} day left.",
|
||||
"type": "Cardinal",
|
||||
"rule": "One",
|
||||
"override": false
|
||||
}
|
||||
```
|
||||
|Field|Description|
|
||||
|---|---|
|
||||
|locale|The locale for which the translation is for.|
|
||||
|key|The translation key that will be used to store and lookup each translation; normally it is a string or integer.|
|
||||
|trans|The actual translation text.|
|
||||
|type|The type of translation Cardinal, Ordinal, Range or "" for a plain substitution(not required to be defined if plain used)|
|
||||
|rule|The plural rule for which the translation is for eg. One, Two, Few, Many or Other.(not required to be defined if plain used)|
|
||||
|override|If you wish to override an existing translation that has already been registered, set this to 'true'. 99% of the time there is no need to define it.|
|
||||
|
||||
Help With Tests
|
||||
---------------
|
||||
To anyone interesting in helping or contributing, I sure could use some help creating tests for each language.
|
||||
Please see issue [here](https://github.com/go-playground/locales/issues/1) for details.
|
||||
|
||||
License
|
||||
------
|
||||
Distributed under MIT License, please see license file in code for more details.
|
148
vendor/github.com/go-playground/universal-translator/errors.go
generated
vendored
Normal file
148
vendor/github.com/go-playground/universal-translator/errors.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
package ut
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-playground/locales"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUnknowTranslation indicates the translation could not be found
|
||||
ErrUnknowTranslation = errors.New("Unknown Translation")
|
||||
)
|
||||
|
||||
var _ error = new(ErrConflictingTranslation)
|
||||
var _ error = new(ErrRangeTranslation)
|
||||
var _ error = new(ErrOrdinalTranslation)
|
||||
var _ error = new(ErrCardinalTranslation)
|
||||
var _ error = new(ErrMissingPluralTranslation)
|
||||
var _ error = new(ErrExistingTranslator)
|
||||
|
||||
// ErrExistingTranslator is the error representing a conflicting translator
|
||||
type ErrExistingTranslator struct {
|
||||
locale string
|
||||
}
|
||||
|
||||
// Error returns ErrExistingTranslator's internal error text
|
||||
func (e *ErrExistingTranslator) Error() string {
|
||||
return fmt.Sprintf("error: conflicting translator for locale '%s'", e.locale)
|
||||
}
|
||||
|
||||
// ErrConflictingTranslation is the error representing a conflicting translation
|
||||
type ErrConflictingTranslation struct {
|
||||
locale string
|
||||
key interface{}
|
||||
rule locales.PluralRule
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrConflictingTranslation's internal error text
|
||||
func (e *ErrConflictingTranslation) Error() string {
|
||||
|
||||
if _, ok := e.key.(string); !ok {
|
||||
return fmt.Sprintf("error: conflicting key '%#v' rule '%s' with text '%s' for locale '%s', value being ignored", e.key, e.rule, e.text, e.locale)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("error: conflicting key '%s' rule '%s' with text '%s' for locale '%s', value being ignored", e.key, e.rule, e.text, e.locale)
|
||||
}
|
||||
|
||||
// ErrRangeTranslation is the error representing a range translation error
|
||||
type ErrRangeTranslation struct {
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrRangeTranslation's internal error text
|
||||
func (e *ErrRangeTranslation) Error() string {
|
||||
return e.text
|
||||
}
|
||||
|
||||
// ErrOrdinalTranslation is the error representing an ordinal translation error
|
||||
type ErrOrdinalTranslation struct {
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrOrdinalTranslation's internal error text
|
||||
func (e *ErrOrdinalTranslation) Error() string {
|
||||
return e.text
|
||||
}
|
||||
|
||||
// ErrCardinalTranslation is the error representing a cardinal translation error
|
||||
type ErrCardinalTranslation struct {
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrCardinalTranslation's internal error text
|
||||
func (e *ErrCardinalTranslation) Error() string {
|
||||
return e.text
|
||||
}
|
||||
|
||||
// ErrMissingPluralTranslation is the error signifying a missing translation given
|
||||
// the locales plural rules.
|
||||
type ErrMissingPluralTranslation struct {
|
||||
locale string
|
||||
key interface{}
|
||||
rule locales.PluralRule
|
||||
translationType string
|
||||
}
|
||||
|
||||
// Error returns ErrMissingPluralTranslation's internal error text
|
||||
func (e *ErrMissingPluralTranslation) Error() string {
|
||||
|
||||
if _, ok := e.key.(string); !ok {
|
||||
return fmt.Sprintf("error: missing '%s' plural rule '%s' for translation with key '%#v' and locale '%s'", e.translationType, e.rule, e.key, e.locale)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("error: missing '%s' plural rule '%s' for translation with key '%s' and locale '%s'", e.translationType, e.rule, e.key, e.locale)
|
||||
}
|
||||
|
||||
// ErrMissingBracket is the error representing a missing bracket in a translation
|
||||
// eg. This is a {0 <-- missing ending '}'
|
||||
type ErrMissingBracket struct {
|
||||
locale string
|
||||
key interface{}
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrMissingBracket error message
|
||||
func (e *ErrMissingBracket) Error() string {
|
||||
return fmt.Sprintf("error: missing bracket '{}', in translation. locale: '%s' key: '%v' text: '%s'", e.locale, e.key, e.text)
|
||||
}
|
||||
|
||||
// ErrBadParamSyntax is the error representing a bad parameter definition in a translation
|
||||
// eg. This is a {must-be-int}
|
||||
type ErrBadParamSyntax struct {
|
||||
locale string
|
||||
param string
|
||||
key interface{}
|
||||
text string
|
||||
}
|
||||
|
||||
// Error returns ErrBadParamSyntax error message
|
||||
func (e *ErrBadParamSyntax) Error() string {
|
||||
return fmt.Sprintf("error: bad parameter syntax, missing parameter '%s' in translation. locale: '%s' key: '%v' text: '%s'", e.param, e.locale, e.key, e.text)
|
||||
}
|
||||
|
||||
// import/export errors
|
||||
|
||||
// ErrMissingLocale is the error representing an expected locale that could
|
||||
// not be found aka locale not registered with the UniversalTranslator Instance
|
||||
type ErrMissingLocale struct {
|
||||
locale string
|
||||
}
|
||||
|
||||
// Error returns ErrMissingLocale's internal error text
|
||||
func (e *ErrMissingLocale) Error() string {
|
||||
return fmt.Sprintf("error: locale '%s' not registered.", e.locale)
|
||||
}
|
||||
|
||||
// ErrBadPluralDefinition is the error representing an incorrect plural definition
|
||||
// usually found within translations defined within files during the import process.
|
||||
type ErrBadPluralDefinition struct {
|
||||
tl translation
|
||||
}
|
||||
|
||||
// Error returns ErrBadPluralDefinition's internal error text
|
||||
func (e *ErrBadPluralDefinition) Error() string {
|
||||
return fmt.Sprintf("error: bad plural definition '%#v'", e.tl)
|
||||
}
|
5
vendor/github.com/go-playground/universal-translator/go.mod
generated
vendored
Normal file
5
vendor/github.com/go-playground/universal-translator/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/go-playground/universal-translator
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/go-playground/locales v0.13.0
|
4
vendor/github.com/go-playground/universal-translator/go.sum
generated
vendored
Normal file
4
vendor/github.com/go-playground/universal-translator/go.sum
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
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=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
274
vendor/github.com/go-playground/universal-translator/import_export.go
generated
vendored
Normal file
274
vendor/github.com/go-playground/universal-translator/import_export.go
generated
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
package ut
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"io"
|
||||
|
||||
"github.com/go-playground/locales"
|
||||
)
|
||||
|
||||
type translation struct {
|
||||
Locale string `json:"locale"`
|
||||
Key interface{} `json:"key"` // either string or integer
|
||||
Translation string `json:"trans"`
|
||||
PluralType string `json:"type,omitempty"`
|
||||
PluralRule string `json:"rule,omitempty"`
|
||||
OverrideExisting bool `json:"override,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
cardinalType = "Cardinal"
|
||||
ordinalType = "Ordinal"
|
||||
rangeType = "Range"
|
||||
)
|
||||
|
||||
// ImportExportFormat is the format of the file import or export
|
||||
type ImportExportFormat uint8
|
||||
|
||||
// supported Export Formats
|
||||
const (
|
||||
FormatJSON ImportExportFormat = iota
|
||||
)
|
||||
|
||||
// Export writes the translations out to a file on disk.
|
||||
//
|
||||
// NOTE: this currently only works with string or int translations keys.
|
||||
func (t *UniversalTranslator) Export(format ImportExportFormat, dirname string) error {
|
||||
|
||||
_, err := os.Stat(dirname)
|
||||
fmt.Println(dirname, err, os.IsNotExist(err))
|
||||
if err != nil {
|
||||
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(dirname, 0744); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// build up translations
|
||||
var trans []translation
|
||||
var b []byte
|
||||
var ext string
|
||||
|
||||
for _, locale := range t.translators {
|
||||
|
||||
for k, v := range locale.(*translator).translations {
|
||||
trans = append(trans, translation{
|
||||
Locale: locale.Locale(),
|
||||
Key: k,
|
||||
Translation: v.text,
|
||||
})
|
||||
}
|
||||
|
||||
for k, pluralTrans := range locale.(*translator).cardinalTanslations {
|
||||
|
||||
for i, plural := range pluralTrans {
|
||||
|
||||
// leave enough for all plural rules
|
||||
// but not all are set for all languages.
|
||||
if plural == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
trans = append(trans, translation{
|
||||
Locale: locale.Locale(),
|
||||
Key: k.(string),
|
||||
Translation: plural.text,
|
||||
PluralType: cardinalType,
|
||||
PluralRule: locales.PluralRule(i).String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for k, pluralTrans := range locale.(*translator).ordinalTanslations {
|
||||
|
||||
for i, plural := range pluralTrans {
|
||||
|
||||
// leave enough for all plural rules
|
||||
// but not all are set for all languages.
|
||||
if plural == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
trans = append(trans, translation{
|
||||
Locale: locale.Locale(),
|
||||
Key: k.(string),
|
||||
Translation: plural.text,
|
||||
PluralType: ordinalType,
|
||||
PluralRule: locales.PluralRule(i).String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for k, pluralTrans := range locale.(*translator).rangeTanslations {
|
||||
|
||||
for i, plural := range pluralTrans {
|
||||
|
||||
// leave enough for all plural rules
|
||||
// but not all are set for all languages.
|
||||
if plural == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
trans = append(trans, translation{
|
||||
Locale: locale.Locale(),
|
||||
Key: k.(string),
|
||||
Translation: plural.text,
|
||||
PluralType: rangeType,
|
||||
PluralRule: locales.PluralRule(i).String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
b, err = json.MarshalIndent(trans, "", " ")
|
||||
ext = ".json"
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(dirname, fmt.Sprintf("%s%s", locale.Locale(), ext)), b, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trans = trans[0:0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Import reads the translations out of a file or directory on disk.
|
||||
//
|
||||
// NOTE: this currently only works with string or int translations keys.
|
||||
func (t *UniversalTranslator) Import(format ImportExportFormat, dirnameOrFilename string) error {
|
||||
|
||||
fi, err := os.Stat(dirnameOrFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
processFn := func(filename string) error {
|
||||
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return t.ImportByReader(format, f)
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
return processFn(dirnameOrFilename)
|
||||
}
|
||||
|
||||
// recursively go through directory
|
||||
walker := func(path string, info os.FileInfo, err error) error {
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
// skip non JSON files
|
||||
if filepath.Ext(info.Name()) != ".json" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return processFn(path)
|
||||
}
|
||||
|
||||
return filepath.Walk(dirnameOrFilename, walker)
|
||||
}
|
||||
|
||||
// ImportByReader imports the the translations found within the contents read from the supplied reader.
|
||||
//
|
||||
// NOTE: generally used when assets have been embedded into the binary and are already in memory.
|
||||
func (t *UniversalTranslator) ImportByReader(format ImportExportFormat, reader io.Reader) error {
|
||||
|
||||
b, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var trans []translation
|
||||
|
||||
switch format {
|
||||
case FormatJSON:
|
||||
err = json.Unmarshal(b, &trans)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, tl := range trans {
|
||||
|
||||
locale, found := t.FindTranslator(tl.Locale)
|
||||
if !found {
|
||||
return &ErrMissingLocale{locale: tl.Locale}
|
||||
}
|
||||
|
||||
pr := stringToPR(tl.PluralRule)
|
||||
|
||||
if pr == locales.PluralRuleUnknown {
|
||||
|
||||
err = locale.Add(tl.Key, tl.Translation, tl.OverrideExisting)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch tl.PluralType {
|
||||
case cardinalType:
|
||||
err = locale.AddCardinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
|
||||
case ordinalType:
|
||||
err = locale.AddOrdinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
|
||||
case rangeType:
|
||||
err = locale.AddRange(tl.Key, tl.Translation, pr, tl.OverrideExisting)
|
||||
default:
|
||||
return &ErrBadPluralDefinition{tl: tl}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringToPR(s string) locales.PluralRule {
|
||||
|
||||
switch s {
|
||||
case "One":
|
||||
return locales.PluralRuleOne
|
||||
case "Two":
|
||||
return locales.PluralRuleTwo
|
||||
case "Few":
|
||||
return locales.PluralRuleFew
|
||||
case "Many":
|
||||
return locales.PluralRuleMany
|
||||
case "Other":
|
||||
return locales.PluralRuleOther
|
||||
default:
|
||||
return locales.PluralRuleUnknown
|
||||
}
|
||||
|
||||
}
|
BIN
vendor/github.com/go-playground/universal-translator/logo.png
generated
vendored
Normal file
BIN
vendor/github.com/go-playground/universal-translator/logo.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
420
vendor/github.com/go-playground/universal-translator/translator.go
generated
vendored
Normal file
420
vendor/github.com/go-playground/universal-translator/translator.go
generated
vendored
Normal file
@ -0,0 +1,420 @@
|
||||
package ut
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/locales"
|
||||
)
|
||||
|
||||
const (
|
||||
paramZero = "{0}"
|
||||
paramOne = "{1}"
|
||||
unknownTranslation = ""
|
||||
)
|
||||
|
||||
// Translator is universal translators
|
||||
// translator instance which is a thin wrapper
|
||||
// around locales.Translator instance providing
|
||||
// some extra functionality
|
||||
type Translator interface {
|
||||
locales.Translator
|
||||
|
||||
// adds a normal translation for a particular language/locale
|
||||
// {#} is the only replacement type accepted and are ad infinitum
|
||||
// eg. one: '{0} day left' other: '{0} days left'
|
||||
Add(key interface{}, text string, override bool) error
|
||||
|
||||
// adds a cardinal plural translation for a particular language/locale
|
||||
// {0} is the only replacement type accepted and only one variable is accepted as
|
||||
// multiple cannot be used for a plural rule determination, unless it is a range;
|
||||
// see AddRange below.
|
||||
// eg. in locale 'en' one: '{0} day left' other: '{0} days left'
|
||||
AddCardinal(key interface{}, text string, rule locales.PluralRule, override bool) error
|
||||
|
||||
// adds an ordinal plural translation for a particular language/locale
|
||||
// {0} is the only replacement type accepted and only one variable is accepted as
|
||||
// multiple cannot be used for a plural rule determination, unless it is a range;
|
||||
// see AddRange below.
|
||||
// eg. in locale 'en' one: '{0}st day of spring' other: '{0}nd day of spring'
|
||||
// - 1st, 2nd, 3rd...
|
||||
AddOrdinal(key interface{}, text string, rule locales.PluralRule, override bool) error
|
||||
|
||||
// adds a range plural translation for a particular language/locale
|
||||
// {0} and {1} are the only replacement types accepted and only these are accepted.
|
||||
// eg. in locale 'nl' one: '{0}-{1} day left' other: '{0}-{1} days left'
|
||||
AddRange(key interface{}, text string, rule locales.PluralRule, override bool) error
|
||||
|
||||
// creates the translation for the locale given the 'key' and params passed in
|
||||
T(key interface{}, params ...string) (string, error)
|
||||
|
||||
// creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments
|
||||
// and param passed in
|
||||
C(key interface{}, num float64, digits uint64, param string) (string, error)
|
||||
|
||||
// creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments
|
||||
// and param passed in
|
||||
O(key interface{}, num float64, digits uint64, param string) (string, error)
|
||||
|
||||
// creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and
|
||||
// 'digit2' arguments and 'param1' and 'param2' passed in
|
||||
R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) (string, error)
|
||||
|
||||
// VerifyTranslations checks to ensures that no plural rules have been
|
||||
// missed within the translations.
|
||||
VerifyTranslations() error
|
||||
}
|
||||
|
||||
var _ Translator = new(translator)
|
||||
var _ locales.Translator = new(translator)
|
||||
|
||||
type translator struct {
|
||||
locales.Translator
|
||||
translations map[interface{}]*transText
|
||||
cardinalTanslations map[interface{}][]*transText // array index is mapped to locales.PluralRule index + the locales.PluralRuleUnknown
|
||||
ordinalTanslations map[interface{}][]*transText
|
||||
rangeTanslations map[interface{}][]*transText
|
||||
}
|
||||
|
||||
type transText struct {
|
||||
text string
|
||||
indexes []int
|
||||
}
|
||||
|
||||
func newTranslator(trans locales.Translator) Translator {
|
||||
return &translator{
|
||||
Translator: trans,
|
||||
translations: make(map[interface{}]*transText), // translation text broken up by byte index
|
||||
cardinalTanslations: make(map[interface{}][]*transText),
|
||||
ordinalTanslations: make(map[interface{}][]*transText),
|
||||
rangeTanslations: make(map[interface{}][]*transText),
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a normal translation for a particular language/locale
|
||||
// {#} is the only replacement type accepted and are ad infinitum
|
||||
// eg. one: '{0} day left' other: '{0} days left'
|
||||
func (t *translator) Add(key interface{}, text string, override bool) error {
|
||||
|
||||
if _, ok := t.translations[key]; ok && !override {
|
||||
return &ErrConflictingTranslation{locale: t.Locale(), key: key, text: text}
|
||||
}
|
||||
|
||||
lb := strings.Count(text, "{")
|
||||
rb := strings.Count(text, "}")
|
||||
|
||||
if lb != rb {
|
||||
return &ErrMissingBracket{locale: t.Locale(), key: key, text: text}
|
||||
}
|
||||
|
||||
trans := &transText{
|
||||
text: text,
|
||||
}
|
||||
|
||||
var idx int
|
||||
|
||||
for i := 0; i < lb; i++ {
|
||||
s := "{" + strconv.Itoa(i) + "}"
|
||||
idx = strings.Index(text, s)
|
||||
if idx == -1 {
|
||||
return &ErrBadParamSyntax{locale: t.Locale(), param: s, key: key, text: text}
|
||||
}
|
||||
|
||||
trans.indexes = append(trans.indexes, idx)
|
||||
trans.indexes = append(trans.indexes, idx+len(s))
|
||||
}
|
||||
|
||||
t.translations[key] = trans
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddCardinal adds a cardinal plural translation for a particular language/locale
|
||||
// {0} is the only replacement type accepted and only one variable is accepted as
|
||||
// multiple cannot be used for a plural rule determination, unless it is a range;
|
||||
// see AddRange below.
|
||||
// eg. in locale 'en' one: '{0} day left' other: '{0} days left'
|
||||
func (t *translator) AddCardinal(key interface{}, text string, rule locales.PluralRule, override bool) error {
|
||||
|
||||
var verified bool
|
||||
|
||||
// verify plural rule exists for locale
|
||||
for _, pr := range t.PluralsCardinal() {
|
||||
if pr == rule {
|
||||
verified = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !verified {
|
||||
return &ErrCardinalTranslation{text: fmt.Sprintf("error: cardinal plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
tarr, ok := t.cardinalTanslations[key]
|
||||
if ok {
|
||||
// verify not adding a conflicting record
|
||||
if len(tarr) > 0 && tarr[rule] != nil && !override {
|
||||
return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text}
|
||||
}
|
||||
|
||||
} else {
|
||||
tarr = make([]*transText, 7, 7)
|
||||
t.cardinalTanslations[key] = tarr
|
||||
}
|
||||
|
||||
trans := &transText{
|
||||
text: text,
|
||||
indexes: make([]int, 2, 2),
|
||||
}
|
||||
|
||||
tarr[rule] = trans
|
||||
|
||||
idx := strings.Index(text, paramZero)
|
||||
if idx == -1 {
|
||||
tarr[rule] = nil
|
||||
return &ErrCardinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddCardinal'. locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
trans.indexes[0] = idx
|
||||
trans.indexes[1] = idx + len(paramZero)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddOrdinal adds an ordinal plural translation for a particular language/locale
|
||||
// {0} is the only replacement type accepted and only one variable is accepted as
|
||||
// multiple cannot be used for a plural rule determination, unless it is a range;
|
||||
// see AddRange below.
|
||||
// eg. in locale 'en' one: '{0}st day of spring' other: '{0}nd day of spring' - 1st, 2nd, 3rd...
|
||||
func (t *translator) AddOrdinal(key interface{}, text string, rule locales.PluralRule, override bool) error {
|
||||
|
||||
var verified bool
|
||||
|
||||
// verify plural rule exists for locale
|
||||
for _, pr := range t.PluralsOrdinal() {
|
||||
if pr == rule {
|
||||
verified = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !verified {
|
||||
return &ErrOrdinalTranslation{text: fmt.Sprintf("error: ordinal plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
tarr, ok := t.ordinalTanslations[key]
|
||||
if ok {
|
||||
// verify not adding a conflicting record
|
||||
if len(tarr) > 0 && tarr[rule] != nil && !override {
|
||||
return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text}
|
||||
}
|
||||
|
||||
} else {
|
||||
tarr = make([]*transText, 7, 7)
|
||||
t.ordinalTanslations[key] = tarr
|
||||
}
|
||||
|
||||
trans := &transText{
|
||||
text: text,
|
||||
indexes: make([]int, 2, 2),
|
||||
}
|
||||
|
||||
tarr[rule] = trans
|
||||
|
||||
idx := strings.Index(text, paramZero)
|
||||
if idx == -1 {
|
||||
tarr[rule] = nil
|
||||
return &ErrOrdinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddOrdinal'. locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
trans.indexes[0] = idx
|
||||
trans.indexes[1] = idx + len(paramZero)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddRange adds a range plural translation for a particular language/locale
|
||||
// {0} and {1} are the only replacement types accepted and only these are accepted.
|
||||
// eg. in locale 'nl' one: '{0}-{1} day left' other: '{0}-{1} days left'
|
||||
func (t *translator) AddRange(key interface{}, text string, rule locales.PluralRule, override bool) error {
|
||||
|
||||
var verified bool
|
||||
|
||||
// verify plural rule exists for locale
|
||||
for _, pr := range t.PluralsRange() {
|
||||
if pr == rule {
|
||||
verified = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !verified {
|
||||
return &ErrRangeTranslation{text: fmt.Sprintf("error: range plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
tarr, ok := t.rangeTanslations[key]
|
||||
if ok {
|
||||
// verify not adding a conflicting record
|
||||
if len(tarr) > 0 && tarr[rule] != nil && !override {
|
||||
return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text}
|
||||
}
|
||||
|
||||
} else {
|
||||
tarr = make([]*transText, 7, 7)
|
||||
t.rangeTanslations[key] = tarr
|
||||
}
|
||||
|
||||
trans := &transText{
|
||||
text: text,
|
||||
indexes: make([]int, 4, 4),
|
||||
}
|
||||
|
||||
tarr[rule] = trans
|
||||
|
||||
idx := strings.Index(text, paramZero)
|
||||
if idx == -1 {
|
||||
tarr[rule] = nil
|
||||
return &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, are you sure you're adding a Range Translation? locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
trans.indexes[0] = idx
|
||||
trans.indexes[1] = idx + len(paramZero)
|
||||
|
||||
idx = strings.Index(text, paramOne)
|
||||
if idx == -1 {
|
||||
tarr[rule] = nil
|
||||
return &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, a Range Translation requires two parameters. locale: '%s' key: '%v' text: '%s'", paramOne, t.Locale(), key, text)}
|
||||
}
|
||||
|
||||
trans.indexes[2] = idx
|
||||
trans.indexes[3] = idx + len(paramOne)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// T creates the translation for the locale given the 'key' and params passed in
|
||||
func (t *translator) T(key interface{}, params ...string) (string, error) {
|
||||
|
||||
trans, ok := t.translations[key]
|
||||
if !ok {
|
||||
return unknownTranslation, ErrUnknowTranslation
|
||||
}
|
||||
|
||||
b := make([]byte, 0, 64)
|
||||
|
||||
var start, end, count int
|
||||
|
||||
for i := 0; i < len(trans.indexes); i++ {
|
||||
end = trans.indexes[i]
|
||||
b = append(b, trans.text[start:end]...)
|
||||
b = append(b, params[count]...)
|
||||
i++
|
||||
start = trans.indexes[i]
|
||||
count++
|
||||
}
|
||||
|
||||
b = append(b, trans.text[start:]...)
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// C creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in
|
||||
func (t *translator) C(key interface{}, num float64, digits uint64, param string) (string, error) {
|
||||
|
||||
tarr, ok := t.cardinalTanslations[key]
|
||||
if !ok {
|
||||
return unknownTranslation, ErrUnknowTranslation
|
||||
}
|
||||
|
||||
rule := t.CardinalPluralRule(num, digits)
|
||||
|
||||
trans := tarr[rule]
|
||||
|
||||
b := make([]byte, 0, 64)
|
||||
b = append(b, trans.text[:trans.indexes[0]]...)
|
||||
b = append(b, param...)
|
||||
b = append(b, trans.text[trans.indexes[1]:]...)
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// O creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in
|
||||
func (t *translator) O(key interface{}, num float64, digits uint64, param string) (string, error) {
|
||||
|
||||
tarr, ok := t.ordinalTanslations[key]
|
||||
if !ok {
|
||||
return unknownTranslation, ErrUnknowTranslation
|
||||
}
|
||||
|
||||
rule := t.OrdinalPluralRule(num, digits)
|
||||
|
||||
trans := tarr[rule]
|
||||
|
||||
b := make([]byte, 0, 64)
|
||||
b = append(b, trans.text[:trans.indexes[0]]...)
|
||||
b = append(b, param...)
|
||||
b = append(b, trans.text[trans.indexes[1]:]...)
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// R creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and 'digit2' arguments
|
||||
// and 'param1' and 'param2' passed in
|
||||
func (t *translator) R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) (string, error) {
|
||||
|
||||
tarr, ok := t.rangeTanslations[key]
|
||||
if !ok {
|
||||
return unknownTranslation, ErrUnknowTranslation
|
||||
}
|
||||
|
||||
rule := t.RangePluralRule(num1, digits1, num2, digits2)
|
||||
|
||||
trans := tarr[rule]
|
||||
|
||||
b := make([]byte, 0, 64)
|
||||
b = append(b, trans.text[:trans.indexes[0]]...)
|
||||
b = append(b, param1...)
|
||||
b = append(b, trans.text[trans.indexes[1]:trans.indexes[2]]...)
|
||||
b = append(b, param2...)
|
||||
b = append(b, trans.text[trans.indexes[3]:]...)
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// VerifyTranslations checks to ensures that no plural rules have been
|
||||
// missed within the translations.
|
||||
func (t *translator) VerifyTranslations() error {
|
||||
|
||||
for k, v := range t.cardinalTanslations {
|
||||
|
||||
for _, rule := range t.PluralsCardinal() {
|
||||
|
||||
if v[rule] == nil {
|
||||
return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "plural", rule: rule, key: k}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range t.ordinalTanslations {
|
||||
|
||||
for _, rule := range t.PluralsOrdinal() {
|
||||
|
||||
if v[rule] == nil {
|
||||
return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "ordinal", rule: rule, key: k}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range t.rangeTanslations {
|
||||
|
||||
for _, rule := range t.PluralsRange() {
|
||||
|
||||
if v[rule] == nil {
|
||||
return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "range", rule: rule, key: k}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
113
vendor/github.com/go-playground/universal-translator/universal_translator.go
generated
vendored
Normal file
113
vendor/github.com/go-playground/universal-translator/universal_translator.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
package ut
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/locales"
|
||||
)
|
||||
|
||||
// UniversalTranslator holds all locale & translation data
|
||||
type UniversalTranslator struct {
|
||||
translators map[string]Translator
|
||||
fallback Translator
|
||||
}
|
||||
|
||||
// New returns a new UniversalTranslator instance set with
|
||||
// the fallback locale and locales it should support
|
||||
func New(fallback locales.Translator, supportedLocales ...locales.Translator) *UniversalTranslator {
|
||||
|
||||
t := &UniversalTranslator{
|
||||
translators: make(map[string]Translator),
|
||||
}
|
||||
|
||||
for _, v := range supportedLocales {
|
||||
|
||||
trans := newTranslator(v)
|
||||
t.translators[strings.ToLower(trans.Locale())] = trans
|
||||
|
||||
if fallback.Locale() == v.Locale() {
|
||||
t.fallback = trans
|
||||
}
|
||||
}
|
||||
|
||||
if t.fallback == nil && fallback != nil {
|
||||
t.fallback = newTranslator(fallback)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// FindTranslator trys to find a Translator based on an array of locales
|
||||
// and returns the first one it can find, otherwise returns the
|
||||
// fallback translator.
|
||||
func (t *UniversalTranslator) FindTranslator(locales ...string) (trans Translator, found bool) {
|
||||
|
||||
for _, locale := range locales {
|
||||
|
||||
if trans, found = t.translators[strings.ToLower(locale)]; found {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return t.fallback, false
|
||||
}
|
||||
|
||||
// GetTranslator returns the specified translator for the given locale,
|
||||
// or fallback if not found
|
||||
func (t *UniversalTranslator) GetTranslator(locale string) (trans Translator, found bool) {
|
||||
|
||||
if trans, found = t.translators[strings.ToLower(locale)]; found {
|
||||
return
|
||||
}
|
||||
|
||||
return t.fallback, false
|
||||
}
|
||||
|
||||
// GetFallback returns the fallback locale
|
||||
func (t *UniversalTranslator) GetFallback() Translator {
|
||||
return t.fallback
|
||||
}
|
||||
|
||||
// AddTranslator adds the supplied translator, if it already exists the override param
|
||||
// will be checked and if false an error will be returned, otherwise the translator will be
|
||||
// overridden; if the fallback matches the supplied translator it will be overridden as well
|
||||
// NOTE: this is normally only used when translator is embedded within a library
|
||||
func (t *UniversalTranslator) AddTranslator(translator locales.Translator, override bool) error {
|
||||
|
||||
lc := strings.ToLower(translator.Locale())
|
||||
_, ok := t.translators[lc]
|
||||
if ok && !override {
|
||||
return &ErrExistingTranslator{locale: translator.Locale()}
|
||||
}
|
||||
|
||||
trans := newTranslator(translator)
|
||||
|
||||
if t.fallback.Locale() == translator.Locale() {
|
||||
|
||||
// because it's optional to have a fallback, I don't impose that limitation
|
||||
// don't know why you wouldn't but...
|
||||
if !override {
|
||||
return &ErrExistingTranslator{locale: translator.Locale()}
|
||||
}
|
||||
|
||||
t.fallback = trans
|
||||
}
|
||||
|
||||
t.translators[lc] = trans
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyTranslations runs through all locales and identifies any issues
|
||||
// eg. missing plural rules for a locale
|
||||
func (t *UniversalTranslator) VerifyTranslations() (err error) {
|
||||
|
||||
for _, trans := range t.translators {
|
||||
err = trans.VerifyTranslations()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
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
|
29
vendor/github.com/go-playground/validator/v10/.travis.yml
generated
vendored
Normal file
29
vendor/github.com/go-playground/validator/v10/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.15.2
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients: dean.karn@gmail.com
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
before_install:
|
||||
- go install github.com/mattn/goveralls
|
||||
- mkdir -p $GOPATH/src/gopkg.in
|
||||
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/validator.v9
|
||||
|
||||
# Only clone the most recent commit.
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
script:
|
||||
- go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
|
||||
|
||||
after_success: |
|
||||
[ $TRAVIS_GO_VERSION = 1.15.2 ] &&
|
||||
goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
|
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.
|
||||
|
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.21.0; \
|
||||
}
|
||||
|
||||
lint: linters-install
|
||||
$(PWD)/bin/golangci-lint run
|
||||
|
||||
test:
|
||||
$(GOCMD) test -cover -race ./...
|
||||
|
||||
bench:
|
||||
$(GOCMD) test -bench=. -benchmem ./...
|
||||
|
||||
.PHONY: test lint linters-install
|
299
vendor/github.com/go-playground/validator/v10/README.md
generated
vendored
Normal file
299
vendor/github.com/go-playground/validator/v10/README.md
generated
vendored
Normal file
@ -0,0 +1,299 @@
|
||||
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/v10
|
||||
|
||||
Then import the validator package into your own code.
|
||||
|
||||
import "github.com/go-playground/validator/v10"
|
||||
|
||||
Error Return Value
|
||||
-------
|
||||
|
||||
Validation functions return type error
|
||||
|
||||
They return type error to avoid the issue discussed in the following, where err is always != nil:
|
||||
|
||||
* http://stackoverflow.com/a/29138676/3158232
|
||||
* https://github.com/go-playground/validator/issues/134
|
||||
|
||||
Validator 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://godoc.org/github.com/go-playground/validator 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.
|
2285
vendor/github.com/go-playground/validator/v10/baked_in.go
generated
vendored
Normal file
2285
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
|
||||
}
|
162
vendor/github.com/go-playground/validator/v10/country_codes.go
generated
vendored
Normal file
162
vendor/github.com/go-playground/validator/v10/country_codes.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
package validator
|
||||
|
||||
var iso3166_1_alpha2 = map[string]bool{
|
||||
// see: https://www.iso.org/iso-3166-country-codes.html
|
||||
"AF": true, "AX": true, "AL": true, "DZ": true, "AS": true,
|
||||
"AD": true, "AO": true, "AI": true, "AQ": true, "AG": true,
|
||||
"AR": true, "AM": true, "AW": true, "AU": true, "AT": true,
|
||||
"AZ": true, "BS": true, "BH": true, "BD": true, "BB": true,
|
||||
"BY": true, "BE": true, "BZ": true, "BJ": true, "BM": true,
|
||||
"BT": true, "BO": true, "BQ": true, "BA": true, "BW": true,
|
||||
"BV": true, "BR": true, "IO": true, "BN": true, "BG": true,
|
||||
"BF": true, "BI": true, "KH": true, "CM": true, "CA": true,
|
||||
"CV": true, "KY": true, "CF": true, "TD": true, "CL": true,
|
||||
"CN": true, "CX": true, "CC": true, "CO": true, "KM": true,
|
||||
"CG": true, "CD": true, "CK": true, "CR": true, "CI": true,
|
||||
"HR": true, "CU": true, "CW": true, "CY": true, "CZ": true,
|
||||
"DK": true, "DJ": true, "DM": true, "DO": true, "EC": true,
|
||||
"EG": true, "SV": true, "GQ": true, "ER": true, "EE": true,
|
||||
"ET": true, "FK": true, "FO": true, "FJ": true, "FI": true,
|
||||
"FR": true, "GF": true, "PF": true, "TF": true, "GA": true,
|
||||
"GM": true, "GE": true, "DE": true, "GH": true, "GI": true,
|
||||
"GR": true, "GL": true, "GD": true, "GP": true, "GU": true,
|
||||
"GT": true, "GG": true, "GN": true, "GW": true, "GY": true,
|
||||
"HT": true, "HM": true, "VA": true, "HN": true, "HK": true,
|
||||
"HU": true, "IS": true, "IN": true, "ID": true, "IR": true,
|
||||
"IQ": true, "IE": true, "IM": true, "IL": true, "IT": true,
|
||||
"JM": true, "JP": true, "JE": true, "JO": true, "KZ": true,
|
||||
"KE": true, "KI": true, "KP": true, "KR": true, "KW": true,
|
||||
"KG": true, "LA": true, "LV": true, "LB": true, "LS": true,
|
||||
"LR": true, "LY": true, "LI": true, "LT": true, "LU": true,
|
||||
"MO": true, "MK": true, "MG": true, "MW": true, "MY": true,
|
||||
"MV": true, "ML": true, "MT": true, "MH": true, "MQ": true,
|
||||
"MR": true, "MU": true, "YT": true, "MX": true, "FM": true,
|
||||
"MD": true, "MC": true, "MN": true, "ME": true, "MS": true,
|
||||
"MA": true, "MZ": true, "MM": true, "NA": true, "NR": true,
|
||||
"NP": true, "NL": true, "NC": true, "NZ": true, "NI": true,
|
||||
"NE": true, "NG": true, "NU": true, "NF": true, "MP": true,
|
||||
"NO": true, "OM": true, "PK": true, "PW": true, "PS": true,
|
||||
"PA": true, "PG": true, "PY": true, "PE": true, "PH": true,
|
||||
"PN": true, "PL": true, "PT": true, "PR": true, "QA": true,
|
||||
"RE": true, "RO": true, "RU": true, "RW": true, "BL": true,
|
||||
"SH": true, "KN": true, "LC": true, "MF": true, "PM": true,
|
||||
"VC": true, "WS": true, "SM": true, "ST": true, "SA": true,
|
||||
"SN": true, "RS": true, "SC": true, "SL": true, "SG": true,
|
||||
"SX": true, "SK": true, "SI": true, "SB": true, "SO": true,
|
||||
"ZA": true, "GS": true, "SS": true, "ES": true, "LK": true,
|
||||
"SD": true, "SR": true, "SJ": true, "SZ": true, "SE": true,
|
||||
"CH": true, "SY": true, "TW": true, "TJ": true, "TZ": true,
|
||||
"TH": true, "TL": true, "TG": true, "TK": true, "TO": true,
|
||||
"TT": true, "TN": true, "TR": true, "TM": true, "TC": true,
|
||||
"TV": true, "UG": true, "UA": true, "AE": true, "GB": true,
|
||||
"US": true, "UM": true, "UY": true, "UZ": true, "VU": true,
|
||||
"VE": true, "VN": true, "VG": true, "VI": true, "WF": true,
|
||||
"EH": true, "YE": true, "ZM": true, "ZW": true,
|
||||
}
|
||||
|
||||
var iso3166_1_alpha3 = map[string]bool{
|
||||
// see: https://www.iso.org/iso-3166-country-codes.html
|
||||
"AFG": true, "ALB": true, "DZA": true, "ASM": true, "AND": true,
|
||||
"AGO": true, "AIA": true, "ATA": true, "ATG": true, "ARG": true,
|
||||
"ARM": true, "ABW": true, "AUS": true, "AUT": true, "AZE": true,
|
||||
"BHS": true, "BHR": true, "BGD": true, "BRB": true, "BLR": true,
|
||||
"BEL": true, "BLZ": true, "BEN": true, "BMU": true, "BTN": true,
|
||||
"BOL": true, "BES": true, "BIH": true, "BWA": true, "BVT": true,
|
||||
"BRA": true, "IOT": true, "BRN": true, "BGR": true, "BFA": true,
|
||||
"BDI": true, "CPV": true, "KHM": true, "CMR": true, "CAN": true,
|
||||
"CYM": true, "CAF": true, "TCD": true, "CHL": true, "CHN": true,
|
||||
"CXR": true, "CCK": true, "COL": true, "COM": true, "COD": true,
|
||||
"COG": true, "COK": true, "CRI": true, "HRV": true, "CUB": true,
|
||||
"CUW": true, "CYP": true, "CZE": true, "CIV": true, "DNK": true,
|
||||
"DJI": true, "DMA": true, "DOM": true, "ECU": true, "EGY": true,
|
||||
"SLV": true, "GNQ": true, "ERI": true, "EST": true, "SWZ": true,
|
||||
"ETH": true, "FLK": true, "FRO": true, "FJI": true, "FIN": true,
|
||||
"FRA": true, "GUF": true, "PYF": true, "ATF": true, "GAB": true,
|
||||
"GMB": true, "GEO": true, "DEU": true, "GHA": true, "GIB": true,
|
||||
"GRC": true, "GRL": true, "GRD": true, "GLP": true, "GUM": true,
|
||||
"GTM": true, "GGY": true, "GIN": true, "GNB": true, "GUY": true,
|
||||
"HTI": true, "HMD": true, "VAT": true, "HND": true, "HKG": true,
|
||||
"HUN": true, "ISL": true, "IND": true, "IDN": true, "IRN": true,
|
||||
"IRQ": true, "IRL": true, "IMN": true, "ISR": true, "ITA": true,
|
||||
"JAM": true, "JPN": true, "JEY": true, "JOR": true, "KAZ": true,
|
||||
"KEN": true, "KIR": true, "PRK": true, "KOR": true, "KWT": true,
|
||||
"KGZ": true, "LAO": true, "LVA": true, "LBN": true, "LSO": true,
|
||||
"LBR": true, "LBY": true, "LIE": true, "LTU": true, "LUX": true,
|
||||
"MAC": true, "MDG": true, "MWI": true, "MYS": true, "MDV": true,
|
||||
"MLI": true, "MLT": true, "MHL": true, "MTQ": true, "MRT": true,
|
||||
"MUS": true, "MYT": true, "MEX": true, "FSM": true, "MDA": true,
|
||||
"MCO": true, "MNG": true, "MNE": true, "MSR": true, "MAR": true,
|
||||
"MOZ": true, "MMR": true, "NAM": true, "NRU": true, "NPL": true,
|
||||
"NLD": true, "NCL": true, "NZL": true, "NIC": true, "NER": true,
|
||||
"NGA": true, "NIU": true, "NFK": true, "MKD": true, "MNP": true,
|
||||
"NOR": true, "OMN": true, "PAK": true, "PLW": true, "PSE": true,
|
||||
"PAN": true, "PNG": true, "PRY": true, "PER": true, "PHL": true,
|
||||
"PCN": true, "POL": true, "PRT": true, "PRI": true, "QAT": true,
|
||||
"ROU": true, "RUS": true, "RWA": true, "REU": true, "BLM": true,
|
||||
"SHN": true, "KNA": true, "LCA": true, "MAF": true, "SPM": true,
|
||||
"VCT": true, "WSM": true, "SMR": true, "STP": true, "SAU": true,
|
||||
"SEN": true, "SRB": true, "SYC": true, "SLE": true, "SGP": true,
|
||||
"SXM": true, "SVK": true, "SVN": true, "SLB": true, "SOM": true,
|
||||
"ZAF": true, "SGS": true, "SSD": true, "ESP": true, "LKA": true,
|
||||
"SDN": true, "SUR": true, "SJM": true, "SWE": true, "CHE": true,
|
||||
"SYR": true, "TWN": true, "TJK": true, "TZA": true, "THA": true,
|
||||
"TLS": true, "TGO": true, "TKL": true, "TON": true, "TTO": true,
|
||||
"TUN": true, "TUR": true, "TKM": true, "TCA": true, "TUV": true,
|
||||
"UGA": true, "UKR": true, "ARE": true, "GBR": true, "UMI": true,
|
||||
"USA": true, "URY": true, "UZB": true, "VUT": true, "VEN": true,
|
||||
"VNM": true, "VGB": true, "VIR": true, "WLF": true, "ESH": true,
|
||||
"YEM": true, "ZMB": true, "ZWE": true, "ALA": true,
|
||||
}
|
||||
var iso3166_1_alpha_numeric = map[int]bool{
|
||||
// see: https://www.iso.org/iso-3166-country-codes.html
|
||||
4: true, 8: true, 12: true, 16: true, 20: true,
|
||||
24: true, 660: true, 10: true, 28: true, 32: true,
|
||||
51: true, 533: true, 36: true, 40: true, 31: true,
|
||||
44: true, 48: true, 50: true, 52: true, 112: true,
|
||||
56: true, 84: true, 204: true, 60: true, 64: true,
|
||||
68: true, 535: true, 70: true, 72: true, 74: true,
|
||||
76: true, 86: true, 96: true, 100: true, 854: true,
|
||||
108: true, 132: true, 116: true, 120: true, 124: true,
|
||||
136: true, 140: true, 148: true, 152: true, 156: true,
|
||||
162: true, 166: true, 170: true, 174: true, 180: true,
|
||||
178: true, 184: true, 188: true, 191: true, 192: true,
|
||||
531: true, 196: true, 203: true, 384: true, 208: true,
|
||||
262: true, 212: true, 214: true, 218: true, 818: true,
|
||||
222: true, 226: true, 232: true, 233: true, 748: true,
|
||||
231: true, 238: true, 234: true, 242: true, 246: true,
|
||||
250: true, 254: true, 258: true, 260: true, 266: true,
|
||||
270: true, 268: true, 276: true, 288: true, 292: true,
|
||||
300: true, 304: true, 308: true, 312: true, 316: true,
|
||||
320: true, 831: true, 324: true, 624: true, 328: true,
|
||||
332: true, 334: true, 336: true, 340: true, 344: true,
|
||||
348: true, 352: true, 356: true, 360: true, 364: true,
|
||||
368: true, 372: true, 833: true, 376: true, 380: true,
|
||||
388: true, 392: true, 832: true, 400: true, 398: true,
|
||||
404: true, 296: true, 408: true, 410: true, 414: true,
|
||||
417: true, 418: true, 428: true, 422: true, 426: true,
|
||||
430: true, 434: true, 438: true, 440: true, 442: true,
|
||||
446: true, 450: true, 454: true, 458: true, 462: true,
|
||||
466: true, 470: true, 584: true, 474: true, 478: true,
|
||||
480: true, 175: true, 484: true, 583: true, 498: true,
|
||||
492: true, 496: true, 499: true, 500: true, 504: true,
|
||||
508: true, 104: true, 516: true, 520: true, 524: true,
|
||||
528: true, 540: true, 554: true, 558: true, 562: true,
|
||||
566: true, 570: true, 574: true, 807: true, 580: true,
|
||||
578: true, 512: true, 586: true, 585: true, 275: true,
|
||||
591: true, 598: true, 600: true, 604: true, 608: true,
|
||||
612: true, 616: true, 620: true, 630: true, 634: true,
|
||||
642: true, 643: true, 646: true, 638: true, 652: true,
|
||||
654: true, 659: true, 662: true, 663: true, 666: true,
|
||||
670: true, 882: true, 674: true, 678: true, 682: true,
|
||||
686: true, 688: true, 690: true, 694: true, 702: true,
|
||||
534: true, 703: true, 705: true, 90: true, 706: true,
|
||||
710: true, 239: true, 728: true, 724: true, 144: true,
|
||||
729: true, 740: true, 744: true, 752: true, 756: true,
|
||||
760: true, 158: true, 762: true, 834: true, 764: true,
|
||||
626: true, 768: true, 772: true, 776: true, 780: true,
|
||||
788: true, 792: true, 795: true, 796: true, 798: true,
|
||||
800: true, 804: true, 784: true, 826: true, 581: true,
|
||||
840: true, 858: true, 860: true, 548: true, 862: true,
|
||||
704: true, 92: true, 850: true, 876: true, 732: true,
|
||||
887: true, 894: true, 716: true, 248: true,
|
||||
}
|
1308
vendor/github.com/go-playground/validator/v10/doc.go
generated
vendored
Normal file
1308
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 {
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// returns the field's actual name from the struct, when able to determine.
|
||||
//
|
||||
// eq. "FirstName"
|
||||
// see Field for comparison
|
||||
StructField() string
|
||||
|
||||
// returns the actual field's value in case needed for creating the error
|
||||
// message
|
||||
Value() interface{}
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
119
vendor/github.com/go-playground/validator/v10/field_level.go
generated
vendored
Normal file
119
vendor/github.com/go-playground/validator/v10/field_level.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
package validator
|
||||
|
||||
import "reflect"
|
||||
|
||||
// FieldLevel contains all the information and helper functions
|
||||
// to validate a field
|
||||
type FieldLevel interface {
|
||||
// returns the top level struct, if any
|
||||
Top() reflect.Value
|
||||
|
||||
// returns the current fields parent struct, if any or
|
||||
// the comparison value if called 'VarWithValue'
|
||||
Parent() reflect.Value
|
||||
|
||||
// returns current field for validation
|
||||
Field() reflect.Value
|
||||
|
||||
// returns the field's name with the tag
|
||||
// name taking precedence over the fields actual name.
|
||||
FieldName() string
|
||||
|
||||
// returns the struct field's name
|
||||
StructFieldName() string
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
|
||||
// GetStructFieldOK 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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) {
|
||||
return v.getStructFieldOKInternal(val, namespace)
|
||||
}
|
11
vendor/github.com/go-playground/validator/v10/go.mod
generated
vendored
Normal file
11
vendor/github.com/go-playground/validator/v10/go.mod
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
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
|
||||
)
|
28
vendor/github.com/go-playground/validator/v10/go.sum
generated
vendored
Normal file
28
vendor/github.com/go-playground/validator/v10/go.sum
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
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/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/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
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 |
101
vendor/github.com/go-playground/validator/v10/regexes.go
generated
vendored
Normal file
101
vendor/github.com/go-playground/validator/v10/regexes.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
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 = `(%[A-Fa-f0-9]{2})`
|
||||
hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(>)|(<)|(")|(&)+[;]?`
|
||||
hTMLRegexString = `<[/]?([a-zA-Z]+).*?>`
|
||||
splitParamsRegexString = `'[^']*'|\S+`
|
||||
)
|
||||
|
||||
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)
|
||||
)
|
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 {
|
||||
|
||||
// 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
|
||||
|
||||
// returns the top level struct, if any
|
||||
Top() reflect.Value
|
||||
|
||||
// returns the current fields parent struct, if any
|
||||
Parent() reflect.Value
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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, parent, 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, current, current, typ, ns, structNs, ct)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
619
vendor/github.com/go-playground/validator/v10/validator_instance.go
generated
vendored
Normal file
619
vendor/github.com/go-playground/validator/v10/validator_instance.go
generated
vendored
Normal file
@ -0,0 +1,619 @@
|
||||
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"
|
||||
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:
|
||||
_ = 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
|
||||
}
|
||||
|
||||
// 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...)
|
||||
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