diff --git a/baked_in.go b/baked_in.go index 5fa0e22..0fae541 100644 --- a/baked_in.go +++ b/baked_in.go @@ -5,7 +5,6 @@ import ( "context" "crypto/sha256" "fmt" - urn "github.com/leodido/go-urn" "net" "net/url" "os" @@ -15,6 +14,8 @@ import ( "sync" "time" "unicode/utf8" + + urn "github.com/leodido/go-urn" ) // Func accepts a FieldLevel interface for all validation needs. The return @@ -121,6 +122,10 @@ var ( "uuid3": isUUID3, "uuid4": isUUID4, "uuid5": isUUID5, + "uuid_rfc4122": isUUIDRFC4122, + "uuid3_rfc4122": isUUID3RFC4122, + "uuid4_rfc4122": isUUID4RFC4122, + "uuid5_rfc4122": isUUID5RFC4122, "ascii": isASCII, "printascii": isPrintableASCII, "multibyte": hasMultiByteCharacter, @@ -370,6 +375,26 @@ func isUUID(fl FieldLevel) bool { return uUIDRegex.MatchString(fl.Field().String()) } +// IsUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID. +func isUUID5RFC4122(fl FieldLevel) bool { + return uUID5RFC4122Regex.MatchString(fl.Field().String()) +} + +// IsUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID. +func isUUID4RFC4122(fl FieldLevel) bool { + return uUID4RFC4122Regex.MatchString(fl.Field().String()) +} + +// IsUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID. +func isUUID3RFC4122(fl FieldLevel) bool { + return uUID3RFC4122Regex.MatchString(fl.Field().String()) +} + +// IsUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version. +func isUUIDRFC4122(fl FieldLevel) bool { + return uUIDRFC4122Regex.MatchString(fl.Field().String()) +} + // IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN. func isISBN(fl FieldLevel) bool { return isISBN10(fl) || isISBN13(fl) diff --git a/regexes.go b/regexes.go index 07a8705..3f79c61 100644 --- a/regexes.go +++ b/regexes.go @@ -24,6 +24,10 @@ const ( uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" uUIDRegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + uUID3RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-3[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" + uUID4RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + uUID5RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + uUIDRFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" aSCIIRegexString = "^[\x00-\x7F]*$" printableASCIIRegexString = "^[\x20-\x7E]*$" multibyteRegexString = "[^\x00-\x7F]" @@ -66,6 +70,10 @@ var ( uUID4Regex = regexp.MustCompile(uUID4RegexString) uUID5Regex = regexp.MustCompile(uUID5RegexString) uUIDRegex = regexp.MustCompile(uUIDRegexString) + uUID3RFC4122Regex = regexp.MustCompile(uUID3RFC4122RegexString) + uUID4RFC4122Regex = regexp.MustCompile(uUID4RFC4122RegexString) + uUID5RFC4122Regex = regexp.MustCompile(uUID5RFC4122RegexString) + uUIDRFC4122Regex = regexp.MustCompile(uUIDRFC4122RegexString) aSCIIRegex = regexp.MustCompile(aSCIIRegexString) printableASCIIRegex = regexp.MustCompile(printableASCIIRegexString) multibyteRegex = regexp.MustCompile(multibyteRegexString) diff --git a/validator_test.go b/validator_test.go index 06cb617..5534aa5 100644 --- a/validator_test.go +++ b/validator_test.go @@ -3714,6 +3714,152 @@ func TestUUIDValidation(t *testing.T) { } } +func TestUUID5RFC4122Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + + {"", false}, + {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"9c858901-8a57-4791-81Fe-4c455b099bc9", false}, + {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"987Fbc97-4bed-5078-af07-9141ba07c9f3", true}, + {"987Fbc97-4bed-5078-9f07-9141ba07c9f3", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "uuid5_rfc4122") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "uuid5_rfc4122" { + t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) + } + } + } + } +} + +func TestUUID4RFC4122Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, + {"a987fbc9-4bed-5078-af07-9141ba07c9F3", false}, + {"934859", false}, + {"57b73598-8764-4ad0-a76A-679bb6640eb1", true}, + {"625e63f3-58f5-40b7-83a1-a72ad31acFfb", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "uuid4_rfc4122") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "uuid4_rfc4122" { + t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) + } + } + } + } +} + +func TestUUID3RFC4122Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"412452646", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, + {"a987fbc9-4bed-4078-8f07-9141ba07c9F3", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9F3", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "uuid3_rfc4122") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "uuid3_rfc4122" { + t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) + } + } + } + } +} + +func TestUUIDRFC4122Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, + {"a987Fbc94bed3078cf079141ba07c9f3", false}, + {"934859", false}, + {"987fbc9-4bed-3078-cf07a-9141ba07c9F3", false}, + {"aaaaaaaa-1111-1111-aaaG-111111111111", false}, + {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", true}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "uuid_rfc4122") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "uuid_rfc4122" { + t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) + } + } + } + } +} + func TestISBNValidation(t *testing.T) { tests := []struct { param string