<commit_before>//
//  Validator.swift
//  ValidationKit
//
//  Created by <NAME> on 15/08/16.
//  Copyright © 2016 iOS NSAgora. All rights reserved.
//

import Foundation

/**
 A generic collection of `ValidationConstraints` on which an input can be validated on.
 */
public struct Validator<T> {

    var constraints = [ValidationConstraint<T>]()
}

extension Validator {

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter constraint: `ValidationConstraint`
     */
    public mutating func add(constraint:ValidationConstraint<T>) {
        constraints.append(constraint)
    }

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter predicate: A `ValidationPredicate` to describes the evaluation rule.
     - parameter message: A localized `String` to describe the reason why the input is invalid.
     */
    public mutating func add<P:ValidationPredicate>(predicate:P, message:String) where P.InputType == T {
        let constraint = ValidationConstraint(predicate: predicate, message: message)
        add(constraint: constraint)
    }

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter predicate: A `ValidationPredicate` to describes the evaluation rule.
     - parameter message: A `MessageBuilder` clouser to dinamicaly build the reason why the input is invalid.
     */
    public mutating func add<P:ValidationPredicate>(predicate:P, message: @escaping MessageBuilder<T>) where P.InputType == T {
        let constraint = ValidationConstraint(predicate: predicate, message: message)
        add(constraint: constraint)
    }
}

extension Validator {

    /**
     Evaluates the input on all `ValidationConstraints` until the first fails.
     
     - parameter input: The input to be validated.
     - returns: `.Valid` if the input is valid or a `.Invalid` containng the `ValiationError` of the failing `ValidationConstraint` otherwise.
     */
    public func validate(input:T?) -> ValidationResult {
        return constraints.reduce(.valid) { $0.isInvalid ? $0 : $1.evaluate(with: input) }
    }

    /**
     Evaluates the input on all `ValidationConstraints in the collection.
     
     - parameter input: The input to be validated.
     - returns: An array of `ValidationResult` elements, indicating the evaluation result of each `ValidationConstraint` in collection.
     */
    public func validateAll(input:T?) -> [ValidationResult] {
        return constraints.map{ $0.evaluate(with:input) }
    }
}<commit_msg>Add more options for creating new Validator instances<commit_after>//
//  Validator.swift
//  ValidationKit
//
//  Created by <NAME> on 15/08/16.
//  Copyright © 2016 iOS NSAgora. All rights reserved.
//

import Foundation

/**
 A generic collection of `ValidationConstraints` on which an input can be validated on.
 */
public struct Validator<T> {

    var constraints:[ValidationConstraint<T>]
    
    /**
     Create a new `Validator` instance
     */
    public init() {
        constraints = [ValidationConstraint<T>]()
    }
    
    /**
     Create a new `Validator` instance populated with a predefined list of `ValidationConstraints`
     
     - parameter constraints: `[ValidationConstraint]`
     */
    public init(constraints:[ValidationConstraint<T>]) {
        self.constraints = constraints
    }

    /**
     Create a new `Validator` instance populated with a unsized list of `ValidationConstraints`
     
     - parameter constraints: `[ValidationConstraint]`
     */
    public init(constraints:ValidationConstraint<T>...) {
        self.init(constraints:constraints)
    }
}

extension Validator {

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter constraint: `ValidationConstraint`
     */
    public mutating func add(constraint:ValidationConstraint<T>) {
        constraints.append(constraint)
    }

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter predicate: A `ValidationPredicate` to describes the evaluation rule.
     - parameter message: A localized `String` to describe the reason why the input is invalid.
     */
    public mutating func add<P:ValidationPredicate>(predicate:P, message:String) where P.InputType == T {
        let constraint = ValidationConstraint(predicate: predicate, message: message)
        add(constraint: constraint)
    }

    /**
     Adds a `ValidationConstraint` to the generic collection of constraints.
     
     - parameter predicate: A `ValidationPredicate` to describes the evaluation rule.
     - parameter message: A `MessageBuilder` clouser to dinamicaly build the reason why the input is invalid.
     */
    public mutating func add<P:ValidationPredicate>(predicate:P, message: @escaping MessageBuilder<T>) where P.InputType == T {
        let constraint = ValidationConstraint(predicate: predicate, message: message)
        add(constraint: constraint)
    }
}

extension Validator {

    /**
     Evaluates the input on all `ValidationConstraints` until the first fails.
     
     - parameter input: The input to be validated.
     - returns: `.Valid` if the input is valid or a `.Invalid` containng the `ValiationError` of the failing `ValidationConstraint` otherwise.
     */
    public func evaluateAny(input:T?) -> ValidationResult {
        return constraints.reduce(.valid) { $0.isInvalid ? $0 : $1.evaluate(with: input) }
    }

    /**
     Evaluates the input on all `ValidationConstraints in the collection.
     
     - parameter input: The input to be validated.
     - returns: An array of `ValidationResult` elements, indicating the evaluation result of each `ValidationConstraint` in collection.
     */
    public func evaluateAll(input:T?) -> [ValidationResult] {
        return constraints.map{ $0.evaluate(with:input) }
    }
}
{'fraction_non_alphanumeric': 0.09201009251471826, 'fraction_numerical': 0.004709840201850294, 'mean_word_length': 3.1006896551724137, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6503122', 'n_tokens_mistral': 1575, 'n_tokens_neox': 1499, 'n_words': 532}