TypeConstraint
public struct TypeConstraint<T, E> : Constraint where E : Error
A Constraint
that allows to evaluate complex data types.
struct RegistrationData {
enum Error: Swift.Error {
case username
case password(Password)
case email
case underAge
}
enum Password {
case missingUppercase
case missingLowercase
case missingDigits
case missingSpecialChars
case tooShort
}
var username: String
var password: String
var email: String
var age: Int
}
var constraint = TypeConstraint<RegistrationData, RegistrationData.Error> {
KeyPathConstraint(\.username) {
BlockConstraint {
$0.count >= 5
} errorBuilder: {
.username
}
}
KeyPathConstraint(\.password) {
GroupConstraint(.all) {
PredicateConstraint {
.characterSet(.lowercaseLetters, mode: .inclusive)
} errorBuilder: {
.password(.missingLowercase)
}
PredicateConstraint{
.characterSet(.uppercaseLetters, mode: .inclusive)
} errorBuilder: {
.password(.missingUppercase)
}
PredicateConstraint {
.characterSet(.decimalDigits, mode: .inclusive)
} errorBuilder: {
.password(.missingDigits)
}
PredicateConstraint {
.characterSet(CharacterSet(charactersIn: "!?@#$%^&*()|\\/<>,.~`_+-="), mode: .inclusive)
} errorBuilder: {
.password(.missingSpecialChars)
}
PredicateConstraint {
.length(min: 8)
} errorBuilder: {
.password(.tooShort)
}
}
}
KeyPathConstraint(\.email) {
PredicateConstraint(.email, error: .email)
}
KeyPathConstraint(\.age) {
PredicateConstraint(.range(min: 14), error: .underAge)
}
}
let user = RegistrationData(username: "nsagora", password: "p@ssW0rd", email: "hello@nsagora.com", age: 21)
constraint.evaluate(with: user)
-
Declaration
Swift
public typealias InputType = T
-
Declaration
Swift
public typealias ErrorType = E
-
Create a new
TypeConstraint
instance.struct RegistrationData { enum Error: Swift.Error { case username case password(Password) case email case underAge } enum Password { case missingUppercase case missingLowercase case missingDigits case missingSpecialChars case tooShort } var username: String var password: String var email: String var age: Int }
var constraint = TypeConstraint<RegistrationData, RegistrationData.Error>() constraint.set(for: \.username) { BlockConstraint { $0.count >= 5 } errorBuilder: { .username } } constraint.set(for: \.password) { GroupConstraint(.all, constraints: PredicateConstraint { .characterSet(.lowercaseLetters, mode: .inclusive) } errorBuilder: { .password(.missingLowercase) }, PredicateConstraint{ .characterSet(.uppercaseLetters, mode: .inclusive) } errorBuilder: { .password(.missingUppercase) }, PredicateConstraint { .characterSet(.decimalDigits, mode: .inclusive) } errorBuilder: { .password(.missingDigits) }, PredicateConstraint { .characterSet(CharacterSet(charactersIn: "!?@#$%^&*()|\\/<>,.~`_+-="), mode: .inclusive) } errorBuilder: { .password(.missingSpecialChars) }, PredicateConstraint { .length(min: 8) } errorBuilder: { .password(.tooShort) } ) } constraint.set(for: \.email) { PredicateConstraint(.email, error: .email) } constraint.set(for: \.age) { PredicateConstraint(.range(min: 14), error: .underAge) } let user = RegistrationData(username: "nsagora", password: "p@ssW0rd", email: "hello@nsagora.com", age: 21) constraint.evaluate(with: user)
Declaration
Swift
public init()
-
Set a
Constraint
on a property from the root object.Declaration
Swift
public mutating func set<C, V>(for keyPath: KeyPath<T, V>, constraint: C) where E == C.ErrorType, C : Constraint, V == C.InputType
Parameters
constraint
A
Constraint
on the property at the providedKeyPath
.keyPath
The
KeyPath
for the property we set theConstraint
on. -
Set a
Constraint
on a property from the root object.Declaration
Swift
public mutating func set<C, V>(for keyPath: KeyPath<T, V>, constraintBuilder: () -> C) where E == C.ErrorType, C : Constraint, V == C.InputType
Parameters
constraint
A
Constraint
on the property at the providedKeyPath
.keyPath
The
KeyPath
for the property we set theConstraint
on. -
Evaluates the input against the underlying constraints.
Declaration
Swift
public func evaluate(with input: T) -> Result<Void, Summary<E>>
Parameters
input
The input to be validated.
Return Value
.success
if the input is valid,.failure
containing theSummary
of the failingConstraint
s otherwise.
-
Create a new
TypeConstraint
instance.struct RegistrationData { enum Error: Swift.Error { case username case password(Password) case email case underAge } enum Password { case missingUppercase case missingLowercase case missingDigits case missingSpecialChars case tooShort } var username: String var password: String var email: String var age: Int }
var constraint = TypeConstraint<RegistrationData, RegistrationData.Error> { KeyPathConstraint(\.username) { BlockConstraint { $0.count >= 5 } errorBuilder: { .username } } KeyPathConstraint(\.password) { GroupConstraint(.all) { PredicateConstraint { .characterSet(.lowercaseLetters, mode: .inclusive) } errorBuilder: { .password(.missingLowercase) } PredicateConstraint{ .characterSet(.uppercaseLetters, mode: .inclusive) } errorBuilder: { .password(.missingUppercase) } PredicateConstraint { .characterSet(.decimalDigits, mode: .inclusive) } errorBuilder: { .password(.missingDigits) } PredicateConstraint { .characterSet(CharacterSet(charactersIn: "!?@#$%^&*()|\\/<>,.~`_+-="), mode: .inclusive) } errorBuilder: { .password(.missingSpecialChars) } PredicateConstraint { .length(min: 8) } errorBuilder: { .password(.tooShort) } } } KeyPathConstraint(\.email) { PredicateConstraint(.email, error: .email) } KeyPathConstraint(\.age) { PredicateConstraint(.range(min: 14), error: .underAge) } } let user = RegistrationData(username: "nsagora", password: "p@ssW0rd", email: "hello@nsagora.com", age: 21) constraint.evaluate(with: user)
Declaration
Swift
public init(@ConstraintBuilder<T, E> constraintBuilder: () -> [AnyConstraint<T, E>])