forked from apps/featurer
		
	Add vendor to improve building speed.
This also adds ability to be built in network-constrained environment.
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. | ||||
							
								
								
									
										170
									
								
								vendor/github.com/go-playground/locales/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								vendor/github.com/go-playground/locales/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| ## locales | ||||
| <img align="right" src="https://raw.githubusercontent.com/go-playground/locales/master/logo.png"> | ||||
| [](https://travis-ci.org/go-playground/locales) | ||||
| [](https://godoc.org/github.com/go-playground/locales) | ||||
|  | ||||
|  | ||||
| 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, v36.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. | ||||
							
								
								
									
										311
									
								
								vendor/github.com/go-playground/locales/currency/currency.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								vendor/github.com/go-playground/locales/currency/currency.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,311 @@ | ||||
| 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 | ||||
| 	MRU | ||||
| 	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 | ||||
| 	UYW | ||||
| 	UZS | ||||
| 	VEB | ||||
| 	VEF | ||||
| 	VES | ||||
| 	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 | ||||
| ) | ||||
							
								
								
									
										
											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. | ||||
							
								
								
									
										18
									
								
								vendor/github.com/go-playground/universal-translator/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/go-playground/universal-translator/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.41.1; \ | ||||
| 	} | ||||
|  | ||||
| lint: linters-install | ||||
| 	golangci-lint run | ||||
|  | ||||
| test: | ||||
| 	$(GOCMD) test -cover -race ./... | ||||
|  | ||||
| bench: | ||||
| 	$(GOCMD) test -bench=. -benchmem ./... | ||||
|  | ||||
| .PHONY: test lint linters-install | ||||
							
								
								
									
										87
									
								
								vendor/github.com/go-playground/universal-translator/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								vendor/github.com/go-playground/universal-translator/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| ## universal-translator | ||||
| <img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png"> | ||||
| [](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) | ||||
|  | ||||
|  | ||||
| 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, v36.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 ) | ||||
| - [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 within 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) | ||||
| } | ||||
							
								
								
									
										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" | ||||
| 	"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) | ||||
| 	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 = os.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 := io.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 "Zero": | ||||
| 		return locales.PluralRuleZero | ||||
| 	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) | ||||
| 		t.cardinalTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 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) | ||||
| 		t.ordinalTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 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) | ||||
| 		t.rangeTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 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 | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/go-playground/validator/v10/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/go-playground/validator/v10/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| # Compiled Object files, Static and Dynamic libs (Shared Objects) | ||||
| *.o | ||||
| *.a | ||||
| *.so | ||||
|  | ||||
| # Folders | ||||
| _obj | ||||
| _test | ||||
| bin | ||||
|  | ||||
| # Architecture specific extensions/prefixes | ||||
| *.[568vq] | ||||
| [568vq].out | ||||
|  | ||||
| *.cgo1.go | ||||
| *.cgo2.c | ||||
| _cgo_defun.c | ||||
| _cgo_gotypes.go | ||||
| _cgo_export.* | ||||
|  | ||||
| _testmain.go | ||||
|  | ||||
| *.exe | ||||
| *.test | ||||
| *.prof | ||||
| *.test | ||||
| *.out | ||||
| *.txt | ||||
| /**/*.DS_Store | ||||
| cover.html | ||||
| README.html | ||||
| .idea | ||||
							
								
								
									
										22
									
								
								vendor/github.com/go-playground/validator/v10/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/go-playground/validator/v10/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2015 Dean Karn | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
|  | ||||
							
								
								
									
										16
									
								
								vendor/github.com/go-playground/validator/v10/MAINTAINERS.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/go-playground/validator/v10/MAINTAINERS.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| ## Maintainers Guide | ||||
|  | ||||
| ### Semantic Versioning | ||||
| Semantic versioning as defined [here](https://semver.org) must be strictly adhered to. | ||||
|  | ||||
| ### External Dependencies | ||||
| Any new external dependencies MUST: | ||||
| - Have a compatible LICENSE present. | ||||
| - Be actively maintained. | ||||
| - Be approved by @go-playground/admins | ||||
|  | ||||
| ### PR Merge Requirements | ||||
| - Up-to-date branch. | ||||
| - Passing tests and linting. | ||||
| - CODEOWNERS approval. | ||||
| - Tests that cover both the Happy and Unhappy paths. | ||||
							
								
								
									
										18
									
								
								vendor/github.com/go-playground/validator/v10/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/go-playground/validator/v10/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| GOCMD=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.41.1; \ | ||||
| 	} | ||||
|  | ||||
| lint: linters-install | ||||
| 	golangci-lint run | ||||
|  | ||||
| test: | ||||
| 	$(GOCMD) test -cover -race ./... | ||||
|  | ||||
| bench: | ||||
| 	$(GOCMD) test -run=NONE -bench=. -benchmem ./... | ||||
|  | ||||
| .PHONY: test lint linters-install | ||||
							
								
								
									
										358
									
								
								vendor/github.com/go-playground/validator/v10/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										358
									
								
								vendor/github.com/go-playground/validator/v10/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,358 @@ | ||||
