diff --git a/Sources/Vapor/Validation/Validators/Pattern.swift b/Sources/Vapor/Validation/Validators/Pattern.swift new file mode 100644 index 0000000000..d5255033b4 --- /dev/null +++ b/Sources/Vapor/Validation/Validators/Pattern.swift @@ -0,0 +1,37 @@ +extension Validator where T == String { + /// Validates whether a `String` matches a RegularExpression pattern + public static func pattern(_ pattern: String) -> Validator { + .init { + guard + let range = $0.range(of: pattern, options: [.regularExpression]), + range.lowerBound == $0.startIndex && range.upperBound == $0.endIndex + else { + return ValidatorResults.Pattern(isValidPattern: false, pattern: pattern) + } + return ValidatorResults.Pattern(isValidPattern: true, pattern: pattern) + } + } +} + +extension ValidatorResults { + /// `ValidatorResult` of a validator that validates whether a `String`matches a RegularExpression pattern + public struct Pattern { + public let isValidPattern: Bool + public let pattern: String + } +} + +extension ValidatorResults.Pattern: ValidatorResult { + public var isFailure: Bool { + /// The input is valid for the pattern + !self.isValidPattern + } + + public var successDescription: String? { + "is a valid pattern" + } + + public var failureDescription: String? { + "is not a valid pattern \(self.pattern)" + } +} diff --git a/Tests/VaporTests/ValidationTests.swift b/Tests/VaporTests/ValidationTests.swift index 97b44d15a1..4285ae6b95 100644 --- a/Tests/VaporTests/ValidationTests.swift +++ b/Tests/VaporTests/ValidationTests.swift @@ -542,6 +542,11 @@ class ValidationTests: XCTestCase { assert(true, fails: !.valid, "is valid") assert("123", fails: !.valid, "is valid") } + + func testPattern() { + assert("this are not numbers", fails: .pattern("^[0-9]*$"), "is not a valid pattern ^[0-9]*$") + assert("12345", passes: .pattern("^[0-9]*$")) + } func testPreexistingValidatorResultIsIncluded() throws { struct CustomValidatorResult: ValidatorResult {