An experimental library for validating just about anything.
Inspired by swift-parsing, this library provides a declarative and composable way of validating any type of input into a Validated
struct.
The library exposes a Validated
type and some helpers to accumulate validation errors.
enum Validated<Valid> {
case valid(Valid)
case invalid([ValidationError])
}
A Validator
is defined by Input
associated type representing the type to be validated. A Valid
associated type representing the possibly transform validated Input
. Finally, a validate
function to validate an Input
into a Validated<Valid>
.
public protocol Validator {
associatedtype Input
associatedtype Valid
func validate(_ input: Input) -> Validated<Valid>
}
The most common way of creating a Validator
is through the various builders.
The Validate
validator, is an entry point for the ValidateBuilder
. It validates an input by running it again various Validator
s of the matching Input
and Valid
associated value. It accumulates errors.
Validate {
Predicate<String> { !$0.isEmpty }
Predicate<String> { $0 != "bad" }
}
The OneOf
validator is an entry point for the OneOfBuilder
. It validates an input by running it again various Validator
s of the matching Input
and Valid
associated value. It succeeds if one of the validators succeeds and only fails if all of them fail.
OneOf {
Predicate("a")
Predicate("b")
Predicate("c")
}
The ValidateThrough
validator is an entry point for the ValidateThroughBuilder
. It validates an input by running it again various Validator
s of the matching Input
and Valid
associated value. It pipes the Valid
value of a previous validator to the next.
enum Enum: String {
case a, b, c
}
ValidateThrough {
String?.validator()
Enum.validator()
}
The library comes with a playground that you can run to experiment with the different validators.