I'm trying to implement a generic validator in Swift. The validator simply performs some validation, i.e. email validation, and returns true or false based on whether or not the value is valid.
protocol Validator {
associatedtype Value
func validate(_ value: Value) -> Bool
}
I've also managed to get these validators implemented. As you can see, the associatedValue works like a charm.
struct EmailValidator: Validator {
func validate(_ value: String) -> Bool {
NSPredicate(format: "SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}").evaluate(with: value)
}
}
struct RequiredValidator: Validator {
func validate(_ value: String) -> Bool {
!value.isEmpty
}
}
But now I'd like to have a compound validator, that doesn't have to conform Validator, but it does need to accept any Validator where the associatedValue is the same. Below I have an example.
let compoundValidator = CompoundValidator<String>(EmailValidator(), RequiredValidator())
However, when I try to implement this idea, I run into errors such as Cannot specialize non-generic type 'Validator' or Cannot convert value of type 'Value' to expected argument type 'Validator.Value' or Protocol 'Validator' can only be used as a generic constraint because it has Self or associated type requirements depending on what I try to implement. Is there a way I can achieve this compound validator using generics?
struct CompoundValidator<Value> {
let validators: [Validator<Value>]
init(_ validators: Validator<Value>...) {
self.validators = validators
}
func validate(_ value: Value) -> Bool {
validators.reduce(into: true) { partialResult, validator in
partialResult = partialResult && validator.validate(value)
}
}
}