| Package validator | ||||
| ================= | ||||
| <img align="right" src="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 returns only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so: | ||||
|  | ||||
| ```go | ||||
| err := validate.Struct(mystruct) | ||||
| validationErrors := err.(validator.ValidationErrors) | ||||
|  ``` | ||||
|  | ||||
| Usage and documentation | ||||
| ------ | ||||
|  | ||||
| Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs. | ||||
|  | ||||
| ##### Examples: | ||||
|  | ||||
| - [Simple](https://github.com/go-playground/validator/blob/master/_examples/simple/main.go) | ||||
| - [Custom Field Types](https://github.com/go-playground/validator/blob/master/_examples/custom/main.go) | ||||
| - [Struct Level](https://github.com/go-playground/validator/blob/master/_examples/struct-level/main.go) | ||||
| - [Translations & Custom Errors](https://github.com/go-playground/validator/blob/master/_examples/translations/main.go) | ||||
| - [Gin upgrade and/or override validator](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding) | ||||
| - [wash - an example application putting it all together](https://github.com/bluesuncorp/wash) | ||||
|  | ||||
| Baked-in Validations | ||||
| ------ | ||||
|  | ||||
| ### Special Notes: | ||||
| - If new to using validator it is highly recommended to initialize it using the `WithRequiredStructEnabled` option which is opt-in to new behaviour that will become the default behaviour in v11+. See documentation for more details. | ||||
| ```go | ||||
| validate := validator.New(validator.WithRequiredStructEnabled()) | ||||
| ``` | ||||
|  | ||||
| ### Fields: | ||||
|  | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | eqcsfield | Field Equals Another Field (relative)| | ||||
| | eqfield | Field Equals Another Field | | ||||
| | fieldcontains | Check the indicated characters are present in the Field | | ||||
| | fieldexcludes | Check the indicated characters are not present in the field | | ||||
| | gtcsfield | Field Greater Than Another Relative Field | | ||||
| | gtecsfield | Field Greater Than or Equal To Another Relative Field | | ||||
| | gtefield | Field Greater Than or Equal To Another Field | | ||||
| | gtfield | Field Greater Than Another Field | | ||||
| | ltcsfield | Less Than Another Relative Field | | ||||
| | ltecsfield | Less Than or Equal To Another Relative Field | | ||||
| | ltefield | Less Than or Equal To Another Field | | ||||
| | ltfield | Less Than Another Field | | ||||
| | necsfield | Field Does Not Equal Another Field (relative) | | ||||
| | nefield | Field Does Not Equal Another Field | | ||||
|  | ||||
| ### Network: | ||||
|  | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | cidr | Classless Inter-Domain Routing CIDR | | ||||
| | cidrv4 | Classless Inter-Domain Routing CIDRv4 | | ||||
| | cidrv6 | Classless Inter-Domain Routing CIDRv6 | | ||||
| | datauri | Data URL | | ||||
| | fqdn | Full Qualified Domain Name (FQDN) | | ||||
| | hostname | Hostname RFC 952 | | ||||
| | hostname_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 | | ||||
| | http_url | HTTP 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 | | ||||
| | boolean | Boolean | | ||||
| | contains | Contains | | ||||
| | containsany | Contains Any | | ||||
| | containsrune | Contains Rune | | ||||
| | endsnotwith | Ends Not With | | ||||
| | endswith | Ends With | | ||||
| | excludes | Excludes | | ||||
| | excludesall | Excludes All | | ||||
| | excludesrune | Excludes Rune | | ||||
| | lowercase | Lowercase | | ||||
| | multibyte | Multi-Byte Characters | | ||||
| | number | Number | | ||||
| | numeric | Numeric | | ||||
| | printascii | Printable ASCII | | ||||
| | startsnotwith | Starts Not With | | ||||
| | startswith | Starts With | | ||||
| | uppercase | Uppercase | | ||||
|  | ||||
| ### Format: | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | base64 | Base64 String | | ||||
| | base64url | Base64URL String | | ||||
| | base64rawurl | Base64RawURL String | | ||||
| | bic | Business Identifier Code (ISO 9362) | | ||||
| | bcp47_language_tag | Language tag (BCP 47) | | ||||
| | btc_addr | Bitcoin Address | | ||||
| | btc_addr_bech32 | Bitcoin Bech32 Address (segwit) | | ||||
| | credit_card | Credit Card Number | | ||||
| | mongodb | MongoDB ObjectID | | ||||
| | cron | Cron | | ||||
| | spicedb | SpiceDb ObjectID/Permission/Type | | ||||
| | 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 | | ||||
| | issn | International Standard Serial Number | | ||||
| | iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) | | ||||
| | iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) | | ||||
| | iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) | | ||||
| | iso3166_2 | Country subdivision code (ISO 3166-2) | | ||||
| | iso4217 | Currency code (ISO 4217) | | ||||
| | json | JSON | | ||||
| | jwt | JSON Web Token (JWT) | | ||||
| | latitude | Latitude | | ||||
| | longitude | Longitude | | ||||
| | luhn_checksum | Luhn Algorithm Checksum (for strings and (u)int) | | ||||
| | postcode_iso3166_alpha2 | Postcode | | ||||
| | postcode_iso3166_alpha2_field | Postcode | | ||||
| | rgb | RGB String | | ||||
| | rgba | RGBA String | | ||||
| | ssn | Social Security Number SSN | | ||||
| | timezone | Timezone | | ||||
| | uuid | Universally Unique Identifier UUID | | ||||
| | uuid3 | Universally Unique Identifier UUID v3 | | ||||
| | uuid3_rfc4122 | Universally Unique Identifier UUID v3 RFC4122 | | ||||
| | uuid4 | Universally Unique Identifier UUID v4 | | ||||
| | uuid4_rfc4122 | Universally Unique Identifier UUID v4 RFC4122 | | ||||
| | uuid5 | Universally Unique Identifier UUID v5 | | ||||
| | uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 | | ||||
| | uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 | | ||||
| | md4 | MD4 hash | | ||||
| | md5 | MD5 hash | | ||||
| | sha256 | SHA256 hash | | ||||
| | sha384 | SHA384 hash | | ||||
| | sha512 | SHA512 hash | | ||||
| | ripemd128 | RIPEMD-128 hash | | ||||
| | ripemd128 | RIPEMD-160 hash | | ||||
| | tiger128 | TIGER128 hash | | ||||
| | tiger160 | TIGER160 hash | | ||||
| | tiger192 | TIGER192 hash | | ||||
| | semver | Semantic Versioning 2.0.0 | | ||||
| | ulid | Universally Unique Lexicographically Sortable Identifier ULID | | ||||
| | cve | Common Vulnerabilities and Exposures Identifier (CVE id) | | ||||
|  | ||||
| ### Comparisons: | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | eq | Equals | | ||||
| | eq_ignore_case | Equals ignoring case | | ||||
| | gt | Greater than| | ||||
| | gte | Greater than or equal | | ||||
| | lt | Less Than | | ||||
| | lte | Less Than or Equal | | ||||
| | ne | Not Equal | | ||||
| | ne_ignore_case | Not Equal ignoring case | | ||||
|  | ||||
| ### Other: | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | dir | Existing Directory | | ||||
| | dirpath | Directory Path | | ||||
| | file | Existing File | | ||||
| | filepath | File Path | | ||||
| | image | Image | | ||||
| | isdefault | Is Default | | ||||
| | len | Length | | ||||
| | max | Maximum | | ||||
| | min | Minimum | | ||||
| | oneof | One Of | | ||||
| | required | Required | | ||||
| | required_if | Required If | | ||||
| | required_unless | Required Unless | | ||||
| | required_with | Required With | | ||||
| | required_with_all | Required With All | | ||||
| | required_without | Required Without | | ||||
| | required_without_all | Required Without All | | ||||
| | excluded_if | Excluded If | | ||||
| | excluded_unless | Excluded Unless | | ||||
| | excluded_with | Excluded With | | ||||
| | excluded_with_all | Excluded With All | | ||||
| | excluded_without | Excluded Without | | ||||
| | excluded_without_all | Excluded Without All | | ||||
| | unique | Unique | | ||||
|  | ||||
| #### Aliases: | ||||
| | Tag | Description | | ||||
| | - | - | | ||||
| | iscolor | hexcolor\|rgb\|rgba\|hsl\|hsla | | ||||
| | country_code | iso3166_1_alpha2\|iso3166_1_alpha3\|iso3166_1_alpha_numeric | | ||||
|  | ||||
| Benchmarks | ||||
| ------ | ||||
| ###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64 | ||||
| ```go | ||||
| go version go1.21.0 darwin/arm64 | ||||
| goos: darwin | ||||
| goarch: arm64 | ||||
| pkg: github.com/go-playground/validator/v10 | ||||
| BenchmarkFieldSuccess-8                                         33142266                35.94 ns/op            0 B/op          0 allocs/op | ||||
| BenchmarkFieldSuccessParallel-8                                 200816191                6.568 ns/op           0 B/op          0 allocs/op | ||||
| BenchmarkFieldFailure-8                                          6779707               175.1 ns/op           200 B/op          4 allocs/op | ||||
| BenchmarkFieldFailureParallel-8                                 11044147               108.4 ns/op           200 B/op          4 allocs/op | ||||
| BenchmarkFieldArrayDiveSuccess-8                                 6054232               194.4 ns/op            97 B/op          5 allocs/op | ||||
| BenchmarkFieldArrayDiveSuccessParallel-8                        12523388                94.07 ns/op           97 B/op          5 allocs/op | ||||
| BenchmarkFieldArrayDiveFailure-8                                 3587043               334.3 ns/op           300 B/op         10 allocs/op | ||||
| BenchmarkFieldArrayDiveFailureParallel-8                         5816665               200.8 ns/op           300 B/op         10 allocs/op | ||||
| BenchmarkFieldMapDiveSuccess-8                                   2217910               540.1 ns/op           288 B/op         14 allocs/op | ||||
| BenchmarkFieldMapDiveSuccessParallel-8                           4446698               258.7 ns/op           288 B/op         14 allocs/op | ||||
| BenchmarkFieldMapDiveFailure-8                                   2392759               504.6 ns/op           376 B/op         13 allocs/op | ||||
| BenchmarkFieldMapDiveFailureParallel-8                           4244199               286.9 ns/op           376 B/op         13 allocs/op | ||||
| BenchmarkFieldMapDiveWithKeysSuccess-8                           2005857               592.1 ns/op           288 B/op         14 allocs/op | ||||
| BenchmarkFieldMapDiveWithKeysSuccessParallel-8                   4400850               296.9 ns/op           288 B/op         14 allocs/op | ||||
| BenchmarkFieldMapDiveWithKeysFailure-8                           1850227               643.8 ns/op           553 B/op         16 allocs/op | ||||
| BenchmarkFieldMapDiveWithKeysFailureParallel-8                   3293233               375.1 ns/op           553 B/op         16 allocs/op | ||||
| BenchmarkFieldCustomTypeSuccess-8                               12174412                98.25 ns/op           32 B/op          2 allocs/op | ||||
| BenchmarkFieldCustomTypeSuccessParallel-8                       34389907                35.49 ns/op           32 B/op          2 allocs/op | ||||
| BenchmarkFieldCustomTypeFailure-8                                7582524               156.6 ns/op           184 B/op          3 allocs/op | ||||
| BenchmarkFieldCustomTypeFailureParallel-8                       13019902                92.79 ns/op          184 B/op          3 allocs/op | ||||
| BenchmarkFieldOrTagSuccess-8                                     3427260               349.4 ns/op            16 B/op          1 allocs/op | ||||
| BenchmarkFieldOrTagSuccessParallel-8                            15144128                81.25 ns/op           16 B/op          1 allocs/op | ||||
| BenchmarkFieldOrTagFailure-8                                     5913546               201.9 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkFieldOrTagFailureParallel-8                             9810212               113.7 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkStructLevelValidationSuccess-8                         13456327                87.66 ns/op           16 B/op          1 allocs/op | ||||
| BenchmarkStructLevelValidationSuccessParallel-8                 41818888                27.77 ns/op           16 B/op          1 allocs/op | ||||
| BenchmarkStructLevelValidationFailure-8                          4166284               272.6 ns/op           264 B/op          7 allocs/op | ||||
| BenchmarkStructLevelValidationFailureParallel-8                  7594581               152.1 ns/op           264 B/op          7 allocs/op | ||||
| BenchmarkStructSimpleCustomTypeSuccess-8                         6508082               182.6 ns/op            32 B/op          2 allocs/op | ||||
| BenchmarkStructSimpleCustomTypeSuccessParallel-8                23078605                54.78 ns/op           32 B/op          2 allocs/op | ||||
| BenchmarkStructSimpleCustomTypeFailure-8                         3118352               381.0 ns/op           416 B/op          9 allocs/op | ||||
| BenchmarkStructSimpleCustomTypeFailureParallel-8                 5300738               224.1 ns/op           432 B/op         10 allocs/op | ||||
| BenchmarkStructFilteredSuccess-8                                 4761807               251.1 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkStructFilteredSuccessParallel-8                         8792598               128.6 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkStructFilteredFailure-8                                 5202573               232.1 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkStructFilteredFailureParallel-8                         9591267               121.4 ns/op           216 B/op          5 allocs/op | ||||
| BenchmarkStructPartialSuccess-8                                  5188512               231.6 ns/op           224 B/op          4 allocs/op | ||||
| BenchmarkStructPartialSuccessParallel-8                          9179776               123.1 ns/op           224 B/op          4 allocs/op | ||||
| BenchmarkStructPartialFailure-8                                  3071212               392.5 ns/op           440 B/op          9 allocs/op | ||||
| BenchmarkStructPartialFailureParallel-8                          5344261               223.7 ns/op           440 B/op          9 allocs/op | ||||
| BenchmarkStructExceptSuccess-8                                   3184230               375.0 ns/op           424 B/op          8 allocs/op | ||||
| BenchmarkStructExceptSuccessParallel-8                          10090130               108.9 ns/op           208 B/op          3 allocs/op | ||||
| BenchmarkStructExceptFailure-8                                   3347226               357.7 ns/op           424 B/op          8 allocs/op | ||||
| BenchmarkStructExceptFailureParallel-8                           5654923               209.5 ns/op           424 B/op          8 allocs/op | ||||
| BenchmarkStructSimpleCrossFieldSuccess-8                         5232265               229.1 ns/op            56 B/op          3 allocs/op | ||||
| BenchmarkStructSimpleCrossFieldSuccessParallel-8                17436674                64.75 ns/op           56 B/op          3 allocs/op | ||||
| BenchmarkStructSimpleCrossFieldFailure-8                         3128613               383.6 ns/op           272 B/op          8 allocs/op | ||||
| BenchmarkStructSimpleCrossFieldFailureParallel-8                 6994113               168.8 ns/op           272 B/op          8 allocs/op | ||||
| BenchmarkStructSimpleCrossStructCrossFieldSuccess-8              3506487               340.9 ns/op            64 B/op          4 allocs/op | ||||
| BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8     13431300                91.77 ns/op           64 B/op          4 allocs/op | ||||
| BenchmarkStructSimpleCrossStructCrossFieldFailure-8              2410566               500.9 ns/op           288 B/op          9 allocs/op | ||||
| BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8      6344510               188.2 ns/op           288 B/op          9 allocs/op | ||||
| BenchmarkStructSimpleSuccess-8                                   8922726               133.8 ns/op             0 B/op          0 allocs/op | ||||
| BenchmarkStructSimpleSuccessParallel-8                          55291153                23.63 ns/op            0 B/op          0 allocs/op | ||||
| BenchmarkStructSimpleFailure-8                                   3171553               378.4 ns/op           416 B/op          9 allocs/op | ||||
| BenchmarkStructSimpleFailureParallel-8                           5571692               212.0 ns/op           416 B/op          9 allocs/op | ||||
| BenchmarkStructComplexSuccess-8                                  1683750               714.5 ns/op           224 B/op          5 allocs/op | ||||
| BenchmarkStructComplexSuccessParallel-8                          4578046               257.0 ns/op           224 B/op          5 allocs/op | ||||
| BenchmarkStructComplexFailure-8                                   481585              2547 ns/op            3041 B/op         48 allocs/op | ||||
| BenchmarkStructComplexFailureParallel-8                           965764              1577 ns/op            3040 B/op         48 allocs/op | ||||
| BenchmarkOneof-8                                                17380881                68.50 ns/op            0 B/op          0 allocs/op | ||||
| BenchmarkOneofParallel-8                                         8084733               153.5 ns/op             0 B/op          0 allocs/op | ||||
| ``` | ||||
|  | ||||
| Complementary Software | ||||
| ---------------------- | ||||
|  | ||||
| Here is a list of software that complements using this library either pre or post validation. | ||||
|  | ||||
| * [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. | ||||
| * [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects | ||||
|  | ||||
| How to Contribute | ||||
| ------ | ||||
|  | ||||
| Make a pull request... | ||||
|  | ||||
| License | ||||
| ------- | ||||
| Distributed under MIT License, please see license file within the code for more details. | ||||
|  | ||||
| Maintainers | ||||
| ----------- | ||||
| This project has grown large enough that more than one person is required to properly support the community. | ||||
| If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn | ||||
							
								
								
									
										2999
									
								
								vendor/github.com/go-playground/validator/v10/baked_in.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2999
									
								
								vendor/github.com/go-playground/validator/v10/baked_in.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										332
									
								
								vendor/github.com/go-playground/validator/v10/cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								vendor/github.com/go-playground/validator/v10/cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| package validator | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| ) | ||||
|  | ||||
| type tagType uint8 | ||||
|  | ||||
| const ( | ||||
| 	typeDefault tagType = iota | ||||
| 	typeOmitEmpty | ||||
| 	typeIsDefault | ||||
| 	typeNoStructLevel | ||||
| 	typeStructOnly | ||||
| 	typeDive | ||||
| 	typeOr | ||||
| 	typeKeys | ||||
| 	typeEndKeys | ||||
| 	typeOmitNil | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	invalidValidation   = "Invalid validation tag on field '%s'" | ||||
| 	undefinedValidation = "Undefined validation function '%s' on field '%s'" | ||||
| 	keysTagNotDefined   = "'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag" | ||||
| ) | ||||
|  | ||||
| type structCache struct { | ||||
| 	lock sync.Mutex | ||||
| 	m    atomic.Value // map[reflect.Type]*cStruct | ||||
| } | ||||
|  | ||||
| func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) { | ||||
| 	c, found = sc.m.Load().(map[reflect.Type]*cStruct)[key] | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (sc *structCache) Set(key reflect.Type, value *cStruct) { | ||||
| 	m := sc.m.Load().(map[reflect.Type]*cStruct) | ||||
| 	nm := make(map[reflect.Type]*cStruct, len(m)+1) | ||||
| 	for k, v := range m { | ||||
| 		nm[k] = v | ||||
| 	} | ||||
| 	nm[key] = value | ||||
| 	sc.m.Store(nm) | ||||
| } | ||||
|  | ||||
| type tagCache struct { | ||||
| 	lock sync.Mutex | ||||
| 	m    atomic.Value // map[string]*cTag | ||||
| } | ||||
|  | ||||
| func (tc *tagCache) Get(key string) (c *cTag, found bool) { | ||||
| 	c, found = tc.m.Load().(map[string]*cTag)[key] | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (tc *tagCache) Set(key string, value *cTag) { | ||||
| 	m := tc.m.Load().(map[string]*cTag) | ||||
| 	nm := make(map[string]*cTag, len(m)+1) | ||||
| 	for k, v := range m { | ||||
| 		nm[k] = v | ||||
| 	} | ||||
| 	nm[key] = value | ||||
| 	tc.m.Store(nm) | ||||
| } | ||||
|  | ||||
| type cStruct struct { | ||||
| 	name   string | ||||
| 	fields []*cField | ||||
| 	fn     StructLevelFuncCtx | ||||
| } | ||||
|  | ||||
| type cField struct { | ||||
| 	idx        int | ||||
| 	name       string | ||||
| 	altName    string | ||||
| 	namesEqual bool | ||||
| 	cTags      *cTag | ||||
| } | ||||
|  | ||||
| type cTag struct { | ||||
| 	tag                  string | ||||
| 	aliasTag             string | ||||
| 	actualAliasTag       string | ||||
| 	param                string | ||||
| 	keys                 *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation | ||||
| 	next                 *cTag | ||||
| 	fn                   FuncCtx | ||||
| 	typeof               tagType | ||||
| 	hasTag               bool | ||||
| 	hasAlias             bool | ||||
| 	hasParam             bool // true if parameter used eg. eq= where the equal sign has been set | ||||
| 	isBlockEnd           bool // indicates the current tag represents the last validation in the block | ||||
| 	runValidationWhenNil bool | ||||
| } | ||||
|  | ||||
| func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct { | ||||
| 	v.structCache.lock.Lock() | ||||
| 	defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise! | ||||
|  | ||||
| 	typ := current.Type() | ||||
|  | ||||
| 	// could have been multiple trying to access, but once first is done this ensures struct | ||||
| 	// isn't parsed again. | ||||
| 	cs, ok := v.structCache.Get(typ) | ||||
| 	if ok { | ||||
| 		return cs | ||||
| 	} | ||||
|  | ||||
| 	cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]} | ||||
|  | ||||
| 	numFields := current.NumField() | ||||
| 	rules := v.rules[typ] | ||||
|  | ||||
| 	var ctag *cTag | ||||
| 	var fld reflect.StructField | ||||
| 	var tag string | ||||
| 	var customName string | ||||
|  | ||||
| 	for i := 0; i < numFields; i++ { | ||||
|  | ||||
| 		fld = typ.Field(i) | ||||
|  | ||||
| 		if !v.privateFieldValidation && !fld.Anonymous && len(fld.PkgPath) > 0 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if rtag, ok := rules[fld.Name]; ok { | ||||
| 			tag = rtag | ||||
| 		} else { | ||||
| 			tag = fld.Tag.Get(v.tagName) | ||||
| 		} | ||||
|  | ||||
| 		if tag == skipValidationTag { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		customName = fld.Name | ||||
|  | ||||
| 		if v.hasTagNameFunc { | ||||
| 			name := v.tagNameFunc(fld) | ||||
| 			if len(name) > 0 { | ||||
| 				customName = name | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different | ||||
| 		// and so only struct level caching can be used instead of combined with Field tag caching | ||||
|  | ||||
| 		if len(tag) > 0 { | ||||
| 			ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false) | ||||
| 		} else { | ||||
| 			// even if field doesn't have validations need cTag for traversing to potential inner/nested | ||||
| 			// elements of the field. | ||||
| 			ctag = new(cTag) | ||||
| 		} | ||||
|  | ||||
| 		cs.fields = append(cs.fields, &cField{ | ||||
| 			idx:        i, | ||||
| 			name:       fld.Name, | ||||
| 			altName:    customName, | ||||
| 			cTags:      ctag, | ||||
| 			namesEqual: fld.Name == customName, | ||||
| 		}) | ||||
| 	} | ||||
| 	v.structCache.Set(typ, cs) | ||||
| 	return cs | ||||
| } | ||||
|  | ||||
| func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias string, hasAlias bool) (firstCtag *cTag, current *cTag) { | ||||
| 	var t string | ||||
| 	noAlias := len(alias) == 0 | ||||
| 	tags := strings.Split(tag, tagSeparator) | ||||
|  | ||||
| 	for i := 0; i < len(tags); i++ { | ||||
| 		t = tags[i] | ||||
| 		if noAlias { | ||||
| 			alias = t | ||||
| 		} | ||||
|  | ||||
| 		// check map for alias and process new tags, otherwise process as usual | ||||
| 		if tagsVal, found := v.aliases[t]; found { | ||||
| 			if i == 0 { | ||||
| 				firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) | ||||
| 			} else { | ||||
| 				next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) | ||||
| 				current.next, current = next, curr | ||||
|  | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		var prevTag tagType | ||||
|  | ||||
| 		if i == 0 { | ||||
| 			current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true, typeof: typeDefault} | ||||
| 			firstCtag = current | ||||
| 		} else { | ||||
| 			prevTag = current.typeof | ||||
| 			current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} | ||||
| 			current = current.next | ||||
| 		} | ||||
|  | ||||
| 		switch t { | ||||
| 		case diveTag: | ||||
| 			current.typeof = typeDive | ||||
| 			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 omitnil: | ||||
| 			current.typeof = typeOmitNil | ||||
| 			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 | ||||
| } | ||||
							
								
								
									
										1177
									
								
								vendor/github.com/go-playground/validator/v10/country_codes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1177
									
								
								vendor/github.com/go-playground/validator/v10/country_codes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										79
									
								
								vendor/github.com/go-playground/validator/v10/currency_codes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/github.com/go-playground/validator/v10/currency_codes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| package validator | ||||
|  | ||||
| var iso4217 = map[string]bool{ | ||||
| 	"AFN": true, "EUR": true, "ALL": true, "DZD": true, "USD": true, | ||||
| 	"AOA": true, "XCD": true, "ARS": true, "AMD": true, "AWG": true, | ||||
| 	"AUD": true, "AZN": true, "BSD": true, "BHD": true, "BDT": true, | ||||
| 	"BBD": true, "BYN": true, "BZD": true, "XOF": true, "BMD": true, | ||||
| 	"INR": true, "BTN": true, "BOB": true, "BOV": true, "BAM": true, | ||||
| 	"BWP": true, "NOK": true, "BRL": true, "BND": true, "BGN": true, | ||||
| 	"BIF": true, "CVE": true, "KHR": true, "XAF": true, "CAD": true, | ||||
| 	"KYD": true, "CLP": true, "CLF": true, "CNY": true, "COP": true, | ||||
| 	"COU": true, "KMF": true, "CDF": true, "NZD": true, "CRC": true, | ||||
| 	"HRK": true, "CUP": true, "CUC": true, "ANG": true, "CZK": true, | ||||
| 	"DKK": true, "DJF": true, "DOP": true, "EGP": true, "SVC": true, | ||||
| 	"ERN": true, "SZL": true, "ETB": true, "FKP": true, "FJD": true, | ||||
| 	"XPF": true, "GMD": true, "GEL": true, "GHS": true, "GIP": true, | ||||
| 	"GTQ": true, "GBP": true, "GNF": true, "GYD": true, "HTG": true, | ||||
| 	"HNL": true, "HKD": true, "HUF": true, "ISK": true, "IDR": true, | ||||
| 	"XDR": true, "IRR": true, "IQD": true, "ILS": true, "JMD": true, | ||||
| 	"JPY": true, "JOD": true, "KZT": true, "KES": true, "KPW": true, | ||||
| 	"KRW": true, "KWD": true, "KGS": true, "LAK": true, "LBP": true, | ||||
| 	"LSL": true, "ZAR": true, "LRD": true, "LYD": true, "CHF": true, | ||||
| 	"MOP": true, "MKD": true, "MGA": true, "MWK": true, "MYR": true, | ||||
| 	"MVR": true, "MRU": true, "MUR": true, "XUA": true, "MXN": true, | ||||
| 	"MXV": true, "MDL": true, "MNT": true, "MAD": true, "MZN": true, | ||||
| 	"MMK": true, "NAD": true, "NPR": true, "NIO": true, "NGN": true, | ||||
| 	"OMR": true, "PKR": true, "PAB": true, "PGK": true, "PYG": true, | ||||
| 	"PEN": true, "PHP": true, "PLN": true, "QAR": true, "RON": true, | ||||
| 	"RUB": true, "RWF": true, "SHP": true, "WST": true, "STN": true, | ||||
| 	"SAR": true, "RSD": true, "SCR": true, "SLL": true, "SGD": true, | ||||
| 	"XSU": true, "SBD": true, "SOS": true, "SSP": true, "LKR": true, | ||||
| 	"SDG": true, "SRD": true, "SEK": true, "CHE": true, "CHW": true, | ||||
| 	"SYP": true, "TWD": true, "TJS": true, "TZS": true, "THB": true, | ||||
| 	"TOP": true, "TTD": true, "TND": true, "TRY": true, "TMT": true, | ||||
| 	"UGX": true, "UAH": true, "AED": true, "USN": true, "UYU": true, | ||||
| 	"UYI": true, "UYW": true, "UZS": true, "VUV": true, "VES": true, | ||||
| 	"VND": true, "YER": true, "ZMW": true, "ZWL": true, "XBA": true, | ||||
| 	"XBB": true, "XBC": true, "XBD": true, "XTS": true, "XXX": true, | ||||
| 	"XAU": true, "XPD": true, "XPT": true, "XAG": true, | ||||
| } | ||||
|  | ||||
| var iso4217_numeric = map[int]bool{ | ||||
| 	8: true, 12: true, 32: true, 36: true, 44: true, | ||||
| 	48: true, 50: true, 51: true, 52: true, 60: true, | ||||
| 	64: true, 68: true, 72: true, 84: true, 90: true, | ||||
| 	96: true, 104: true, 108: true, 116: true, 124: true, | ||||
| 	132: true, 136: true, 144: true, 152: true, 156: true, | ||||
| 	170: true, 174: true, 188: true, 191: true, 192: true, | ||||
| 	203: true, 208: true, 214: true, 222: true, 230: true, | ||||
| 	232: true, 238: true, 242: true, 262: true, 270: true, | ||||
| 	292: true, 320: true, 324: true, 328: true, 332: true, | ||||
| 	340: true, 344: true, 348: true, 352: true, 356: true, | ||||
| 	360: true, 364: true, 368: true, 376: true, 388: true, | ||||
| 	392: true, 398: true, 400: true, 404: true, 408: true, | ||||
| 	410: true, 414: true, 417: true, 418: true, 422: true, | ||||
| 	426: true, 430: true, 434: true, 446: true, 454: true, | ||||
| 	458: true, 462: true, 480: true, 484: true, 496: true, | ||||
| 	498: true, 504: true, 512: true, 516: true, 524: true, | ||||
| 	532: true, 533: true, 548: true, 554: true, 558: true, | ||||
| 	566: true, 578: true, 586: true, 590: true, 598: true, | ||||
| 	600: true, 604: true, 608: true, 634: true, 643: true, | ||||
| 	646: true, 654: true, 682: true, 690: true, 694: true, | ||||
| 	702: true, 704: true, 706: true, 710: true, 728: true, | ||||
| 	748: true, 752: true, 756: true, 760: true, 764: true, | ||||
| 	776: true, 780: true, 784: true, 788: true, 800: true, | ||||
| 	807: true, 818: true, 826: true, 834: true, 840: true, | ||||
| 	858: true, 860: true, 882: true, 886: true, 901: true, | ||||
| 	927: true, 928: true, 929: true, 930: true, 931: true, | ||||
| 	932: true, 933: true, 934: true, 936: true, 938: true, | ||||
| 	940: true, 941: true, 943: true, 944: true, 946: true, | ||||
| 	947: true, 948: true, 949: true, 950: true, 951: true, | ||||
| 	952: true, 953: true, 955: true, 956: true, 957: true, | ||||
| 	958: true, 959: true, 960: true, 961: true, 962: true, | ||||
| 	963: true, 964: true, 965: true, 967: true, 968: true, | ||||
| 	969: true, 970: true, 971: true, 972: true, 973: true, | ||||
| 	975: true, 976: true, 977: true, 978: true, 979: true, | ||||
| 	980: true, 981: true, 984: true, 985: true, 986: true, | ||||
| 	990: true, 994: true, 997: true, 999: true, | ||||
| } | ||||
							
								
								
									
										1483
									
								
								vendor/github.com/go-playground/validator/v10/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1483
									
								
								vendor/github.com/go-playground/validator/v10/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										276
									
								
								vendor/github.com/go-playground/validator/v10/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								vendor/github.com/go-playground/validator/v10/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,276 @@ | ||||
| package validator | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
|  | ||||
| 	ut "github.com/go-playground/universal-translator" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag" | ||||
| ) | ||||
|  | ||||
| // ValidationErrorsTranslations is the translation return type | ||||
| type ValidationErrorsTranslations map[string]string | ||||
|  | ||||
| // InvalidValidationError describes an invalid argument passed to | ||||
| // `Struct`, `StructExcept`, StructPartial` or `Field` | ||||
| type InvalidValidationError struct { | ||||
| 	Type reflect.Type | ||||
| } | ||||
|  | ||||
| // Error returns InvalidValidationError message | ||||
| func (e *InvalidValidationError) Error() string { | ||||
|  | ||||
| 	if e.Type == nil { | ||||
| 		return "validator: (nil)" | ||||
| 	} | ||||
|  | ||||
| 	return "validator: (nil " + e.Type.String() + ")" | ||||
| } | ||||
|  | ||||
| // ValidationErrors is an array of FieldError's | ||||
| // for use in custom error messages post validation. | ||||
| type ValidationErrors []FieldError | ||||
|  | ||||
| // Error is intended for use in development + debugging and not intended to be a production error message. | ||||
| // It allows ValidationErrors to subscribe to the Error interface. | ||||
| // All information to create an error message specific to your application is contained within | ||||
| // the FieldError found within the ValidationErrors array | ||||
| func (ve ValidationErrors) Error() string { | ||||
|  | ||||
| 	buff := bytes.NewBufferString("") | ||||
|  | ||||
| 	for i := 0; i < len(ve); i++ { | ||||
|  | ||||
| 		buff.WriteString(ve[i].Error()) | ||||
| 		buff.WriteString("\n") | ||||
| 	} | ||||
|  | ||||
| 	return strings.TrimSpace(buff.String()) | ||||
| } | ||||
|  | ||||
| // Translate translates all of the ValidationErrors | ||||
| func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations { | ||||
|  | ||||
| 	trans := make(ValidationErrorsTranslations) | ||||
|  | ||||
| 	var fe *fieldError | ||||
|  | ||||
| 	for i := 0; i < len(ve); i++ { | ||||
| 		fe = ve[i].(*fieldError) | ||||
|  | ||||
| 		// // in case an Anonymous struct was used, ensure that the key | ||||
| 		// // would be 'Username' instead of ".Username" | ||||
| 		// if len(fe.ns) > 0 && fe.ns[:1] == "." { | ||||
| 		// 	trans[fe.ns[1:]] = fe.Translate(ut) | ||||
| 		// 	continue | ||||
| 		// } | ||||
|  | ||||
| 		trans[fe.ns] = fe.Translate(ut) | ||||
| 	} | ||||
|  | ||||
| 	return trans | ||||
| } | ||||
|  | ||||
| // FieldError contains all functions to get error details | ||||
| type FieldError interface { | ||||
|  | ||||
| 	// Tag returns the validation tag that failed. if the | ||||
| 	// validation was an alias, this will return the | ||||
| 	// alias name and not the underlying tag that failed. | ||||
| 	// | ||||
| 	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla" | ||||
| 	// will return "iscolor" | ||||
| 	Tag() string | ||||
|  | ||||
| 	// ActualTag returns the validation tag that failed, even if an | ||||
| 	// alias the actual tag within the alias will be returned. | ||||
| 	// If an 'or' validation fails the entire or will be returned. | ||||
| 	// | ||||
| 	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla" | ||||
| 	// will return "hexcolor|rgb|rgba|hsl|hsla" | ||||
| 	ActualTag() string | ||||
|  | ||||
| 	// Namespace returns the namespace for the field error, with the tag | ||||
| 	// name taking precedence over the field's actual name. | ||||
| 	// | ||||
| 	// eg. JSON name "User.fname" | ||||
| 	// | ||||
| 	// See StructNamespace() for a version that returns actual names. | ||||
| 	// | ||||
| 	// NOTE: this field can be blank when validating a single primitive field | ||||
| 	// using validate.Field(...) as there is no way to extract it's name | ||||
| 	Namespace() string | ||||
|  | ||||
| 	// StructNamespace returns the namespace for the field error, with the field's | ||||
| 	// actual name. | ||||
| 	// | ||||
| 	// eq. "User.FirstName" see Namespace for comparison | ||||
| 	// | ||||
| 	// NOTE: this field can be blank when validating a single primitive field | ||||
| 	// using validate.Field(...) as there is no way to extract its name | ||||
| 	StructNamespace() string | ||||
|  | ||||
| 	// Field returns the fields name with the tag name taking precedence over the | ||||
| 	// field's actual name. | ||||
| 	// | ||||
| 	// eq. JSON name "fname" | ||||
| 	// see StructField for comparison | ||||
| 	Field() string | ||||
|  | ||||
| 	// StructField returns the field's actual name from the struct, when able to determine. | ||||
| 	// | ||||
| 	// eq.  "FirstName" | ||||
| 	// see Field for comparison | ||||
| 	StructField() string | ||||
|  | ||||
| 	// Value returns the actual field's value in case needed for creating the error | ||||
| 	// message | ||||
| 	Value() interface{} | ||||
|  | ||||
| 	// Param returns the param value, in string form for comparison; this will also | ||||
| 	// help with generating an error message | ||||
| 	Param() string | ||||
|  | ||||
| 	// Kind returns the Field's reflect Kind | ||||
| 	// | ||||
| 	// eg. time.Time's kind is a struct | ||||
| 	Kind() reflect.Kind | ||||
|  | ||||
| 	// Type returns the Field's reflect Type | ||||
| 	// | ||||
| 	// eg. time.Time's type is time.Time | ||||
| 	Type() reflect.Type | ||||
|  | ||||
| 	// Translate returns the FieldError's translated error | ||||
| 	// from the provided 'ut.Translator' and registered 'TranslationFunc' | ||||
| 	// | ||||
| 	// NOTE: if no registered translator can be found it returns the same as | ||||
| 	// calling fe.Error() | ||||
| 	Translate(ut ut.Translator) string | ||||
|  | ||||
| 	// Error returns the FieldError's message | ||||
| 	Error() string | ||||
| } | ||||
|  | ||||
| // compile time interface checks | ||||
| var _ FieldError = new(fieldError) | ||||
| var _ error = new(fieldError) | ||||
|  | ||||
| // fieldError contains a single field's validation error along | ||||
| // with other properties that may be needed for error message creation | ||||
| // it complies with the FieldError interface | ||||
| type fieldError struct { | ||||
| 	v              *Validate | ||||
| 	tag            string | ||||
| 	actualTag      string | ||||
| 	ns             string | ||||
| 	structNs       string | ||||
| 	fieldLen       uint8 | ||||
| 	structfieldLen uint8 | ||||
| 	value          interface{} | ||||
| 	param          string | ||||
| 	kind           reflect.Kind | ||||
| 	typ            reflect.Type | ||||
| } | ||||
|  | ||||
| // Tag returns the validation tag that failed. | ||||
| func (fe *fieldError) Tag() string { | ||||
| 	return fe.tag | ||||
| } | ||||
|  | ||||
| // ActualTag returns the validation tag that failed, even if an | ||||
| // alias the actual tag within the alias will be returned. | ||||
| func (fe *fieldError) ActualTag() string { | ||||
| 	return fe.actualTag | ||||
| } | ||||
|  | ||||
| // Namespace returns the namespace for the field error, with the tag | ||||
| // name taking precedence over the field's actual name. | ||||
| func (fe *fieldError) Namespace() string { | ||||
| 	return fe.ns | ||||
| } | ||||
|  | ||||
| // StructNamespace returns the namespace for the field error, with the field's | ||||
| // actual name. | ||||
| func (fe *fieldError) StructNamespace() string { | ||||
| 	return fe.structNs | ||||
| } | ||||
|  | ||||
| // Field returns the field's name with the tag name taking precedence over the | ||||
| // field's actual name. | ||||
| func (fe *fieldError) Field() string { | ||||
|  | ||||
| 	return fe.ns[len(fe.ns)-int(fe.fieldLen):] | ||||
| 	// // return fe.field | ||||
| 	// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):] | ||||
|  | ||||
| 	// log.Println("FLD:", fld) | ||||
|  | ||||
| 	// if len(fld) > 0 && fld[:1] == "." { | ||||
| 	// 	return fld[1:] | ||||
| 	// } | ||||
|  | ||||
| 	// return fld | ||||
| } | ||||
|  | ||||
| // StructField returns the field's actual name from the struct, when able to determine. | ||||
| func (fe *fieldError) StructField() string { | ||||
| 	// return fe.structField | ||||
| 	return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):] | ||||
| } | ||||
|  | ||||
| // Value returns the actual field's value in case needed for creating the error | ||||
| // message | ||||
| func (fe *fieldError) Value() interface{} { | ||||
| 	return fe.value | ||||
| } | ||||
|  | ||||
| // Param returns the param value, in string form for comparison; this will | ||||
| // also help with generating an error message | ||||
| func (fe *fieldError) Param() string { | ||||
| 	return fe.param | ||||
| } | ||||
|  | ||||
| // Kind returns the Field's reflect Kind | ||||
| func (fe *fieldError) Kind() reflect.Kind { | ||||
| 	return fe.kind | ||||
| } | ||||
|  | ||||
| // Type returns the Field's reflect Type | ||||
| func (fe *fieldError) Type() reflect.Type { | ||||
| 	return fe.typ | ||||
| } | ||||
|  | ||||
| // Error returns the fieldError's error message | ||||
| func (fe *fieldError) Error() string { | ||||
| 	return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag) | ||||
| } | ||||
|  | ||||
| // Translate returns the FieldError's translated error | ||||
| // from the provided 'ut.Translator' and registered 'TranslationFunc' | ||||
| // | ||||
| // NOTE: if no registered translation can be found, it returns the original | ||||
| // untranslated error message. | ||||
| func (fe *fieldError) Translate(ut ut.Translator) string { | ||||
| 	var fn TranslationFunc | ||||
|  | ||||
| 	m, ok := fe.v.transTagFunc[ut] | ||||
| 	if !ok { | ||||
| 		return fe.Error() | ||||
| 	} | ||||
|  | ||||
| 	fn, ok = m[fe.tag] | ||||
| 	if !ok { | ||||
| 		fn, ok = m[fe.actualTag] | ||||
| 		if !ok { | ||||
| 			return fe.Error() | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return fn(ut, fe) | ||||
| } | ||||
							
								
								
									
										120
									
								
								vendor/github.com/go-playground/validator/v10/field_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								vendor/github.com/go-playground/validator/v10/field_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| package validator | ||||
|  | ||||
| import "reflect" | ||||
|  | ||||
| // FieldLevel contains all the information and helper functions | ||||
| // to validate a field | ||||
| type FieldLevel interface { | ||||
|  | ||||
| 	// Top returns the top level struct, if any | ||||
| 	Top() reflect.Value | ||||
|  | ||||
| 	// Parent returns the current fields parent struct, if any or | ||||
| 	// the comparison value if called 'VarWithValue' | ||||
| 	Parent() reflect.Value | ||||
|  | ||||
| 	// Field returns current field for validation | ||||
| 	Field() reflect.Value | ||||
|  | ||||
| 	// FieldName returns the field's name with the tag | ||||
| 	// name taking precedence over the fields actual name. | ||||
| 	FieldName() string | ||||
|  | ||||
| 	// StructFieldName returns the struct field's name | ||||
| 	StructFieldName() string | ||||
|  | ||||
| 	// Param returns param for validation against current field | ||||
| 	Param() string | ||||
|  | ||||
| 	// GetTag returns the current validations tag name | ||||
| 	GetTag() string | ||||
|  | ||||
| 	// ExtractType gets the actual underlying type of field value. | ||||
| 	// It will dive into pointers, customTypes and return you the | ||||
| 	// underlying value and it's kind. | ||||
| 	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool) | ||||
|  | ||||
| 	// GetStructFieldOK traverses the parent struct to retrieve a specific field denoted by the provided namespace | ||||
| 	// in the param and returns the field, field kind and whether is was successful in retrieving | ||||
| 	// the field at all. | ||||
| 	// | ||||
| 	// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field | ||||
| 	// could not be retrieved because it didn't exist. | ||||
| 	// | ||||
| 	// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable. | ||||
| 	GetStructFieldOK() (reflect.Value, reflect.Kind, bool) | ||||
|  | ||||
| 	// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for | ||||
| 	// the field and namespace allowing more extensibility for validators. | ||||
| 	// | ||||
| 	// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable. | ||||
| 	GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) | ||||
|  | ||||
| 	// GetStructFieldOK2 traverses the parent struct to retrieve a specific field denoted by the provided namespace | ||||
| 	// in the param and returns the field, field kind, if it's a nullable type and whether is was successful in retrieving | ||||
| 	// the field at all. | ||||
| 	// | ||||
| 	// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field | ||||
| 	// could not be retrieved because it didn't exist. | ||||
| 	GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) | ||||
|  | ||||
| 	// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for | ||||
| 	// the field and namespace allowing more extensibility for validators. | ||||
| 	GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) | ||||
| } | ||||
|  | ||||
| var _ FieldLevel = new(validate) | ||||
|  | ||||
| // Field returns current field for validation | ||||
| func (v *validate) Field() reflect.Value { | ||||
| 	return v.flField | ||||
| } | ||||
|  | ||||
| // FieldName returns the field's name with the tag | ||||
| // name taking precedence over the fields actual name. | ||||
| func (v *validate) FieldName() string { | ||||
| 	return v.cf.altName | ||||
| } | ||||
|  | ||||
| // GetTag returns the current validations tag name | ||||
| func (v *validate) GetTag() string { | ||||
| 	return v.ct.tag | ||||
| } | ||||
|  | ||||
| // StructFieldName returns the struct field's name | ||||
| func (v *validate) StructFieldName() string { | ||||
| 	return v.cf.name | ||||
| } | ||||
|  | ||||
| // Param returns param for validation against current field | ||||
| func (v *validate) Param() string { | ||||
| 	return v.ct.param | ||||
| } | ||||
|  | ||||
| // GetStructFieldOK returns Param returns param for validation against current field | ||||
| // | ||||
| // Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable. | ||||
| func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) { | ||||
| 	current, kind, _, found := v.getStructFieldOKInternal(v.slflParent, v.ct.param) | ||||
| 	return current, kind, found | ||||
| } | ||||
|  | ||||
| // GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for | ||||
| // the field and namespace allowing more extensibility for validators. | ||||
| // | ||||
| // Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable. | ||||
| func (v *validate) GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) { | ||||
| 	current, kind, _, found := v.GetStructFieldOKAdvanced2(val, namespace) | ||||
| 	return current, kind, found | ||||
| } | ||||
|  | ||||
| // GetStructFieldOK2 returns Param returns param for validation against current field | ||||
| func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) { | ||||
| 	return v.getStructFieldOKInternal(v.slflParent, v.ct.param) | ||||
| } | ||||
|  | ||||
| // GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for | ||||
| // the field and namespace allowing more extensibility for validators. | ||||
| func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) { | ||||
| 	return v.getStructFieldOKInternal(val, namespace) | ||||
| } | ||||
							
								
								
									
										
											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 | 
							
								
								
									
										26
									
								
								vendor/github.com/go-playground/validator/v10/options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/go-playground/validator/v10/options.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package validator | ||||
