Skip to content

Instantly share code, notes, and snippets.

@illescasDaniel
Created June 5, 2019 19:58
Show Gist options
  • Save illescasDaniel/91610bcfb0e9b87c2f93f9e7ba1bef8c to your computer and use it in GitHub Desktop.
Save illescasDaniel/91610bcfb0e9b87c2f93f9e7ba1bef8c to your computer and use it in GitHub Desktop.
Validate-propertyWrapper
import Foundation
@propertyWrapper
public struct Validate<Value> {
fileprivate let _isValid: (Value) -> Bool
public let asserts: Bool
public let useLastValid: Bool
public let message: (Value) -> String
public init(_ validation: @escaping (Value) -> Bool,
asserts: Bool = false,//true,
useLastValid: Bool = false,
message: @escaping (Value) -> String = { "Invalid - \(String(describing: $0))" }) {
self._isValid = validation
self.asserts = asserts
self.useLastValid = useLastValid
self.message = message
}
public var value: Value? {
get {
if !useLastValid {
return _value
} else {
return _value ?? _lastValid
}
}
set {
if let newValue = newValue, !_isValid(newValue) {
if asserts {
assertionFailure(self.message(newValue))
}
_value = nil
} else {
_value = newValue
if useLastValid { _lastValid = newValue }
}
}
}
//
private var _value: Value?
private var _lastValid: Value?
}
public extension Validate where Value: Equatable {
init(equals otherValue: Value, asserts: Bool = false) {
self.init({ $0 == otherValue }, asserts: asserts, message: { "Error: \($0) not equals to \(otherValue)" })
}
init(notEquals otherValue: Value, asserts: Bool = false) {
self.init({ $0 != otherValue }, asserts: asserts, message: { "Error: \($0) equals to \(otherValue)" })
}
}
public extension Validate where Value: Comparable {
init(lessThan otherValue: Value, asserts: Bool = false) {
self.init({ $0 < otherValue }, asserts: asserts, message: { "Error: \($0) not less than \(otherValue)" })
}
init(greaterThan otherValue: Value, asserts: Bool = false) {
self.init({ $0 > otherValue }, asserts: asserts, message: { "Error: \($0) not greater than \(otherValue)" })
}
}
public extension Validate where Value: Collection {
init(isEmpty: Bool, asserts: Bool = false) {
self.init({ isEmpty && $0.isEmpty }, asserts: asserts, message: { "Error: \($0) is not empty" })
}
}
public extension Validate where Value == String {
init(regex: String, asserts: Bool = false) {
self.init({ $0.range(of: regex, options: .regularExpression) != nil },
asserts: asserts,
message: { "Error: \($0) doesn't match regex: \(regex)" })
}
init(minLength: UInt = 0, maxLength: UInt = UInt(Int.max), asserts: Bool = false) {
self.init({ (minLength...maxLength).contains(UInt($0.count)) },
asserts: asserts,
message: { "Error: \($0) not between \(minLength) and \(maxLength)" })
}
init(isBlank: Bool, asserts: Bool = false) {
self.init({ isBlank && $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).isEmpty },
asserts: asserts,
message: { "Error: \($0) \(isBlank ? "is not blank" : "is blank")" })
}
}
public extension Validate where Value: FixedWidthInteger {
init(min: Value = .min, max: Value = .max, asserts: Bool = false) {
self.init({ (min...max).contains($0) }, asserts: asserts, message: { "Error: \($0) not between \(min) and \(max)" })
}
}
public extension Validate where Value: Numeric & Comparable {
init(min: Value, max: Value, asserts: Bool = false) {
self.init({ (min...max).contains($0) }, asserts: asserts, message: { "Error: \($0) not between \(min) and \(max)" })
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment