diff --git a/baked_in.go b/baked_in.go index 95f56e00..0c07cc9d 100644 --- a/baked_in.go +++ b/baked_in.go @@ -64,8 +64,9 @@ var ( // defines a common or complex set of validation(s) to simplify // adding validation to structs. bakedInAliases = map[string]string{ - "iscolor": "hexcolor|rgb|rgba|hsl|hsla", - "country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric", + "iscolor": "hexcolor|rgb|rgba|hsl|hsla", + "country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric", + "eu_country_code": "iso3166_1_alpha2_eu|iso3166_1_alpha3_eu|iso3166_1_alpha_numeric_eu", } // bakedInValidators is the default map of ValidationFunc @@ -216,8 +217,11 @@ var ( "datetime": isDatetime, "timezone": isTimeZone, "iso3166_1_alpha2": isIso3166Alpha2, + "iso3166_1_alpha2_eu": isIso3166Alpha2EU, "iso3166_1_alpha3": isIso3166Alpha3, + "iso3166_1_alpha3_eu": isIso3166Alpha3EU, "iso3166_1_alpha_numeric": isIso3166AlphaNumeric, + "iso3166_1_alpha_numeric_eu": isIso3166AlphaNumericEU, "iso3166_2": isIso31662, "iso4217": isIso4217, "iso4217_numeric": isIso4217Numeric, @@ -2762,12 +2766,24 @@ func isIso3166Alpha2(fl FieldLevel) bool { return iso3166_1_alpha2[val] } +// isIso3166Alpha2EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 European Union country code. +func isIso3166Alpha2EU(fl FieldLevel) bool { + val := fl.Field().String() + return iso3166_1_alpha2_eu[val] +} + // isIso3166Alpha3 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 country code. func isIso3166Alpha3(fl FieldLevel) bool { val := fl.Field().String() return iso3166_1_alpha3[val] } +// isIso3166Alpha3EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 European Union country code. +func isIso3166Alpha3EU(fl FieldLevel) bool { + val := fl.Field().String() + return iso3166_1_alpha3_eu[val] +} + // isIso3166AlphaNumeric is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric country code. func isIso3166AlphaNumeric(fl FieldLevel) bool { field := fl.Field() @@ -2790,6 +2806,28 @@ func isIso3166AlphaNumeric(fl FieldLevel) bool { return iso3166_1_alpha_numeric[code] } +// isIso3166AlphaNumericEU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric European Union country code. +func isIso3166AlphaNumericEU(fl FieldLevel) bool { + field := fl.Field() + + var code int + switch field.Kind() { + case reflect.String: + i, err := strconv.Atoi(field.String()) + if err != nil { + return false + } + code = i % 1000 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + code = int(field.Int() % 1000) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + code = int(field.Uint() % 1000) + default: + panic(fmt.Sprintf("Bad field type %T", field.Interface())) + } + return iso3166_1_alpha_numeric_eu[code] +} + // isIso31662 is the validation function for validating if the current field's value is a valid iso3166-2 code. func isIso31662(fl FieldLevel) bool { val := fl.Field().String() diff --git a/country_codes.go b/country_codes.go index dc672866..e507149d 100644 --- a/country_codes.go +++ b/country_codes.go @@ -180,12 +180,12 @@ var iso3166_1_alpha_numeric = map[int]bool{ } var iso3166_1_alpha_numeric_eu = map[int]bool{ - 43: true, 32: true, 359: true, 385: true, 357: true, - 420: true, 45: true, 372: true, 358: true, 33: true, - 49: true, 30: true, 36: true, 353: true, 39: true, - 371: true, 370: true, 352: true, 356: true, 31: true, - 48: true, 351: true, 40: true, 421: true, 386: true, - 34: true, 46: true, + 40: true, 56: true, 100: true, 191: true, 196: true, + 200: true, 208: true, 233: true, 246: true, 250: true, + 276: true, 300: true, 348: true, 372: true, 380: true, + 428: true, 440: true, 442: true, 470: true, 528: true, + 616: true, 620: true, 642: true, 703: true, 705: true, + 724: true, 752: true, } var iso3166_2 = map[string]bool{ diff --git a/validator_test.go b/validator_test.go index 3b6d2634..d54ab866 100644 --- a/validator_test.go +++ b/validator_test.go @@ -12482,6 +12482,33 @@ func TestIsIso3166Alpha2Validation(t *testing.T) { } } +func TestIsIso3166Alpha2EUValidation(t *testing.T) { + tests := []struct { + value string `validate:"iso3166_1_alpha2_eu"` + expected bool + }{ + {"SE", true}, + {"UK", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.value, "iso3166_1_alpha2_eu") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha2_eu failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha2_eu failed Error: %s", i, errs) + } + } + } +} + func TestIsIso31662Validation(t *testing.T) { tests := []struct { value string `validate:"iso3166_2"` @@ -12538,6 +12565,34 @@ func TestIsIso3166Alpha3Validation(t *testing.T) { } } +func TestIsIso3166Alpha3EUValidation(t *testing.T) { + tests := []struct { + value string `validate:"iso3166_1_alpha3_eu"` + expected bool + }{ + {"POL", true}, + {"SWE", true}, + {"UNK", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.value, "iso3166_1_alpha3_eu") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha3_eu failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha3_eu failed Error: %s", i, errs) + } + } + } +} + func TestIsIso3166AlphaNumericValidation(t *testing.T) { tests := []struct { value interface{} @@ -12573,6 +12628,39 @@ func TestIsIso3166AlphaNumericValidation(t *testing.T) { }, "Bad field type []string") } +func TestIsIso3166AlphaNumericEUValidation(t *testing.T) { + tests := []struct { + value interface{} + expected bool + }{ + {752, true}, //Sweden + {"752", true}, + {826, false}, // UK + {"826", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.value, "iso3166_1_alpha_numeric_eu") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha_numeric_eu failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d iso3166_1_alpha_numeric_eu failed Error: %s", i, errs) + } + } + } + + PanicMatches(t, func() { + _ = validate.Var([]string{"1"}, "iso3166_1_alpha_numeric_eu") + }, "Bad field type []string") +} + func TestCountryCodeValidation(t *testing.T) { tests := []struct { value interface{} @@ -12606,6 +12694,39 @@ func TestCountryCodeValidation(t *testing.T) { } } +func TestEUCountryCodeValidation(t *testing.T) { + tests := []struct { + value interface{} + expected bool + }{ + {724, true}, + {0, false}, + {1, false}, + {"POL", true}, + {"NO", false}, + {"724", true}, + {"1", false}, + {"0", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.value, "eu_country_code") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d eu_country_code failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d eu_country_code failed Error: %s", i, errs) + } + } + } +} + func TestIsIso4217Validation(t *testing.T) { tests := []struct { value string `validate:"iso4217"`