|  | ||||
| // Option represents a configurations option to be applied to validator during initialization. | ||||
| type Option func(*Validate) | ||||
|  | ||||
| // WithRequiredStructEnabled enables required tag on non-pointer structs to be applied instead of ignored. | ||||
| // | ||||
| // This was made opt-in behaviour in order to maintain backward compatibility with the behaviour previous | ||||
| // to being able to apply struct level validations on struct fields directly. | ||||
| // | ||||
| // It is recommended you enabled this as it will be the default behaviour in v11+ | ||||
| func WithRequiredStructEnabled() Option { | ||||
| 	return func(v *Validate) { | ||||
| 		v.requiredStructEnabled = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithPrivateFieldValidation activates validation for unexported fields via the use of the `unsafe` package. | ||||
| // | ||||
| // By opting into this feature you are acknowledging that you are aware of the risks and accept any current or future | ||||
| // consequences of using this feature. | ||||
| func WithPrivateFieldValidation() Option { | ||||
| 	return func(v *Validate) { | ||||
| 		v.privateFieldValidation = true | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										173
									
								
								vendor/github.com/go-playground/validator/v10/postcode_regexes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								vendor/github.com/go-playground/validator/v10/postcode_regexes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| package validator | ||||
|  | ||||
| import "regexp" | ||||
|  | ||||
| var postCodePatternDict = map[string]string{ | ||||
| 	"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`, | ||||
| 	"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, | ||||
| 	"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, | ||||
| 	"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, | ||||
| 	"US": `^\d{5}([ \-]\d{4})?$`, | ||||
| 	"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`, | ||||
| 	"DE": `^\d{5}$`, | ||||
| 	"JP": `^\d{3}-\d{4}$`, | ||||
| 	"FR": `^\d{2}[ ]?\d{3}$`, | ||||
| 	"AU": `^\d{4}$`, | ||||
| 	"IT": `^\d{5}$`, | ||||
| 	"CH": `^\d{4}$`, | ||||
| 	"AT": `^\d{4}$`, | ||||
| 	"ES": `^\d{5}$`, | ||||
| 	"NL": `^\d{4}[ ]?[A-Z]{2}$`, | ||||
| 	"BE": `^\d{4}$`, | ||||
| 	"DK": `^\d{4}$`, | ||||
| 	"SE": `^\d{3}[ ]?\d{2}$`, | ||||
| 	"NO": `^\d{4}$`, | ||||
| 	"BR": `^\d{5}[\-]?\d{3}$`, | ||||
| 	"PT": `^\d{4}([\-]\d{3})?$`, | ||||
| 	"FI": `^\d{5}$`, | ||||
| 	"AX": `^22\d{3}$`, | ||||
| 	"KR": `^\d{3}[\-]\d{3}$`, | ||||
| 	"CN": `^\d{6}$`, | ||||
| 	"TW": `^\d{3}(\d{2})?$`, | ||||
| 	"SG": `^\d{6}$`, | ||||
| 	"DZ": `^\d{5}$`, | ||||
| 	"AD": `^AD\d{3}$`, | ||||
| 	"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`, | ||||
| 	"AM": `^(37)?\d{4}$`, | ||||
| 	"AZ": `^\d{4}$`, | ||||
| 	"BH": `^((1[0-2]|[2-9])\d{2})?$`, | ||||
| 	"BD": `^\d{4}$`, | ||||
| 	"BB": `^(BB\d{5})?$`, | ||||
| 	"BY": `^\d{6}$`, | ||||
| 	"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`, | ||||
| 	"BA": `^\d{5}$`, | ||||
| 	"IO": `^BBND 1ZZ$`, | ||||
| 	"BN": `^[A-Z]{2}[ ]?\d{4}$`, | ||||
| 	"BG": `^\d{4}$`, | ||||
| 	"KH": `^\d{5}$`, | ||||
| 	"CV": `^\d{4}$`, | ||||
| 	"CL": `^\d{7}$`, | ||||
| 	"CR": `^\d{4,5}|\d{3}-\d{4}$`, | ||||
| 	"HR": `^\d{5}$`, | ||||
| 	"CY": `^\d{4}$`, | ||||
| 	"CZ": `^\d{3}[ ]?\d{2}$`, | ||||
| 	"DO": `^\d{5}$`, | ||||
| 	"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`, | ||||
| 	"EG": `^\d{5}$`, | ||||
| 	"EE": `^\d{5}$`, | ||||
| 	"FO": `^\d{3}$`, | ||||
| 	"GE": `^\d{4}$`, | ||||
| 	"GR": `^\d{3}[ ]?\d{2}$`, | ||||
| 	"GL": `^39\d{2}$`, | ||||
| 	"GT": `^\d{5}$`, | ||||
| 	"HT": `^\d{4}$`, | ||||
| 	"HN": `^(?:\d{5})?$`, | ||||
| 	"HU": `^\d{4}$`, | ||||
| 	"IS": `^\d{3}$`, | ||||
| 	"IN": `^\d{6}$`, | ||||
| 	"ID": `^\d{5}$`, | ||||
| 	"IL": `^\d{5}$`, | ||||
| 	"JO": `^\d{5}$`, | ||||
| 	"KZ": `^\d{6}$`, | ||||
| 	"KE": `^\d{5}$`, | ||||
| 	"KW": `^\d{5}$`, | ||||
| 	"LA": `^\d{5}$`, | ||||
| 	"LV": `^\d{4}$`, | ||||
| 	"LB": `^(\d{4}([ ]?\d{4})?)?$`, | ||||
| 	"LI": `^(948[5-9])|(949[0-7])$`, | ||||
| 	"LT": `^\d{5}$`, | ||||
| 	"LU": `^\d{4}$`, | ||||
| 	"MK": `^\d{4}$`, | ||||
| 	"MY": `^\d{5}$`, | ||||
| 	"MV": `^\d{5}$`, | ||||
| 	"MT": `^[A-Z]{3}[ ]?\d{2,4}$`, | ||||
| 	"MU": `^(\d{3}[A-Z]{2}\d{3})?$`, | ||||
| 	"MX": `^\d{5}$`, | ||||
| 	"MD": `^\d{4}$`, | ||||
| 	"MC": `^980\d{2}$`, | ||||
| 	"MA": `^\d{5}$`, | ||||
| 	"NP": `^\d{5}$`, | ||||
| 	"NZ": `^\d{4}$`, | ||||
| 	"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`, | ||||
| 	"NG": `^(\d{6})?$`, | ||||
| 	"OM": `^(PC )?\d{3}$`, | ||||
| 	"PK": `^\d{5}$`, | ||||
| 	"PY": `^\d{4}$`, | ||||
| 	"PH": `^\d{4}$`, | ||||
| 	"PL": `^\d{2}-\d{3}$`, | ||||
| 	"PR": `^00[679]\d{2}([ \-]\d{4})?$`, | ||||
| 	"RO": `^\d{6}$`, | ||||
| 	"RU": `^\d{6}$`, | ||||
| 	"SM": `^4789\d$`, | ||||
| 	"SA": `^\d{5}$`, | ||||
| 	"SN": `^\d{5}$`, | ||||
| 	"SK": `^\d{3}[ ]?\d{2}$`, | ||||
| 	"SI": `^\d{4}$`, | ||||
| 	"ZA": `^\d{4}$`, | ||||
| 	"LK": `^\d{5}$`, | ||||
| 	"TJ": `^\d{6}$`, | ||||
| 	"TH": `^\d{5}$`, | ||||
| 	"TN": `^\d{4}$`, | ||||
| 	"TR": `^\d{5}$`, | ||||
| 	"TM": `^\d{6}$`, | ||||
| 	"UA": `^\d{5}$`, | ||||
| 	"UY": `^\d{5}$`, | ||||
| 	"UZ": `^\d{6}$`, | ||||
| 	"VA": `^00120$`, | ||||
| 	"VE": `^\d{4}$`, | ||||
| 	"ZM": `^\d{5}$`, | ||||
| 	"AS": `^96799$`, | ||||
| 	"CC": `^6799$`, | ||||
| 	"CK": `^\d{4}$`, | ||||
| 	"RS": `^\d{6}$`, | ||||
| 	"ME": `^8\d{4}$`, | ||||
| 	"CS": `^\d{5}$`, | ||||
| 	"YU": `^\d{5}$`, | ||||
| 	"CX": `^6798$`, | ||||
| 	"ET": `^\d{4}$`, | ||||
| 	"FK": `^FIQQ 1ZZ$`, | ||||
| 	"NF": `^2899$`, | ||||
| 	"FM": `^(9694[1-4])([ \-]\d{4})?$`, | ||||
| 	"GF": `^9[78]3\d{2}$`, | ||||
| 	"GN": `^\d{3}$`, | ||||
| 	"GP": `^9[78][01]\d{2}$`, | ||||
| 	"GS": `^SIQQ 1ZZ$`, | ||||
| 	"GU": `^969[123]\d([ \-]\d{4})?$`, | ||||
| 	"GW": `^\d{4}$`, | ||||
| 	"HM": `^\d{4}$`, | ||||
| 	"IQ": `^\d{5}$`, | ||||
| 	"KG": `^\d{6}$`, | ||||
| 	"LR": `^\d{4}$`, | ||||
| 	"LS": `^\d{3}$`, | ||||
| 	"MG": `^\d{3}$`, | ||||
| 	"MH": `^969[67]\d([ \-]\d{4})?$`, | ||||
| 	"MN": `^\d{6}$`, | ||||
| 	"MP": `^9695[012]([ \-]\d{4})?$`, | ||||
| 	"MQ": `^9[78]2\d{2}$`, | ||||
| 	"NC": `^988\d{2}$`, | ||||
| 	"NE": `^\d{4}$`, | ||||
| 	"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`, | ||||
| 	"VN": `^[0-9]{1,6}$`, | ||||
| 	"PF": `^987\d{2}$`, | ||||
| 	"PG": `^\d{3}$`, | ||||
| 	"PM": `^9[78]5\d{2}$`, | ||||
| 	"PN": `^PCRN 1ZZ$`, | ||||
| 	"PW": `^96940$`, | ||||
| 	"RE": `^9[78]4\d{2}$`, | ||||
| 	"SH": `^(ASCN|STHL) 1ZZ$`, | ||||
| 	"SJ": `^\d{4}$`, | ||||
| 	"SO": `^\d{5}$`, | ||||
| 	"SZ": `^[HLMS]\d{3}$`, | ||||
| 	"TC": `^TKCA 1ZZ$`, | ||||
| 	"WF": `^986\d{2}$`, | ||||
| 	"XK": `^\d{5}$`, | ||||
| 	"YT": `^976\d{2}$`, | ||||
| } | ||||
|  | ||||
| var postCodeRegexDict = map[string]*regexp.Regexp{} | ||||
|  | ||||
| func init() { | ||||
| 	for countryCode, pattern := range postCodePatternDict { | ||||
| 		postCodeRegexDict[countryCode] = regexp.MustCompile(pattern) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										147
									
								
								vendor/github.com/go-playground/validator/v10/regexes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								vendor/github.com/go-playground/validator/v10/regexes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| 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]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$" | ||||
| 	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}$" | ||||
| 	base32RegexString                = "^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=|[A-Z2-7]{8})$" | ||||
| 	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})$" | ||||
| 	base64RawURLRegexString          = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2,4})$" | ||||
| 	iSBN10RegexString                = "^(?:[0-9]{9}X|[0-9]{10})$" | ||||
| 	iSBN13RegexString                = "^(?:(?:97(?:8|9))[0-9]{10})$" | ||||
| 	iSSNRegexString                  = "^(?:[0-9]{4}-[0-9]{3}[0-9X])$" | ||||
| 	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}$" | ||||
| 	uLIDRegexString                  = "^(?i)[A-HJKMNP-TV-Z0-9]{26}$" | ||||
| 	md4RegexString                   = "^[0-9a-f]{32}$" | ||||
| 	md5RegexString                   = "^[0-9a-f]{32}$" | ||||
| 	sha256RegexString                = "^[0-9a-f]{64}$" | ||||
| 	sha384RegexString                = "^[0-9a-f]{96}$" | ||||
| 	sha512RegexString                = "^[0-9a-f]{128}$" | ||||
| 	ripemd128RegexString             = "^[0-9a-f]{32}$" | ||||
| 	ripemd160RegexString             = "^[0-9a-f]{40}$" | ||||
| 	tiger128RegexString              = "^[0-9a-f]{32}$" | ||||
| 	tiger160RegexString              = "^[0-9a-f]{40}$" | ||||
| 	tiger192RegexString              = "^[0-9a-f]{48}$" | ||||
| 	aSCIIRegexString                 = "^[\x00-\x7F]*$" | ||||
| 	printableASCIIRegexString        = "^[\x20-\x7E]*$" | ||||
| 	multibyteRegexString             = "[^\x00-\x7F]" | ||||
| 	dataURIRegexString               = `^data:((?:\w+\/(?:([^;]|;[^;]).)+)?)` | ||||
| 	latitudeRegexString              = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" | ||||
| 	longitudeRegexString             = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" | ||||
| 	sSNRegexString                   = `^[0-9]{3}[ -]?(0[1-9]|[1-9][0-9])[ -]?([1-9][0-9]{3}|[0-9][1-9][0-9]{2}|[0-9]{2}[1-9][0-9]|[0-9]{3}[1-9])$` | ||||
| 	hostnameRegexStringRFC952        = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`                                                                   // https://tools.ietf.org/html/rfc952 | ||||
| 	hostnameRegexStringRFC1123       = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62}){1}(\.[a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})*?$`                                 // accepts hostname starting with a digit https://tools.ietf.org/html/rfc1123 | ||||
| 	fqdnRegexStringRFC1123           = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})(\.[a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})*?(\.[a-zA-Z]{1}[a-zA-Z0-9]{0,62})\.?$` // same as hostnameRegexStringRFC1123 but must contain a non numerical TLD (possibly ending with '.') | ||||
| 	btcAddressRegexString            = `^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$`                                                                             // bitcoin address | ||||
| 	btcAddressUpperRegexStringBech32 = `^BC1[02-9AC-HJ-NP-Z]{7,76}$`                                                                                   // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32 | ||||
| 	btcAddressLowerRegexStringBech32 = `^bc1[02-9ac-hj-np-z]{7,76}$`                                                                                   // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32 | ||||
| 	ethAddressRegexString            = `^0x[0-9a-fA-F]{40}$` | ||||
| 	ethAddressUpperRegexString       = `^0x[0-9A-F]{40}$` | ||||
| 	ethAddressLowerRegexString       = `^0x[0-9a-f]{40}$` | ||||
| 	uRLEncodedRegexString            = `^(?:[^%]|%[0-9A-Fa-f]{2})*$` | ||||
| 	hTMLEncodedRegexString           = `&#[x]?([0-9a-fA-F]{2})|(>)|(<)|(")|(&)+[;]?` | ||||
| 	hTMLRegexString                  = `<[/]?([a-zA-Z]+).*?>` | ||||
| 	jWTRegexString                   = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$" | ||||
| 	splitParamsRegexString           = `'[^']*'|\S+` | ||||
| 	bicRegexString                   = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$` | ||||
| 	semverRegexString                = `^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$` // numbered capture groups https://semver.org/ | ||||
| 	dnsRegexStringRFC1035Label       = "^[a-z]([-a-z0-9]*[a-z0-9]){0,62}$" | ||||
| 	cveRegexString                   = `^CVE-(1999|2\d{3})-(0[^0]\d{2}|0\d[^0]\d{1}|0\d{2}[^0]|[1-9]{1}\d{3,})$` // CVE Format Id https://cve.mitre.org/cve/identifiers/syntaxchange.html | ||||
| 	mongodbRegexString               = "^[a-f\\d]{24}$" | ||||
| 	cronRegexString                  = `(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})` | ||||
| 	spicedbIDRegexString             = `^(([a-zA-Z0-9/_|\-=+]{1,})|\*)$` | ||||
| 	spicedbPermissionRegexString     = "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" | ||||
| 	spicedbTypeRegexString           = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" | ||||
| ) | ||||
|  | ||||
| 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) | ||||
| 	base32Regex                = regexp.MustCompile(base32RegexString) | ||||
| 	base64Regex                = regexp.MustCompile(base64RegexString) | ||||
| 	base64URLRegex             = regexp.MustCompile(base64URLRegexString) | ||||
| 	base64RawURLRegex          = regexp.MustCompile(base64RawURLRegexString) | ||||
| 	iSBN10Regex                = regexp.MustCompile(iSBN10RegexString) | ||||
| 	iSBN13Regex                = regexp.MustCompile(iSBN13RegexString) | ||||
| 	iSSNRegex                  = regexp.MustCompile(iSSNRegexString) | ||||
| 	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) | ||||
| 	uLIDRegex                  = regexp.MustCompile(uLIDRegexString) | ||||
| 	md4Regex                   = regexp.MustCompile(md4RegexString) | ||||
| 	md5Regex                   = regexp.MustCompile(md5RegexString) | ||||
| 	sha256Regex                = regexp.MustCompile(sha256RegexString) | ||||
| 	sha384Regex                = regexp.MustCompile(sha384RegexString) | ||||
| 	sha512Regex                = regexp.MustCompile(sha512RegexString) | ||||
| 	ripemd128Regex             = regexp.MustCompile(ripemd128RegexString) | ||||
| 	ripemd160Regex             = regexp.MustCompile(ripemd160RegexString) | ||||
| 	tiger128Regex              = regexp.MustCompile(tiger128RegexString) | ||||
| 	tiger160Regex              = regexp.MustCompile(tiger160RegexString) | ||||
| 	tiger192Regex              = regexp.MustCompile(tiger192RegexString) | ||||
| 	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) | ||||
| 	uRLEncodedRegex            = regexp.MustCompile(uRLEncodedRegexString) | ||||
| 	hTMLEncodedRegex           = regexp.MustCompile(hTMLEncodedRegexString) | ||||
| 	hTMLRegex                  = regexp.MustCompile(hTMLRegexString) | ||||
| 	jWTRegex                   = regexp.MustCompile(jWTRegexString) | ||||
| 	splitParamsRegex           = regexp.MustCompile(splitParamsRegexString) | ||||
| 	bicRegex                   = regexp.MustCompile(bicRegexString) | ||||
| 	semverRegex                = regexp.MustCompile(semverRegexString) | ||||
| 	dnsRegexRFC1035Label       = regexp.MustCompile(dnsRegexStringRFC1035Label) | ||||
| 	cveRegex                   = regexp.MustCompile(cveRegexString) | ||||
| 	mongodbRegex               = regexp.MustCompile(mongodbRegexString) | ||||
| 	cronRegex                  = regexp.MustCompile(cronRegexString) | ||||
| 	spicedbIDRegex             = regexp.MustCompile(spicedbIDRegexString) | ||||
| 	spicedbPermissionRegex     = regexp.MustCompile(spicedbPermissionRegexString) | ||||
| 	spicedbTypeRegex           = regexp.MustCompile(spicedbTypeRegexString) | ||||
| ) | ||||
							
								
								
									
										175
									
								
								vendor/github.com/go-playground/validator/v10/struct_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								vendor/github.com/go-playground/validator/v10/struct_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| package validator | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| // StructLevelFunc accepts all values needed for struct level validation | ||||
| type StructLevelFunc func(sl StructLevel) | ||||
|  | ||||
| // StructLevelFuncCtx accepts all values needed for struct level validation | ||||
| // but also allows passing of contextual validation information via context.Context. | ||||
| type StructLevelFuncCtx func(ctx context.Context, sl StructLevel) | ||||
|  | ||||
| // wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx | ||||
| func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx { | ||||
| 	return func(ctx context.Context, sl StructLevel) { | ||||
| 		fn(sl) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // StructLevel contains all the information and helper functions | ||||
| // to validate a struct | ||||
| type StructLevel interface { | ||||
|  | ||||
| 	// Validator returns the main validation object, in case one wants to call validations internally. | ||||
| 	// this is so you don't have to use anonymous functions to get access to the validate | ||||
| 	// instance. | ||||
| 	Validator() *Validate | ||||
|  | ||||
| 	// Top returns the top level struct, if any | ||||
| 	Top() reflect.Value | ||||
|  | ||||
| 	// Parent returns the current fields parent struct, if any | ||||
| 	Parent() reflect.Value | ||||
|  | ||||
| 	// Current returns the current struct. | ||||
| 	Current() reflect.Value | ||||
|  | ||||
| 	// ExtractType gets the actual underlying type of field value. | ||||
| 	// It will dive into pointers, customTypes and return you the | ||||
| 	// underlying value and its kind. | ||||
| 	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool) | ||||
|  | ||||
| 	// ReportError reports an error just by passing the field and tag information | ||||
| 	// | ||||
| 	// NOTES: | ||||
| 	// | ||||
| 	// fieldName and altName get appended to the existing namespace that | ||||
| 	// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending | ||||
| 	// on the nesting | ||||
| 	// | ||||
| 	// tag can be an existing validation tag or just something you make up | ||||
| 	// and process on the flip side it's up to you. | ||||
| 	ReportError(field interface{}, fieldName, structFieldName string, tag, param string) | ||||
|  | ||||
| 	// ReportValidationErrors reports an error just by passing ValidationErrors | ||||
| 	// | ||||
| 	// NOTES: | ||||
| 	// | ||||
| 	// relativeNamespace and relativeActualNamespace get appended to the | ||||
| 	// existing namespace that validator is on. | ||||
| 	// e.g. pass 'User.FirstName' or 'Users[0].FirstName' depending | ||||
| 	// on the nesting. most of the time they will be blank, unless you validate | ||||
| 	// at a level lower the 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 accurate 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 accurate 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 | ||||
							
								
								
									
										311
									
								
								vendor/github.com/go-playground/validator/v10/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								vendor/github.com/go-playground/validator/v10/util.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,311 @@ | ||||
| package validator | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"regexp" | ||||
| 	"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.ConvertibleTo(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 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 | ||||
| } | ||||
|  | ||||
| // asFloat64 returns the parameter as a float64 | ||||
| // or panics if it can't convert | ||||
| func asFloat64(param string) float64 { | ||||
| 	i, err := strconv.ParseFloat(param, 64) | ||||
| 	panicIf(err) | ||||
| 	return i | ||||
| } | ||||
|  | ||||
| // asFloat64 returns the parameter as a float64 | ||||
| // or panics if it can't convert | ||||
| func asFloat32(param string) float64 { | ||||
| 	i, err := strconv.ParseFloat(param, 32) | ||||
| 	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()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Checks if field value matches regex. If fl.Field can be cast to Stringer, it uses the Stringer interfaces | ||||
| // String() return value. Otherwise, it uses fl.Field's String() value. | ||||
| func fieldMatchesRegexByStringerValOrString(regex *regexp.Regexp, fl FieldLevel) bool { | ||||
| 	switch fl.Field().Kind() { | ||||
| 	case reflect.String: | ||||
| 		return regex.MatchString(fl.Field().String()) | ||||
| 	default: | ||||
| 		if stringer, ok := fl.Field().Interface().(fmt.Stringer); ok { | ||||
| 			return regex.MatchString(stringer.String()) | ||||
| 		} else { | ||||
| 			return regex.MatchString(fl.Field().String()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										510
									
								
								vendor/github.com/go-playground/validator/v10/validator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								vendor/github.com/go-playground/validator/v10/validator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,510 @@ | ||||
| package validator | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // per validate construct | ||||
| type validate struct { | ||||
| 	v              *Validate | ||||
| 	top            reflect.Value | ||||
| 	ns             []byte | ||||
| 	actualNs       []byte | ||||
| 	errs           ValidationErrors | ||||
| 	includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise | ||||
| 	ffn            FilterFunc | ||||
| 	slflParent     reflect.Value // StructLevel & FieldLevel | ||||
| 	slCurrent      reflect.Value // StructLevel & FieldLevel | ||||
| 	flField        reflect.Value // StructLevel & FieldLevel | ||||
| 	cf             *cField       // StructLevel & FieldLevel | ||||
| 	ct             *cTag         // StructLevel & FieldLevel | ||||
| 	misc           []byte        // misc reusable | ||||
| 	str1           string        // misc reusable | ||||
| 	str2           string        // misc reusable | ||||
| 	fldIsPointer   bool          // StructLevel & FieldLevel | ||||
| 	isPartial      bool | ||||
| 	hasExcludes    bool | ||||
| } | ||||
|  | ||||
| // parent and current will be the same the first run of validateStruct | ||||
| func (v *validate) validateStruct(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) { | ||||
|  | ||||
| 	cs, ok := v.v.structCache.Get(typ) | ||||
| 	if !ok { | ||||
| 		cs = v.v.extractStructCache(current, typ.Name()) | ||||
| 	} | ||||
|  | ||||
| 	if len(ns) == 0 && len(cs.name) != 0 { | ||||
|  | ||||
| 		ns = append(ns, cs.name...) | ||||
| 		ns = append(ns, '.') | ||||
|  | ||||
| 		structNs = append(structNs, cs.name...) | ||||
| 		structNs = append(structNs, '.') | ||||
| 	} | ||||
|  | ||||
| 	// ct is nil on top level struct, and structs as fields that have no tag info | ||||
| 	// so if nil or if not nil and the structonly tag isn't present | ||||
| 	if ct == nil || ct.typeof != typeStructOnly { | ||||
|  | ||||
| 		var f *cField | ||||
|  | ||||
| 		for i := 0; i < len(cs.fields); i++ { | ||||
|  | ||||
| 			f = cs.fields[i] | ||||
|  | ||||
| 			if v.isPartial { | ||||
|  | ||||
| 				if v.ffn != nil { | ||||
| 					// used with StructFiltered | ||||
| 					if v.ffn(append(structNs, f.name...)) { | ||||
| 						continue | ||||
| 					} | ||||
|  | ||||
| 				} else { | ||||
| 					// used with StructPartial & StructExcept | ||||
| 					_, ok = v.includeExclude[string(append(structNs, f.name...))] | ||||
|  | ||||
| 					if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) { | ||||
| 						continue | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// check if any struct level validations, after all field validations already checked. | ||||
| 	// first iteration will have no info about nostructlevel tag, and is checked prior to | ||||
| 	// calling the next iteration of validateStruct called from traverseField. | ||||
| 	if cs.fn != nil { | ||||
|  | ||||
| 		v.slflParent = parent | ||||
| 		v.slCurrent = current | ||||
| 		v.ns = ns | ||||
| 		v.actualNs = structNs | ||||
|  | ||||
| 		cs.fn(ctx, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options | ||||
| func (v *validate) traverseField(ctx context.Context, parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) { | ||||
| 	var typ reflect.Type | ||||
| 	var kind reflect.Kind | ||||
|  | ||||
| 	current, kind, v.fldIsPointer = v.extractTypeInternal(current, false) | ||||
|  | ||||
| 	var isNestedStruct bool | ||||
|  | ||||
| 	switch kind { | ||||
| 	case reflect.Ptr, reflect.Interface, reflect.Invalid: | ||||
|  | ||||
| 		if ct == nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if ct.typeof == typeOmitNil && (kind != reflect.Invalid && current.IsNil()) { | ||||
| 			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:          getValue(current), | ||||
| 						param:          ct.param, | ||||
| 						kind:           kind, | ||||
| 						typ:            current.Type(), | ||||
| 					}, | ||||
| 				) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if kind == reflect.Invalid { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 	case reflect.Struct: | ||||
| 		isNestedStruct = !current.Type().ConvertibleTo(timeType) | ||||
| 		// For backward compatibility before struct level validation tags were supported | ||||
| 		// as there were a number of projects relying on `required` not failing on non-pointer | ||||
| 		// structs. Since it's basically nonsensical to use `required` with a non-pointer struct | ||||
| 		// are explicitly skipping the required validation for it. This WILL be removed in the | ||||
| 		// next major version. | ||||
| 		if isNestedStruct && !v.v.requiredStructEnabled && ct != nil && ct.tag == requiredTag { | ||||
| 			ct = ct.next | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	typ = current.Type() | ||||
|  | ||||
| OUTER: | ||||
| 	for { | ||||
| 		if ct == nil || !ct.hasTag || (isNestedStruct && len(cf.name) == 0) { | ||||
| 			// isNestedStruct check here | ||||
| 			if isNestedStruct { | ||||
| 				// if len == 0 then validating using 'Var' or 'VarWithValue' | ||||
| 				// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... | ||||
| 				// VarWithField - this allows for validating against each field within the struct against a specific value | ||||
| 				//                pretty handy in certain situations | ||||
| 				if len(cf.name) > 0 { | ||||
| 					ns = append(append(ns, cf.altName...), '.') | ||||
| 					structNs = append(append(structNs, cf.name...), '.') | ||||
| 				} | ||||
|  | ||||
| 				v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		switch ct.typeof { | ||||
| 		case typeNoStructLevel: | ||||
| 			return | ||||
|  | ||||
| 		case typeStructOnly: | ||||
| 			if isNestedStruct { | ||||
| 				// if len == 0 then validating using 'Var' or 'VarWithValue' | ||||
| 				// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... | ||||
| 				// VarWithField - this allows for validating against each field within the struct against a specific value | ||||
| 				//                pretty handy in certain situations | ||||
| 				if len(cf.name) > 0 { | ||||
| 					ns = append(append(ns, cf.altName...), '.') | ||||
| 					structNs = append(append(structNs, cf.name...), '.') | ||||
| 				} | ||||
|  | ||||
| 				v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) | ||||
| 			} | ||||
| 			return | ||||
|  | ||||
| 		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 typeOmitNil: | ||||
| 			v.slflParent = parent | ||||
| 			v.flField = current | ||||
| 			v.cf = cf | ||||
| 			v.ct = ct | ||||
|  | ||||
| 			switch field := v.Field(); field.Kind() { | ||||
| 			case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: | ||||
| 				if field.IsNil() { | ||||
| 					return | ||||
| 				} | ||||
| 			default: | ||||
| 				if v.fldIsPointer && field.Interface() == nil { | ||||
| 					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) { | ||||
| 					if ct.isBlockEnd { | ||||
| 						ct = ct.next | ||||
| 						continue OUTER | ||||
| 					} | ||||
|  | ||||
| 					// drain rest of the 'or' values, then continue or leave | ||||
| 					for { | ||||
|  | ||||
| 						ct = ct.next | ||||
|  | ||||
| 						if ct == nil { | ||||
| 							continue OUTER | ||||
| 						} | ||||
|  | ||||
| 						if ct.typeof != typeOr { | ||||
| 							continue OUTER | ||||
| 						} | ||||
|  | ||||
| 						if ct.isBlockEnd { | ||||
| 							ct = ct.next | ||||
| 							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:          getValue(current), | ||||
| 								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:          getValue(current), | ||||
| 								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:          getValue(current), | ||||
| 						param:          ct.param, | ||||
| 						kind:           kind, | ||||
| 						typ:            typ, | ||||
| 					}, | ||||
| 				) | ||||
|  | ||||
| 				return | ||||
| 			} | ||||
| 			ct = ct.next | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| func getValue(val reflect.Value) interface{} { | ||||
| 	if val.CanInterface() { | ||||
| 		return val.Interface() | ||||
| 	} | ||||
|  | ||||
| 	if val.CanAddr() { | ||||
| 		return reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem().Interface() | ||||
| 	} | ||||
|  | ||||
| 	switch val.Kind() { | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		return val.Int() | ||||
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||||
| 		return val.Uint() | ||||
| 	case reflect.Complex64, reflect.Complex128: | ||||
| 		return val.Complex() | ||||
| 	case reflect.Float32, reflect.Float64: | ||||
| 		return val.Float() | ||||
| 	default: | ||||
| 		return val.String() | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										710
									
								
								vendor/github.com/go-playground/validator/v10/validator_instance.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										710
									
								
								vendor/github.com/go-playground/validator/v10/validator_instance.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,710 @@ | ||||
| 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" | ||||
| 	omitnil               = "omitnil" | ||||
| 	isdefault             = "isdefault" | ||||
| 	requiredWithoutAllTag = "required_without_all" | ||||
| 	requiredWithoutTag    = "required_without" | ||||
| 	requiredWithTag       = "required_with" | ||||
| 	requiredWithAllTag    = "required_with_all" | ||||
| 	requiredIfTag         = "required_if" | ||||
| 	requiredUnlessTag     = "required_unless" | ||||
| 	skipUnlessTag         = "skip_unless" | ||||
| 	excludedWithoutAllTag = "excluded_without_all" | ||||
| 	excludedWithoutTag    = "excluded_without" | ||||
| 	excludedWithTag       = "excluded_with" | ||||
| 	excludedWithAllTag    = "excluded_with_all" | ||||
| 	excludedIfTag         = "excluded_if" | ||||
| 	excludedUnlessTag     = "excluded_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{}) | ||||
|  | ||||
| 	byteSliceType = reflect.TypeOf([]byte{}) | ||||
|  | ||||
| 	defaultCField = &cField{namesEqual: true} | ||||
| ) | ||||
|  | ||||
| // FilterFunc is the type used to filter fields using | ||||
| // StructFiltered(...) function. | ||||
| // returning true results in the field being filtered/skipped 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 | ||||
| 	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 | ||||
| 	rules                  map[reflect.Type]map[string]string | ||||
| 	tagCache               *tagCache | ||||
| 	structCache            *structCache | ||||
| 	hasCustomFuncs         bool | ||||
| 	hasTagNameFunc         bool | ||||
| 	requiredStructEnabled  bool | ||||
| 	privateFieldValidation bool | ||||
| } | ||||
|  | ||||
| // New returns a new instance of 'validate' with sane defaults. | ||||
| // Validate is designed to be thread-safe and used as a singleton instance. | ||||
| // It caches information about your struct and validations, | ||||
| // in essence only parsing your validation tags once per struct type. | ||||
| // Using multiple instances neglects the benefit of caching. | ||||
| func New(options ...Option) *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, | ||||
| 			excludedIfTag, excludedUnlessTag, excludedWithTag, excludedWithAllTag, excludedWithoutTag, excludedWithoutAllTag, | ||||
| 			skipUnlessTag: | ||||
| 			_ = 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), | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, o := range options { | ||||
| 		o(v) | ||||
| 	} | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| // SetTagName allows for changing of the default tag name of 'validate' | ||||
| func (v *Validate) SetTagName(name string) { | ||||
| 	v.tagName = name | ||||
| } | ||||
|  | ||||
| // ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual | ||||
| // validation information via context.Context. | ||||
| func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} { | ||||
| 	errs := make(map[string]interface{}) | ||||
| 	for field, rule := range rules { | ||||
| 		if ruleObj, ok := rule.(map[string]interface{}); ok { | ||||
| 			if dataObj, ok := data[field].(map[string]interface{}); ok { | ||||
| 				err := v.ValidateMapCtx(ctx, dataObj, ruleObj) | ||||
| 				if len(err) > 0 { | ||||
| 					errs[field] = err | ||||
| 				} | ||||
| 			} else if dataObjs, ok := data[field].([]map[string]interface{}); ok { | ||||
| 				for _, obj := range dataObjs { | ||||
| 					err := v.ValidateMapCtx(ctx, obj, ruleObj) | ||||
| 					if len(err) > 0 { | ||||
| 						errs[field] = err | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				errs[field] = errors.New("The field: '" + field + "' is not a map to dive") | ||||
| 			} | ||||
| 		} else if ruleStr, ok := rule.(string); ok { | ||||
| 			err := v.VarCtx(ctx, data[field], ruleStr) | ||||
| 			if err != nil { | ||||
| 				errs[field] = err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return errs | ||||
| } | ||||
|  | ||||
| // ValidateMap validates map data from a map of tags | ||||
| func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} { | ||||
| 	return v.ValidateMapCtx(context.Background(), data, rules) | ||||
| } | ||||
|  | ||||
| // RegisterTagNameFunc registers a function to get alternate names for StructFields. | ||||
| // | ||||
| // eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names: | ||||
| // | ||||
| //	validate.RegisterTagNameFunc(func(fld reflect.StructField) string { | ||||
| //	    name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] | ||||
| //	    // skip if tag key says it should be ignored | ||||
| //	    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 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // RegisterStructValidationMapRules registers validate map rules. | ||||
| // Be aware that map validation rules supersede those defined on a/the struct if present. | ||||
| // | ||||
| // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation | ||||
| func (v *Validate) RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) { | ||||
| 	if v.rules == nil { | ||||
| 		v.rules = make(map[reflect.Type]map[string]string) | ||||
| 	} | ||||
|  | ||||
| 	deepCopyRules := make(map[string]string) | ||||
| 	for i, rule := range rules { | ||||
| 		deepCopyRules[i] = rule | ||||
| 	} | ||||
|  | ||||
| 	for _, t := range types { | ||||
| 		typ := reflect.TypeOf(t) | ||||
|  | ||||
| 		if typ.Kind() == reflect.Ptr { | ||||
| 			typ = typ.Elem() | ||||
| 		} | ||||
|  | ||||
| 		if typ.Kind() != reflect.Struct { | ||||
| 			continue | ||||
| 		} | ||||
| 		v.rules[typ] = deepCopyRules | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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().ConvertibleTo(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().ConvertibleTo(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 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().ConvertibleTo(timeType) { | ||||
| 		return &InvalidValidationError{Type: reflect.TypeOf(s)} | ||||
| 	} | ||||
|  | ||||
| 	// good to validate | ||||
| 	vd := v.pool.Get().(*validate) | ||||
| 	vd.top = top | ||||
| 	vd.isPartial = true | ||||
| 	vd.ffn = nil | ||||
| 	vd.hasExcludes = false | ||||
| 	vd.includeExclude = make(map[string]struct{}) | ||||
|  | ||||
| 	typ := val.Type() | ||||
| 	name := typ.Name() | ||||
|  | ||||
| 	for _, k := range fields { | ||||
|  | ||||
| 		flds := strings.Split(k, namespaceSeparator) | ||||
| 		if len(flds) > 0 { | ||||
|  | ||||
| 			vd.misc = append(vd.misc[0:0], name...) | ||||
| 			// Don't append empty name for unnamed structs | ||||
| 			if len(vd.misc) != 0 { | ||||
| 				vd.misc = append(vd.misc, '.') | ||||
| 			} | ||||
|  | ||||
| 			for _, s := range flds { | ||||
|  | ||||
| 				idx := strings.Index(s, leftBracket) | ||||
|  | ||||
| 				if idx != -1 { | ||||
| 					for idx != -1 { | ||||
| 						vd.misc = append(vd.misc, s[:idx]...) | ||||
| 						vd.includeExclude[string(vd.misc)] = struct{}{} | ||||
|  | ||||
| 						idx2 := strings.Index(s, rightBracket) | ||||
| 						idx2++ | ||||
| 						vd.misc = append(vd.misc, s[idx:idx2]...) | ||||
| 						vd.includeExclude[string(vd.misc)] = struct{}{} | ||||
| 						s = s[idx2:] | ||||
| 						idx = strings.Index(s, leftBracket) | ||||
| 					} | ||||
| 				} else { | ||||
|  | ||||
| 					vd.misc = append(vd.misc, s...) | ||||
| 					vd.includeExclude[string(vd.misc)] = struct{}{} | ||||
| 				} | ||||
|  | ||||
| 				vd.misc = append(vd.misc, '.') | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil) | ||||
|  | ||||
| 	if len(vd.errs) > 0 { | ||||
| 		err = vd.errs | ||||
| 		vd.errs = nil | ||||
| 	} | ||||
|  | ||||
| 	v.pool.Put(vd) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // StructExcept validates all fields except the ones passed in. | ||||
| // Fields may be provided in a namespaced fashion relative to the  struct provided | ||||
| // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name | ||||
| // | ||||
| // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. | ||||
| // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. | ||||
| func (v *Validate) StructExcept(s interface{}, fields ...string) error { | ||||
| 	return v.StructExceptCtx(context.Background(), s, fields...) | ||||
| } | ||||
|  | ||||
| // StructExceptCtx validates all fields except the ones passed in and allows passing of contextual | ||||
| // validation 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().ConvertibleTo(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 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