Converted Failable type to Validated property wrapper
This commit is contained in:
parent
a3d86b2ba7
commit
5a785409cb
|
@ -1,6 +1,7 @@
|
|||
extension Failable where T == Bool {
|
||||
extension Validated where T == Bool {
|
||||
/// See [`Bool.toggle()`](https://developer.apple.com/documentation/swift/bool/2994863-toggle).
|
||||
public mutating func toggle() {
|
||||
self.value?.toggle()
|
||||
guard case let .value(value) = self else { return }
|
||||
self = .init(initialValue: !value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
extension Failable: Equatable where T: Equatable {
|
||||
extension Validated: Equatable where T: Equatable {
|
||||
/// See [`Equatable.==(_:_:)`](https://developer.apple.com/documentation/swift/equatable/1539854).
|
||||
public static func == (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Bool {
|
||||
switch (lhs.stored, rhs.stored) {
|
||||
case let (.success(left), .success(right)): return left == right
|
||||
case let (.failure(left), .failure(right)): return left.localizedDescription == right.localizedDescription
|
||||
public static func == (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (.value(left), .value(right)): return left == right
|
||||
case let (.error(left), .error(right)): return left.localizedDescription == right.localizedDescription
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: Comparable where T: Comparable {
|
||||
extension Validated: Comparable where T: Comparable {
|
||||
/// See [`Comparable.<(_:_:)`](https://developer.apple.com/documentation/swift/comparable/1538311).
|
||||
public static func < (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Bool {
|
||||
return Failable<Bool, EmptyValidation<Bool>>(Failable.map(lhs, rhs) { left, right in left < right }).value ?? false
|
||||
public static func < (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (.value(left), .value(right)): return left < right
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: Hashable where T: Hashable {
|
||||
extension Validated: Hashable where T: Hashable {
|
||||
/// See [`Hashable.hash(into:)`](https://developer.apple.com/documentation/swift/hashable/2995575-hash).
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(String(describing: Validations.self))
|
||||
hasher.combine(self.value)
|
||||
switch self {
|
||||
case let .value(value): hasher.combine(value)
|
||||
case let .error(error): hasher.combine(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
extension Failable: Error where T: Error {}
|
||||
extension Validated: Error where T: Error {}
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
extension Failable: ExpressibleByIntegerLiteral where T: ExpressibleByIntegerLiteral {
|
||||
extension Validated: ExpressibleByIntegerLiteral where T: ExpressibleByIntegerLiteral {
|
||||
/// See [`ExpressibleByIntegerLiteral.init(integerLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebyintegerliteral/2298913-init).
|
||||
public init(integerLiteral value: T.IntegerLiteralType) {
|
||||
self = Failable(T(integerLiteral: value))
|
||||
self = Validated(initialValue: T(integerLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByFloatLiteral where T: ExpressibleByFloatLiteral {
|
||||
extension Validated: ExpressibleByFloatLiteral where T: ExpressibleByFloatLiteral {
|
||||
/// See [`ExpressibleByFloatLiteral.init(floatLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebyfloatliteral/2294405-init).
|
||||
public init(floatLiteral value: T.FloatLiteralType) {
|
||||
self = Failable(T(floatLiteral: value))
|
||||
self = Validated(initialValue: T(floatLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByBooleanLiteral where T: ExpressibleByBooleanLiteral {
|
||||
extension Validated: ExpressibleByBooleanLiteral where T: ExpressibleByBooleanLiteral {
|
||||
/// See [`ExpressibleByBooleanLiteral.init(booleanLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebybooleanliteral/2296011-init).
|
||||
public init(booleanLiteral value: T.BooleanLiteralType) {
|
||||
self = Failable(T(booleanLiteral: value))
|
||||
self = Validated(initialValue: T(booleanLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByNilLiteral where T: ExpressibleByNilLiteral {
|
||||
extension Validated: ExpressibleByNilLiteral where T: ExpressibleByNilLiteral {
|
||||
/// See [`ExpressibleByNilLiteral.init(nilLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebynilliteral).
|
||||
public init(nilLiteral: ()) {
|
||||
self = Failable(T(nilLiteral: ()))
|
||||
self = Validated(initialValue: T(nilLiteral: ()))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByStringLiteral where T: ExpressibleByStringLiteral {
|
||||
extension Validated: ExpressibleByStringLiteral where T: ExpressibleByStringLiteral {
|
||||
/// See [`ExpressibleByStringLiteral.init(stringLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebystringliteral/2294174-init)
|
||||
public init(stringLiteral value: T.StringLiteralType) {
|
||||
self = Failable(T(stringLiteral: value))
|
||||
self = Validated(initialValue: T(stringLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByExtendedGraphemeClusterLiteral where T: ExpressibleByExtendedGraphemeClusterLiteral {
|
||||
extension Validated: ExpressibleByExtendedGraphemeClusterLiteral where T: ExpressibleByExtendedGraphemeClusterLiteral {
|
||||
/// See [`ExpressibleByExtendedGraphemeClusterLiteral.init(extendedGraphemeClusterLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebyextendedgraphemeclusterliteral/2294280-init).
|
||||
public init(extendedGraphemeClusterLiteral value: T.ExtendedGraphemeClusterLiteralType) {
|
||||
self = Failable(T(extendedGraphemeClusterLiteral: value))
|
||||
self = Validated(initialValue: T(extendedGraphemeClusterLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByUnicodeScalarLiteral where T: ExpressibleByUnicodeScalarLiteral {
|
||||
extension Validated: ExpressibleByUnicodeScalarLiteral where T: ExpressibleByUnicodeScalarLiteral {
|
||||
/// See [`ExpressibleByUnicodeScalarLiteral.init(unicodeScalarLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebyunicodescalarliteral/2296043-init).
|
||||
public init(unicodeScalarLiteral value: T.UnicodeScalarLiteralType) {
|
||||
self = Failable(T(unicodeScalarLiteral: value))
|
||||
self = Validated(initialValue: T(unicodeScalarLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByArrayLiteral where T: ExpressibleByArrayLiteral {
|
||||
extension Validated: ExpressibleByArrayLiteral where T: ExpressibleByArrayLiteral {
|
||||
/// See [`ExpressibleByArrayLiteral.init(arrayLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebyarrayliteral/2908652-init).
|
||||
public init(arrayLiteral elements: T.ArrayLiteralElement...) {
|
||||
let initializer = unsafeBitCast(T.init(arrayLiteral:), to: (([T.ArrayLiteralElement]) -> T).self)
|
||||
self = Failable(initializer(elements))
|
||||
self = Validated(initialValue: initializer(elements))
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: ExpressibleByDictionaryLiteral where T: ExpressibleByDictionaryLiteral {
|
||||
extension Validated: ExpressibleByDictionaryLiteral where T: ExpressibleByDictionaryLiteral {
|
||||
/// See [`ExpressibleByDictionaryLiteral.init(dictionaryLiteral:)`](https://developer.apple.com/documentation/swift/expressiblebydictionaryliteral/2295781-init).
|
||||
public init(dictionaryLiteral elements: (T.Key, T.Value)...) {
|
||||
let initializer = unsafeBitCast(T.init(dictionaryLiteral:), to: (([(T.Key, T.Value)]) -> T).self)
|
||||
self = Failable(initializer(elements))
|
||||
self = Validated(initialValue: initializer(elements))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
extension Failable: RawRepresentable where T: RawRepresentable {
|
||||
extension Validated: RawRepresentable where T: RawRepresentable {
|
||||
/// See [`RawRepresentable.RawValue`](https://developer.apple.com/documentation/swift/rawrepresentable/1540809-rawvalue).
|
||||
public typealias RawValue = Result<T.RawValue, Error>
|
||||
|
||||
/// See [`RawRepresentable.init(rawValue:)`](https://developer.apple.com/documentation/swift/rawrepresentable/1538354-inithttps://developer.apple.com/documentation/swift/rawrepresentable/1538354-init)
|
||||
public init?(rawValue: RawValue) {
|
||||
guard case let .success(raw) = rawValue, let value = T(rawValue: raw) else { return nil }
|
||||
self = Failable(value)
|
||||
self = Validated(initialValue: value)
|
||||
}
|
||||
|
||||
/// See [`RawRepresentable.rawValue`](https://developer.apple.com/documentation/swift/rawrepresentable/1540698-rawvalue).
|
||||
public var rawValue: Result<T.RawValue, Error> {
|
||||
return self[keyPath: \.rawValue]
|
||||
return Result(catching: { try self.get().rawValue })
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: CaseIterable where T: CaseIterable {
|
||||
extension Validated: CaseIterable where T: CaseIterable {
|
||||
/// See [`CaseIterable.AllCases`](https://developer.apple.com/documentation/swift/caseiterable/2994868-allcases).
|
||||
public typealias AllCases = Array<Failable<T, Validations>>
|
||||
public typealias AllCases = Array<Validated<T, Validations>>
|
||||
|
||||
/// See [`CaseIterable.allCases`](https://developer.apple.com/documentation/swift/caseiterable/2994869-allcases)
|
||||
public static var allCases: AllCases {
|
||||
return T.allCases.map(Failable.init)
|
||||
return T.allCases.map(Validated.init)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
extension Failable: CustomStringConvertible where T: CustomStringConvertible {
|
||||
extension Validated: CustomStringConvertible where T: CustomStringConvertible {
|
||||
/// See [`CustomStringConvertible.description`](https://developer.apple.com/documentation/swift/customstringconvertible/1539130-description).
|
||||
public var description: String {
|
||||
switch self.stored {
|
||||
case let .success(value): return "Failable(" + value.description + ")"
|
||||
case let .failure(error): return "Failable(error: " + error.localizedDescription + ")"
|
||||
switch self {
|
||||
case let .value(value): return "Validated(" + value.description + ")"
|
||||
case let .error(error): return "Validated(error: " + error.localizedDescription + ")"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: LosslessStringConvertible where T: LosslessStringConvertible {
|
||||
extension Validated: LosslessStringConvertible where T: LosslessStringConvertible {
|
||||
/// See [`LosslessStringConvertible.init(_:)`](https://developer.apple.com/documentation/swift/losslessstringconvertible/2429639-init).
|
||||
public init?(_ description: String) {
|
||||
guard let value = T(description) else { return nil }
|
||||
self.init(value)
|
||||
self.init(initialValue: value)
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: CustomDebugStringConvertible where T: CustomDebugStringConvertible {
|
||||
extension Validated: CustomDebugStringConvertible where T: CustomDebugStringConvertible {
|
||||
/// See [`CustomDebugStringConvertible.debugDescription`](https://developer.apple.com/documentation/swift/customdebugstringconvertible/1540125-debugdescription).
|
||||
public var debugDescription: String {
|
||||
return "Failable(value: " + self.value.debugDescription + ", validations: " + String(describing: Validations.self) + ")"
|
||||
return "Validated(value: " + self.value.debugDescription + ", validations: " + String(describing: Validations.self) + ")"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
// MARK: - Keyed Container
|
||||
|
||||
extension KeyedDecodingContainer {
|
||||
/// Decodes a `Failable` instance with the given stored type for the given key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - type: The type of `Failable` instance to decode.
|
||||
/// - key: The key that the decoded value is associated with.
|
||||
///
|
||||
/// - Returns: A value of the requested type, if present for the given key and convertible to the requested type.
|
||||
public func decode<T, V>(_ type: Failable<T, V>.Type, forKey key: K) throws -> Failable<T, V> where T: Decodable {
|
||||
let wrapped = try self.decode(T.self, forKey: key)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
|
||||
/// Decodes a `Failable` instance with the given stored type for the given key if it exists.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - type: The type of `Failable` instance to decode.
|
||||
/// - key: The key that the decoded value is associated with.
|
||||
///
|
||||
/// - Returns: A value of the requested type, if present for the given key and convertible to the requested type.
|
||||
public func decode<T, V>(_ type: Failable<T?, V>.Type, forKey key: K) throws -> Failable<T?, V> where T: Decodable {
|
||||
let wrapped = try self.decodeIfPresent(T.self, forKey: key)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyedEncodingContainer {
|
||||
func value<T, V>(from failable: Failable<T, V>, for key: K) throws -> T where T: Encodable {
|
||||
guard let encodable = failable.value else {
|
||||
throw EncodingError.invalidValue(failable, .init(
|
||||
codingPath: self.codingPath + [key],
|
||||
debugDescription: "Cannot encode error as value of type `\(T.self)`",
|
||||
underlyingError: failable.error
|
||||
))
|
||||
}
|
||||
|
||||
return encodable
|
||||
}
|
||||
|
||||
|
||||
/// Encodes the given `Failable` value for the given key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - value: The value to encode.
|
||||
/// - key: The key to associate the value with.
|
||||
public mutating func encode<T, V>(_ value: Failable<T, V>, forKey key: K) throws where T: Encodable {
|
||||
try self.encode(self.value(from: value, for: key), forKey: key)
|
||||
}
|
||||
|
||||
/// Encodes the given `Failable` value for the given key if it exists.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - value: The value to encode.
|
||||
/// - key: The key to associate the value with.
|
||||
public mutating func encode<T, V>(_ value: Failable<T?, V>, forKey key: K) throws where T: Encodable {
|
||||
try self.encodeIfPresent(self.value(from: value, for: key), forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Unkeyed Container
|
||||
|
||||
extension UnkeyedDecodingContainer {
|
||||
/// Decodes a value of the given type.
|
||||
///
|
||||
/// - Parameter type: The type of `Failable` instance to decode.
|
||||
/// - Returns: A value of the requested type, if present for the given key and convertible to the requested type.
|
||||
public mutating func decode<T, V>(_ type: Failable<T, V>.Type) throws -> Failable<T, V> where T: Decodable {
|
||||
let wrapped = try self.decode(T.self)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
|
||||
/// Decodes a value of the given type.
|
||||
///
|
||||
/// - Parameter type: The type of `Failable` instance to decode.
|
||||
/// - Returns: A value of the requested type, if present for the given key and convertible to the requested type.
|
||||
public mutating func decode<T, V>(_ type: Failable<T?, V>.Type) throws -> Failable<T?, V> where T: Decodable {
|
||||
let wrapped = try self.decodeIfPresent(T.self)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
}
|
||||
|
||||
extension UnkeyedEncodingContainer {
|
||||
func value<T, V>(from failable: Failable<T, V>) throws -> T where T: Encodable {
|
||||
guard let encodable = failable.value else {
|
||||
throw EncodingError.invalidValue(failable, .init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot encode error as value of type `\(T.self)`",
|
||||
underlyingError: failable.error
|
||||
))
|
||||
}
|
||||
|
||||
return encodable
|
||||
}
|
||||
|
||||
/// Encodes the given `Failable` value.
|
||||
///
|
||||
/// - Parameter value: The value to encode.
|
||||
public mutating func encode<T, V>(_ value: Failable<T, V>) throws where T: Encodable {
|
||||
try self.encode(self.value(from: value))
|
||||
}
|
||||
|
||||
/// Encodes the given `Failable` value if it exists.
|
||||
///
|
||||
/// If the value stored by the `Failable` instance is `nil`, then `.encodeNil()` is called instead.
|
||||
///
|
||||
/// - Parameter value: The value to encode.
|
||||
public mutating func encode<T, V>(_ value: Failable<T?, V>) throws where T: Encodable {
|
||||
if let encodable = try self.value(from: value) {
|
||||
try self.encode(encodable)
|
||||
} else {
|
||||
try self.encodeNil()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Single Value Container
|
||||
|
||||
extension SingleValueDecodingContainer {
|
||||
/// Decodes a single `Failable` value of the given type.
|
||||
///
|
||||
/// - Parameter type: The type of `Failable` instance to decode.
|
||||
/// - Returns: A value of the requested type.
|
||||
public func decode<T, V>(_ type: Failable<T, V>.Type) throws -> Failable<T, V> where T: Decodable {
|
||||
let wrapped = try self.decode(T.self)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
|
||||
/// Decodes a single `Failable` value of the given type.
|
||||
///
|
||||
/// - Parameter type: The type of `Failable` instance to decode.
|
||||
/// - Returns: A value of the requested type.
|
||||
public func decode<T, V>(_ type: Failable<T?, V>.Type) throws -> Failable<T?, V> where T: Decodable {
|
||||
if self.decodeNil() {
|
||||
return try Failable(nil).verified()
|
||||
} else {
|
||||
let wrapped = try self.decode(T.self)
|
||||
return try Failable(wrapped).verified()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SingleValueEncodingContainer {
|
||||
func value<T, V>(from failable: Failable<T, V>) throws -> T where T: Encodable {
|
||||
guard let encodable = failable.value else {
|
||||
throw EncodingError.invalidValue(failable, .init(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot encode error as value of type `\(T.self)`",
|
||||
underlyingError: failable.error
|
||||
))
|
||||
}
|
||||
|
||||
return encodable
|
||||
}
|
||||
|
||||
/// Encodes a single `Failable` value.
|
||||
///
|
||||
/// - Parameter value: The value to encode.
|
||||
public mutating func encode<T, V>(_ value: Failable<T, V>) throws where T: Encodable {
|
||||
try self.encode(self.value(from: value))
|
||||
}
|
||||
|
||||
/// Encodes a single `Failable` value if it exists.
|
||||
///
|
||||
/// If the value stored by the `Failable` instance is `nil`, then `.encodeNil()` is called instead.
|
||||
///
|
||||
/// - Parameter value: The value to encode.
|
||||
public mutating func encode<T, V>(_ value: Failable<T?, V>) throws where T: Encodable {
|
||||
if let encodable = try self.value(from: value) {
|
||||
try self.encode(encodable)
|
||||
} else {
|
||||
try self.encodeNil()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,20 @@
|
|||
extension Failable: Encodable where T: Encodable {
|
||||
extension Validated: Encodable where T: Encodable {
|
||||
/// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode)
|
||||
public func encode(to encoder: Encoder)throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
switch self.stored {
|
||||
case let .success(value):
|
||||
try container.encode(value)
|
||||
case let .failure(error):
|
||||
throw EncodingError.invalidValue(self, .init(
|
||||
codingPath: encoder.codingPath,
|
||||
debugDescription: "Cannot encode error as value of type `\(T.self)`",
|
||||
underlyingError: error
|
||||
))
|
||||
}
|
||||
try container.encode(self.get())
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: Decodable where T: Decodable {
|
||||
extension Validated: Decodable where T: Decodable {
|
||||
/// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init)
|
||||
public init(from decoder: Decoder)throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
if _isOptional(T.self), container.decodeNil() {
|
||||
self = try Failable(Void?.none as! T).verified()
|
||||
self = try Validated(initialValue: (Optional<Void>.none as! T)).validate()
|
||||
} else {
|
||||
self = try Failable(container.decode(T.self)).verified()
|
||||
self = try Validated(initialValue: container.decode(T.self)).validate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extension Failable: Sequence where T: Sequence {
|
||||
extension Validated: Sequence where T: Sequence {
|
||||
/// See [`Sequence.Element`](https://developer.apple.com/documentation/swift/sequence/2908099-element).
|
||||
public typealias Element = Failable<T.Element, EmptyValidation<T.Element>>
|
||||
public typealias Element = AlwaysValidated<T.Element>
|
||||
|
||||
/// See [`IteratorProtocol`](https://developer.apple.com/documentation/swift/iteratorprotocol).
|
||||
///
|
||||
|
@ -9,7 +9,7 @@ extension Failable: Sequence where T: Sequence {
|
|||
public struct Iterator: IteratorProtocol {
|
||||
|
||||
/// See [`IteratorProtocol.Element`](https://developer.apple.com/documentation/swift/iteratorprotocol/1641632-element).
|
||||
public typealias Element = Failable.Element
|
||||
public typealias Element = Validated.Element
|
||||
|
||||
var internalIterator: AnyIterator<T.Element>?
|
||||
|
||||
|
@ -20,7 +20,7 @@ extension Failable: Sequence where T: Sequence {
|
|||
/// See [`IteratorProtocol.next()`](https://developer.apple.com/documentation/swift/iteratorprotocol/1641682-next).
|
||||
public mutating func next() -> Element? {
|
||||
if self.internalIterator != nil {
|
||||
return (self.internalIterator?.next()).map(Element.init(_:))
|
||||
return (self.internalIterator?.next()).map(Element.init(initialValue:))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ extension Failable: Sequence where T: Sequence {
|
|||
}
|
||||
}
|
||||
|
||||
extension Failable: Collection where T: Collection {
|
||||
extension Validated: Collection where T: Collection {
|
||||
/// See [`Collection.Index`](https://developer.apple.com/documentation/swift/collection/2943866-index).
|
||||
public typealias Index = Failable<T.Index, EmptyValidation<T.Index>>
|
||||
public typealias Index = AlwaysValidated<T.Index>
|
||||
|
||||
/// See [`Collection.startIndex`](https://developer.apple.com/documentation/swift/collection/2946080-startindex).
|
||||
public var startIndex: Index {
|
||||
|
@ -49,37 +49,37 @@ extension Failable: Collection where T: Collection {
|
|||
}
|
||||
|
||||
/// See [`Collection.endIndex`](https://developer.apple.com/documentation/swift/collection/2944204-endindex).
|
||||
public var endIndex: Failable<T.Index, EmptyValidation<T.Index>> {
|
||||
public var endIndex: Index {
|
||||
return self[keyPath: \.endIndex]
|
||||
}
|
||||
|
||||
/// See [`Collection.subscript(_:)`](https://developer.apple.com/documentation/swift/collection/1641358-subscript).
|
||||
public subscript (position: Index) -> Element {
|
||||
get {
|
||||
return Failable.map(self, position) { collection, index in collection[index] }
|
||||
return Validated.map(self, position) { collection, index in collection[index] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`Collection.index(after:)`](https://developer.apple.com/documentation/swift/collection/2943746-index).
|
||||
public func index(after i: Failable<T.Index, EmptyValidation<T.Index>>) -> Failable<T.Index, EmptyValidation<T.Index>> {
|
||||
return Failable.map(self, i) { collection, index in collection.index(after: index) }
|
||||
public func index(after i: Index) -> Index {
|
||||
return Validated.map(self, i) { collection, index in collection.index(after: index) }
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: BidirectionalCollection where T: BidirectionalCollection {
|
||||
extension Validated: BidirectionalCollection where T: BidirectionalCollection {
|
||||
/// See [`BidirectionalCollection.index(before:)`](https://developer.apple.com/documentation/swift/bidirectionalcollection/3017603-formindex).
|
||||
public func index(before i: Failable<T.Index, EmptyValidation<T.Index>>) -> Failable<T.Index, EmptyValidation<T.Index>> {
|
||||
return Failable.map(self, i) { collection, index in collection.index(before: index) }
|
||||
public func index(before i: Index) -> Index {
|
||||
return Validated.map(self, i) { collection, index in collection.index(before: index) }
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: RandomAccessCollection where T: RandomAccessCollection { }
|
||||
extension Validated: RandomAccessCollection where T: RandomAccessCollection { }
|
||||
|
||||
extension Failable: MutableCollection where T: MutableCollection {
|
||||
extension Validated: MutableCollection where T: MutableCollection {
|
||||
/// See [`MutableCollection.subscript(_:)`](https://developer.apple.com/documentation/swift/mutablecollection/1640969-subscript).
|
||||
public subscript (position: Index) -> Element {
|
||||
get {
|
||||
return Failable.map(self, position) { collection, index in collection[index] }
|
||||
return Validated.map(self, position) { collection, index in collection[index] }
|
||||
}
|
||||
set {
|
||||
if let value = newValue.value, let index = position.value {
|
||||
|
@ -89,9 +89,9 @@ extension Failable: MutableCollection where T: MutableCollection {
|
|||
}
|
||||
}
|
||||
|
||||
extension Failable: RangeReplaceableCollection where T: RangeReplaceableCollection {
|
||||
extension Validated: RangeReplaceableCollection where T: RangeReplaceableCollection {
|
||||
/// See [`RangeReplaceableCollection.init()`](https://developer.apple.com/documentation/swift/rangereplaceablecollection/1641467-init).
|
||||
public init() {
|
||||
self = Failable(T())
|
||||
self = Validated(initialValue: T())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,51 +11,51 @@ public struct MagnitudeValidation<Magnitude>: Validation where Magnitude: Numeri
|
|||
}
|
||||
}
|
||||
|
||||
extension Failable: Strideable where T: Strideable {
|
||||
extension Validated: Strideable where T: Strideable {
|
||||
/// See [`Strideable.Stride`](https://developer.apple.com/documentation/swift/strideable/1541220-stride).
|
||||
public typealias Stride = Failable<T.Stride, EmptyValidation<T.Stride>>
|
||||
public typealias Stride = AlwaysValidated<T.Stride>
|
||||
|
||||
/// See [`Strideable.advanced(by:)`](https://developer.apple.com/documentation/swift/strideable/1641148-advanced).
|
||||
public func advanced(by n: Stride) -> Failable<T, Validations> {
|
||||
return Failable.map(self, n) { start, stride in return start.advanced(by: stride) }
|
||||
public func advanced(by n: Stride) -> Validated<T, Validations> {
|
||||
return Validated.map(self, n) { start, stride in return start.advanced(by: stride) }
|
||||
}
|
||||
|
||||
/// See [`Strideable.distance(to:)`](https://developer.apple.com/documentation/swift/strideable/1641775-distance).
|
||||
public func distance(to other: Failable<T, Validations>) -> Stride {
|
||||
return Failable.map(self, other) { start, end in start.distance(to: end) }
|
||||
public func distance(to other: Validated<T, Validations>) -> Stride {
|
||||
return Validated.map(self, other) { start, end in start.distance(to: end) }
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: AdditiveArithmetic where T: AdditiveArithmetic {
|
||||
extension Validated: AdditiveArithmetic where T: AdditiveArithmetic {
|
||||
/// See [`AdditiveArithmetic.zero`](https://developer.apple.com/documentation/swift/additivearithmetic/3126829-zero).
|
||||
public static var zero: Failable<T, Validations> {
|
||||
return Failable(T.zero)
|
||||
public static var zero: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.zero)
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.-(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126825).
|
||||
public static func - (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in left - right }
|
||||
public static func - (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in left - right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.+(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126821).
|
||||
public static func + (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in left + right }
|
||||
public static func + (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in left + right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.-=(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126828).
|
||||
public static func -= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func -= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs - rhs
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.+=(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126824).
|
||||
public static func += (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func += (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs + rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: Numeric where T: Numeric {
|
||||
extension Validated: Numeric where T: Numeric {
|
||||
/// See [`Numeric.Magnitude`](https://developer.apple.com/documentation/swift/numeric/2884423-magnitude).
|
||||
public typealias Magnitude = Failable<T.Magnitude, MagnitudeValidation<T.Magnitude>>
|
||||
public typealias Magnitude = Validated<T.Magnitude, MagnitudeValidation<T.Magnitude>>
|
||||
|
||||
/// See [`Numeric.magnitude`](https://developer.apple.com/documentation/swift/numeric/2884876-magnitude).
|
||||
public var magnitude: Magnitude {
|
||||
|
@ -65,65 +65,65 @@ extension Failable: Numeric where T: Numeric {
|
|||
/// See [`Numeric.init(exactly:)`](https://developer.apple.com/documentation/swift/numeric/2886795-init).
|
||||
public init?<N>(exactly source: N) where N : BinaryInteger {
|
||||
guard let value = T(exactly: source) else { return nil }
|
||||
self.init(value)
|
||||
self.init(initialValue: value)
|
||||
}
|
||||
|
||||
/// See [`Numeric.*(_:_:)`](https://developer.apple.com/documentation/swift/numeric/2883821).
|
||||
public static func * (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs, closure: { left, right in left * right })
|
||||
public static func * (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs, closure: { left, right in left * right })
|
||||
}
|
||||
|
||||
/// See [`Numeric.*=(_:_:)`](https://developer.apple.com/documentation/swift/numeric/2886882).
|
||||
public static func *= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func *= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs * rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: SignedNumeric where T: SignedNumeric {
|
||||
extension Validated: SignedNumeric where T: SignedNumeric {
|
||||
/// See [`SignedNumeric.negate()`](https://developer.apple.com/documentation/swift/signednumeric/2883859-negate).
|
||||
public mutating func negate() {
|
||||
self.value?.negate()
|
||||
}
|
||||
|
||||
/// See [`SignedNumeric.-(_:)`](https://developer.apple.com/documentation/swift/signednumeric/2965579).
|
||||
public static prefix func - (lhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
public static prefix func - (lhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
guard let value = lhs.value else { return lhs }
|
||||
return Failable<T, Validations>(-value)
|
||||
return Validated<T, Validations>(initialValue: -value)
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.-(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126825).
|
||||
public func - <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func - <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: AdditiveArithmetic
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left - right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left - right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.+(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126821).
|
||||
public func + <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func + <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: AdditiveArithmetic
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left + right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left + right }
|
||||
}
|
||||
|
||||
/// See [`Numeric.*(_:_:)`](https://developer.apple.com/documentation/swift/numeric/2883821).
|
||||
public func * <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func * <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: Numeric
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left * right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left * right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.-=(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126828).
|
||||
public func -= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: AdditiveArithmetic {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left - right }
|
||||
public func -= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: AdditiveArithmetic {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left - right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.+=(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126824).
|
||||
public func += <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: AdditiveArithmetic {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left + right }
|
||||
public func += <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: AdditiveArithmetic {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left + right }
|
||||
}
|
||||
|
||||
/// See [`Numeric.*=(_:_:)`](https://developer.apple.com/documentation/swift/numeric/2886882).
|
||||
public func *= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: Numeric {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left * right }
|
||||
public func *= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: Numeric {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left * right }
|
||||
}
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
// TODO: Try to remove `Validations == MagnitudeValidation<T>` constraint.
|
||||
extension Failable: FloatingPoint where T: FloatingPoint, Validations == MagnitudeValidation<T> {
|
||||
extension Validated: FloatingPoint where T: FloatingPoint, Validations == MagnitudeValidation<T> {
|
||||
/// See [`FloatingPoint.Exponent`](https://developer.apple.com/documentation/swift/floatingpoint/1848224-exponent).
|
||||
public typealias Exponent = Failable<T.Exponent, EmptyValidation<T.Exponent>>
|
||||
public typealias Exponent = AlwaysValidated<T.Exponent>
|
||||
|
||||
/// See [`FloatingPoint.nan`](https://developer.apple.com/documentation/swift/floatingpoint/1641652-nan).
|
||||
public static var nan: Failable<T, Validations> {
|
||||
return Failable(T.nan)
|
||||
public static var nan: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.nan)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.signalingNaN`](https://developer.apple.com/documentation/swift/floatingpoint/1845864-signalingnan).
|
||||
public static var signalingNaN: Failable<T, Validations> {
|
||||
return Failable(T.signalingNaN)
|
||||
public static var signalingNaN: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.signalingNaN)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.infinity`](https://developer.apple.com/documentation/swift/floatingpoint/1641304-infinity).
|
||||
public static var infinity: Failable<T, Validations> {
|
||||
return Failable(T.infinity)
|
||||
public static var infinity: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.infinity)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.greatestFiniteMagnitude`](https://developer.apple.com/documentation/swift/floatingpoint/1849534-greatestfinitemagnitude).
|
||||
public static var greatestFiniteMagnitude: Failable<T, Validations> {
|
||||
return Failable(T.greatestFiniteMagnitude)
|
||||
public static var greatestFiniteMagnitude: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.greatestFiniteMagnitude)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.pi`](https://developer.apple.com/documentation/swift/floatingpoint/1845454-pi).
|
||||
public static var pi: Failable<T, Validations> {
|
||||
return Failable(T.pi)
|
||||
public static var pi: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.pi)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.leastNormalMagnitude`](https://developer.apple.com/documentation/swift/floatingpoint/1849504-leastnormalmagnitude).
|
||||
public static var leastNormalMagnitude: Failable<T, Validations> {
|
||||
return Failable(T.leastNormalMagnitude)
|
||||
public static var leastNormalMagnitude: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.leastNormalMagnitude)
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.leastNonzeroMagnitude`](https://developer.apple.com/documentation/swift/floatingpoint/1848591-leastnonzeromagnitude).
|
||||
public static var leastNonzeroMagnitude: Failable<T, Validations> {
|
||||
return Failable(T.leastNonzeroMagnitude)
|
||||
public static var leastNonzeroMagnitude: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.leastNonzeroMagnitude)
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
|
||||
/// See [`FloatingPoint.ulp`](https://developer.apple.com/documentation/swift/floatingpoint/1847492-ulp).
|
||||
public var ulp: Failable<T, Validations> {
|
||||
public var ulp: Validated<T, Validations> {
|
||||
return self[keyPath: \.ulp]
|
||||
}
|
||||
|
||||
|
@ -55,18 +55,18 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
|
||||
/// See [`FloatingPoint.exponent`](https://developer.apple.com/documentation/swift/floatingpoint/1846275-exponent).
|
||||
public var exponent: Failable<T.Exponent, EmptyValidation<T.Exponent>> {
|
||||
return self[keyPath: \.exponent]
|
||||
public var exponent: Exponent {
|
||||
return self.map { $0.exponent }
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.significand`](https://developer.apple.com/documentation/swift/floatingpoint/1847298-significand).
|
||||
public var significand: Failable<T, Validations> {
|
||||
return self[keyPath: \.significand]
|
||||
public var significand: Validated<T, Validations> {
|
||||
return self.map { $0.significand }
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.nextUp`](https://developer.apple.com/documentation/swift/floatingpoint/1848104-nextup).
|
||||
public var nextUp: Failable<T, Validations> {
|
||||
return self[keyPath: \.nextUp]
|
||||
public var nextUp: Validated<T, Validations> {
|
||||
return self.map { $0.nextUp }
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.isNormal`](https://developer.apple.com/documentation/swift/floatingpoint/1641394-isnormal).
|
||||
|
@ -112,42 +112,42 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
|
||||
/// See [`FloatingPoint.init(_:)`](https://developer.apple.com/documentation/swift/floatingpoint/1641560-init).
|
||||
public init(_ value: Int) {
|
||||
self = Failable(T(value))
|
||||
self = Validated(initialValue: T(value))
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.init(_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2964416-init).
|
||||
public init<Source>(_ value: Source) where Source : BinaryInteger {
|
||||
self = Failable(T(value))
|
||||
self = Validated(initialValue: T(value))
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.init(sign:exponent:significand:`](https://developer.apple.com/documentation/swift/floatingpoint/1845755-init).
|
||||
public init(sign: FloatingPointSign, exponent: Exponent, significand: Failable<T, Validations>) {
|
||||
self = Failable.map(exponent, significand) { exp, sig in T(sign: sign, exponent: exp, significand: sig)}
|
||||
public init(sign: FloatingPointSign, exponent: Exponent, significand: Validated<T, Validations>) {
|
||||
self = Validated.map(exponent, significand) { exp, sig in T(sign: sign, exponent: exp, significand: sig)}
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.init(signOf:magnitudeOf:)`](https://developer.apple.com/documentation/swift/floatingpoint/1849294-init).
|
||||
public init(signOf sign: Failable<T, Validations>, magnitudeOf maginitude: Failable<T, Validations>) {
|
||||
self = Failable.map(sign, maginitude, closure: T.init(signOf:magnitudeOf:))
|
||||
public init(signOf sign: Validated<T, Validations>, magnitudeOf maginitude: Validated<T, Validations>) {
|
||||
self = Validated.map(sign, maginitude, closure: T.init(signOf:magnitudeOf:))
|
||||
}
|
||||
|
||||
|
||||
/// See [`FloatingPoint.*(_:_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2886135).
|
||||
public static func * (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in left * right }
|
||||
public static func * (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in left * right }
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.*=(_:_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2885700).
|
||||
public static func *= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func *= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs * rhs
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint./(_:_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2884057).
|
||||
public static func / (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in left / right }
|
||||
public static func / (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in left / right }
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint./=(_:_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2886632).
|
||||
public static func /= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func /= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs / rhs
|
||||
}
|
||||
|
||||
|
@ -157,8 +157,8 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
|
||||
/// See [`FloatingPoint.formRemainder(dividingBy:)`](https://developer.apple.com/documentation/swift/floatingpoint/2299459-formremainder).
|
||||
public mutating func formRemainder(dividingBy other: Failable<T, Validations>) {
|
||||
self = Failable.map(self, other) { left, right in
|
||||
public mutating func formRemainder(dividingBy other: Validated<T, Validations>) {
|
||||
self = Validated.map(self, other) { left, right in
|
||||
var result = left
|
||||
result.formRemainder(dividingBy: right)
|
||||
return result
|
||||
|
@ -166,8 +166,8 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
|
||||
/// See [`FloatingPoint.formTruncatingRemainder(dividingBy:)`](https://developer.apple.com/documentation/swift/floatingpoint/1846470-formtruncatingremainder).
|
||||
public mutating func formTruncatingRemainder(dividingBy other: Failable<T, Validations>) {
|
||||
self = Failable.map(self, other) { left, right in
|
||||
public mutating func formTruncatingRemainder(dividingBy other: Validated<T, Validations>) {
|
||||
self = Validated.map(self, other) { left, right in
|
||||
var result = left
|
||||
result.formTruncatingRemainder(dividingBy: right)
|
||||
return result
|
||||
|
@ -184,34 +184,34 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
|
||||
/// See [`FloatingPoint.addProduct(_:_:)`](https://developer.apple.com/documentation/swift/floatingpoint/2295205-addproduct).
|
||||
public mutating func addProduct(_ lhs: Failable<T, Validations>, _ rhs: Failable<T, Validations>) {
|
||||
public mutating func addProduct(_ lhs: Validated<T, Validations>, _ rhs: Validated<T, Validations>) {
|
||||
self = self.map { value in
|
||||
var result = value
|
||||
let _: Failable<(), EmptyValidation<()>> = try Failable.map(lhs, rhs) { left, right in
|
||||
let _: AlwaysValidated<()> = try Validated.map(lhs, rhs) { left, right in
|
||||
result.addProduct(left, right)
|
||||
}.verified()
|
||||
}.validate()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.isEqual(to:)`](https://developer.apple.com/documentation/swift/floatingpoint/1846385-isequal).
|
||||
public func isEqual(to other: Failable<T, Validations>) -> Bool {
|
||||
public func isEqual(to other: Validated<T, Validations>) -> Bool {
|
||||
return self == other
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.isLess(than:)`](https://developer.apple.com/documentation/swift/floatingpoint/1849403-isless).
|
||||
public func isLess(than other: Failable<T, Validations>) -> Bool {
|
||||
public func isLess(than other: Validated<T, Validations>) -> Bool {
|
||||
return self < other
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.isLessThanOrEqualTo(_:)`](https://developer.apple.com/documentation/swift/floatingpoint/1849007-islessthanorequalto).
|
||||
public func isLessThanOrEqualTo(_ other: Failable<T, Validations>) -> Bool {
|
||||
public func isLessThanOrEqualTo(_ other: Validated<T, Validations>) -> Bool {
|
||||
return self <= other
|
||||
}
|
||||
|
||||
/// See [`FloatingPoint.isTotallyOrdered(belowOrEqualTo:)`](https://developer.apple.com/documentation/swift/floatingpoint/2428057-istotallyordered).
|
||||
public func isTotallyOrdered(belowOrEqualTo other: Failable<T, MagnitudeValidation<T>>) -> Bool {
|
||||
let ordered: Failable<Bool, EmptyValidation<Bool>> = Failable.map(self, other) { left, right -> Bool in
|
||||
public func isTotallyOrdered(belowOrEqualTo other: Validated<T, MagnitudeValidation<T>>) -> Bool {
|
||||
let ordered: AlwaysValidated<Bool> = Validated.map(self, other) { left, right -> Bool in
|
||||
return left.isTotallyOrdered(belowOrEqualTo: right)
|
||||
}
|
||||
|
||||
|
@ -219,12 +219,12 @@ extension Failable: FloatingPoint where T: FloatingPoint, Validations == Magnitu
|
|||
}
|
||||
}
|
||||
|
||||
extension Failable: BinaryFloatingPoint where T: BinaryFloatingPoint, Validations == MagnitudeValidation<T> {
|
||||
extension Validated: BinaryFloatingPoint where T: BinaryFloatingPoint, Validations == MagnitudeValidation<T> {
|
||||
/// See [`BinaryFloatingPoint.RawSignificand`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1846956-rawexponent).
|
||||
public typealias RawSignificand = Failable<T.RawSignificand, EmptyValidation<T.RawSignificand>>
|
||||
public typealias RawSignificand = AlwaysValidated<T.RawSignificand>
|
||||
|
||||
/// See [`BinaryFloatingPoint.RawExponent`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1848447-rawsignificand).
|
||||
public typealias RawExponent = Failable<T.RawExponent, EmptyValidation<T.RawExponent>>
|
||||
public typealias RawExponent = AlwaysValidated<T.RawExponent>
|
||||
|
||||
/// See [`BinaryFloatingPoint.exponentBitCount`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1847221-exponentbitcount).
|
||||
public static var exponentBitCount: Int {
|
||||
|
@ -242,34 +242,34 @@ extension Failable: BinaryFloatingPoint where T: BinaryFloatingPoint, Validation
|
|||
}
|
||||
|
||||
/// See [`BinaryFloatingPoint.binade`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1848292-binade).
|
||||
public var binade: Failable<T, Validations> {
|
||||
return self[keyPath: \.binade]
|
||||
public var binade: Validated<T, Validations> {
|
||||
return self.map { $0.binade }
|
||||
}
|
||||
|
||||
/// See [`BinaryFloatingPoint.exponentBitPattern`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1846505-exponentbitpattern).
|
||||
public var exponentBitPattern: Failable<T.RawExponent, EmptyValidation<T.RawExponent>> {
|
||||
return self[keyPath: \.exponentBitPattern]
|
||||
public var exponentBitPattern: AlwaysValidated<T.RawExponent> {
|
||||
return self.map { $0.exponentBitPattern }
|
||||
}
|
||||
|
||||
/// See [`BinaryFloatingPoint.significandBitPattern`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1845838-significandbitpattern).
|
||||
public var significandBitPattern: Failable<T.RawSignificand, EmptyValidation<T.RawSignificand>> {
|
||||
return self[keyPath: \.significandBitPattern]
|
||||
public var significandBitPattern: AlwaysValidated<T.RawSignificand> {
|
||||
return self.map { $0.significandBitPattern }
|
||||
}
|
||||
|
||||
/// See [`BinaryFloatingPoint.init(sign:exponentBitPattern:significandBitPattern)`](https://developer.apple.com/documentation/swift/binaryfloatingpoint/1849503-init).
|
||||
public init(sign: FloatingPointSign, exponentBitPattern expBP: RawExponent, significandBitPattern sigBP: RawSignificand) {
|
||||
self = Failable.map(expBP, sigBP) { exp, sig in T(sign: sign, exponentBitPattern: exp, significandBitPattern: sig) }
|
||||
self = Validated.map(expBP, sigBP) { exp, sig in T(sign: sign, exponentBitPattern: exp, significandBitPattern: sig) }
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`Numeric.*(_:_:)`](https://developer.apple.com/documentation/swift/numeric/2883821).
|
||||
public func / <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func / <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: FloatingPoint
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left / right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left / right }
|
||||
}
|
||||
|
||||
/// See [`AdditiveArithmetic.-=(_:_:)`](https://developer.apple.com/documentation/swift/additivearithmetic/3126828).
|
||||
public func /= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: FloatingPoint {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left / right }
|
||||
public func /= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: FloatingPoint {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left / right }
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
extension Failable: UnsignedInteger where T: UnsignedInteger { }
|
||||
extension Validated: UnsignedInteger where T: UnsignedInteger { }
|
||||
|
||||
extension Failable: SignedInteger where T: SignedInteger { }
|
||||
extension Validated: SignedInteger where T: SignedInteger { }
|
||||
|
||||
extension Failable: FixedWidthInteger where T: FixedWidthInteger {
|
||||
extension Validated: FixedWidthInteger where T: FixedWidthInteger {
|
||||
/// See [`FixedWidthInteger.bitWidth`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2886552-bitwidth).
|
||||
public static var bitWidth: Int {
|
||||
return T.bitWidth
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.min`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2884515-min).
|
||||
public static var min: Failable<T, Validations> {
|
||||
return Failable(T.min)
|
||||
public static var min: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.min)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.max`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2883788-max).
|
||||
public static var max: Failable<T, Validations> {
|
||||
return Failable(T.max)
|
||||
public static var max: Validated<T, Validations> {
|
||||
return Validated(initialValue: T.max)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.nonzeroBitCount`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2885911-nonzerobitcount).
|
||||
|
@ -29,81 +29,81 @@ extension Failable: FixedWidthInteger where T: FixedWidthInteger {
|
|||
}
|
||||
|
||||
/// See [`FixedWidthInteger.byteSwapped`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2884324-byteswapped).
|
||||
public var byteSwapped: Failable<T, Validations> {
|
||||
public var byteSwapped: Validated<T, Validations> {
|
||||
return self.map { $0.byteSwapped }
|
||||
}
|
||||
|
||||
/// I don't know what this initializer is for. The `FixedWidthInteger` requires it,
|
||||
/// but I can't find the documentation. Here's a unicorn instead: 🦄
|
||||
public init<BI>(_truncatingBits truncatingBits: BI) where BI : BinaryInteger {
|
||||
self = Failable(T(truncatingBits))
|
||||
self = Validated(initialValue: T(truncatingBits))
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.addingReportingOverflow(_:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2885260-addingreportingoverflow).
|
||||
public func addingReportingOverflow(_ rhs: Failable<T, Validations>)
|
||||
-> (partialValue: Failable<T, Validations>, overflow: Bool)
|
||||
public func addingReportingOverflow(_ rhs: Validated<T, Validations>)
|
||||
-> (partialValue: Validated<T, Validations>, overflow: Bool)
|
||||
{
|
||||
let result: Failable<(T, Bool), EmptyValidation<(T, Bool)>> = Failable.map(self, rhs) { left, right in
|
||||
let result: AlwaysValidated<(T, Bool)> = Validated.map(self, rhs) { left, right in
|
||||
return left.addingReportingOverflow(right)
|
||||
}
|
||||
|
||||
let overflow: Failable<Bool, EmptyValidation<Bool>> = result.map { $0.1 }
|
||||
let overflow: AlwaysValidated<Bool> = result.map { $0.1 }
|
||||
return (partialValue: result.map { $0.0 }, overflow: overflow.value ?? false)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.subtractingReportingOverflow(_:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2885098-subtractingreportingoverflow).
|
||||
public func subtractingReportingOverflow(_ rhs: Failable<T, Validations>)
|
||||
-> (partialValue: Failable<T, Validations>, overflow: Bool)
|
||||
public func subtractingReportingOverflow(_ rhs: Validated<T, Validations>)
|
||||
-> (partialValue: Validated<T, Validations>, overflow: Bool)
|
||||
{
|
||||
let result: Failable<(T, Bool), EmptyValidation<(T, Bool)>> = Failable.map(self, rhs) { left, right in
|
||||
let result: AlwaysValidated<(T, Bool)> = Validated.map(self, rhs) { left, right in
|
||||
return left.subtractingReportingOverflow(right)
|
||||
}
|
||||
|
||||
let overflow: Failable<Bool, EmptyValidation<Bool>> = result.map { $0.1 }
|
||||
let overflow: AlwaysValidated<Bool> = result.map { $0.1 }
|
||||
return (partialValue: result.map { $0.0 }, overflow: overflow.value ?? false)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.multipliedReportingOverflow(by:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2884864-multipliedreportingoverflow).
|
||||
public func multipliedReportingOverflow(by rhs: Failable<T, Validations>)
|
||||
-> (partialValue: Failable<T, Validations>, overflow: Bool)
|
||||
public func multipliedReportingOverflow(by rhs: Validated<T, Validations>)
|
||||
-> (partialValue: Validated<T, Validations>, overflow: Bool)
|
||||
{
|
||||
let result: Failable<(T, Bool), EmptyValidation<(T, Bool)>> = Failable.map(self, rhs) { left, right in
|
||||
let result: AlwaysValidated<(T, Bool)> = Validated.map(self, rhs) { left, right in
|
||||
return left.multipliedReportingOverflow(by: right)
|
||||
}
|
||||
|
||||
let overflow: Failable<Bool, EmptyValidation<Bool>> = result.map { $0.1 }
|
||||
let overflow: AlwaysValidated<Bool> = result.map { $0.1 }
|
||||
return (partialValue: result.map { $0.0 }, overflow: overflow.value ?? false)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.dividedReportingOverflow(by:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2885588-dividedreportingoverflow).
|
||||
public func dividedReportingOverflow(by rhs: Failable<T, Validations>)
|
||||
-> (partialValue: Failable<T, Validations>, overflow: Bool)
|
||||
public func dividedReportingOverflow(by rhs: Validated<T, Validations>)
|
||||
-> (partialValue: Validated<T, Validations>, overflow: Bool)
|
||||
{
|
||||
let result: Failable<(T, Bool), EmptyValidation<(T, Bool)>> = Failable.map(self, rhs) { left, right in
|
||||
let result: AlwaysValidated<(T, Bool)> = Validated.map(self, rhs) { left, right in
|
||||
return left.dividedReportingOverflow(by: right)
|
||||
}
|
||||
|
||||
let overflow: Failable<Bool, EmptyValidation<Bool>> = result.map { $0.1 }
|
||||
let overflow: AlwaysValidated<Bool> = result.map { $0.1 }
|
||||
return (partialValue: result.map { $0.0 }, overflow: overflow.value ?? false)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.remainderReportingOverflow(dividingBy:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2892758-remainderreportingoverflow).
|
||||
public func remainderReportingOverflow(dividingBy rhs: Failable<T, Validations>)
|
||||
-> (partialValue: Failable<T, Validations>, overflow: Bool)
|
||||
public func remainderReportingOverflow(dividingBy rhs: Validated<T, Validations>)
|
||||
-> (partialValue: Validated<T, Validations>, overflow: Bool)
|
||||
{
|
||||
let result: Failable<(T, Bool), EmptyValidation<(T, Bool)>> = Failable.map(self, rhs) { left, right in
|
||||
let result: AlwaysValidated<(T, Bool)> = Validated.map(self, rhs) { left, right in
|
||||
return left.remainderReportingOverflow(dividingBy: right)
|
||||
}
|
||||
|
||||
let overflow: Failable<Bool, EmptyValidation<Bool>> = result.map { $0.1 }
|
||||
let overflow: AlwaysValidated<Bool> = result.map { $0.1 }
|
||||
return (partialValue: result.map { $0.0 }, overflow: overflow.value ?? false)
|
||||
}
|
||||
|
||||
/// See [`FixedWidthInteger.multipliedFullWidth(by:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2884581-multipliedfullwidth).
|
||||
public func multipliedFullWidth(by other: Failable<T, Validations>)
|
||||
-> (high: Failable<T, Validations>, low: Failable<T.Magnitude, MagnitudeValidation<T.Magnitude>>)
|
||||
public func multipliedFullWidth(by other: Validated<T, Validations>)
|
||||
-> (high: Validated<T, Validations>, low: Validated<T.Magnitude, MagnitudeValidation<T.Magnitude>>)
|
||||
{
|
||||
let results: Failable<(T, T.Magnitude), EmptyValidation<(T, T.Magnitude)>> = Failable.map(self, other) { left, right in
|
||||
let results: AlwaysValidated<(T, T.Magnitude)> = Validated.map(self, other) { left, right in
|
||||
return left.multipliedFullWidth(by: right)
|
||||
}
|
||||
|
||||
|
@ -112,23 +112,23 @@ extension Failable: FixedWidthInteger where T: FixedWidthInteger {
|
|||
|
||||
/// See [`FixedWidthInteger.dividingFullWidth(dividend:)`](https://developer.apple.com/documentation/swift/fixedwidthinteger/2884055-dividingfullwidth).
|
||||
public func dividingFullWidth(
|
||||
_ dividend: (high: Failable<T, Validations>, low: Failable<T.Magnitude, MagnitudeValidation<T.Magnitude>>)
|
||||
) -> (quotient: Failable<T, Validations>, remainder: Failable<T, Validations>) {
|
||||
switch (self.stored, dividend.high.stored, dividend.low.stored) {
|
||||
case let (.success(l), .success(high), .success(low)):
|
||||
_ dividend: (high: Validated<T, Validations>, low: Validated<T.Magnitude, MagnitudeValidation<T.Magnitude>>)
|
||||
) -> (quotient: Validated<T, Validations>, remainder: Validated<T, Validations>) {
|
||||
switch (self, dividend.high, dividend.low) {
|
||||
case let (.value(l), .value(high), .value(low)):
|
||||
let result = l.dividingFullWidth((high, low))
|
||||
return (Failable(result.quotient), Failable(result.remainder))
|
||||
case let (_, .failure(left), .failure(right)):
|
||||
return (Validated(initialValue: result.quotient), Validated(initialValue: result.remainder))
|
||||
case let (_, .error(left), .error(right)):
|
||||
let error = ValidationError.foundError(ErrorJoin(left, right))
|
||||
return (Failable(error), Failable(error))
|
||||
case (.failure(let err), _, _), (_, .failure(let err), _), (_, _, .failure(let err)):
|
||||
return (.error(error), .error(error))
|
||||
case (.error(let err), _, _), (_, .error(let err), _), (_, _, .error(let err)):
|
||||
let error = ValidationError.foundError(err)
|
||||
return (Failable(error), Failable(error))
|
||||
return (.error(error), .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable: BinaryInteger where T: BinaryInteger {
|
||||
extension Validated: BinaryInteger where T: BinaryInteger {
|
||||
/// See [`BinaryInteger.Words`](https://developer.apple.com/documentation/swift/binaryinteger/2894610-words).
|
||||
public typealias Words = Array<UInt>
|
||||
|
||||
|
@ -139,29 +139,29 @@ extension Failable: BinaryInteger where T: BinaryInteger {
|
|||
|
||||
/// See [`BinaryInteger.init(_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885704-init).
|
||||
public init<BI>(_ source: BI) where BI: BinaryInteger {
|
||||
self = Failable(T(source))
|
||||
self = Validated(initialValue: T(source))
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.init(_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2884166-init).
|
||||
public init<BFP>(_ source: BFP) where BFP : BinaryFloatingPoint {
|
||||
self = Failable(T(source))
|
||||
self = Validated(initialValue: T(source))
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.init(clamping:)`](https://developer.apple.com/documentation/swift/binaryinteger/2886143-init).
|
||||
public init<BI>(clamping source: BI) where BI: BinaryInteger {
|
||||
self = Failable(T(clamping: source))
|
||||
self = Validated(initialValue: T(clamping: source))
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.init(exactly:)`](https://developer.apple.com/documentation/swift/binaryinteger/2925955-init).
|
||||
public init?<BFP>(exactly source: BFP) where BFP : BinaryFloatingPoint {
|
||||
guard let value = T(exactly: source) else { return nil }
|
||||
self = Failable(value)
|
||||
self = Validated(initialValue: value)
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.init(truncatingIfNeeded:)`](https://developer.apple.com/documentation/swift/binaryinteger/2925529-init).
|
||||
public init<BI>(truncatingIfNeeded source: BI) where BI: BinaryInteger {
|
||||
let t = T(truncatingIfNeeded: source)
|
||||
self = Failable(t)
|
||||
self = Validated(initialValue: t)
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.isSigned`](https://developer.apple.com/documentation/swift/binaryinteger/2886485-issigned).
|
||||
|
@ -180,122 +180,125 @@ extension Failable: BinaryInteger where T: BinaryInteger {
|
|||
}
|
||||
|
||||
/// See [`BinaryInteger.~(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2884248).
|
||||
public prefix static func ~ (value: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
public prefix static func ~ (value: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return value.map { ~$0 }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger./(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885552).
|
||||
public static func / (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in return left / right }
|
||||
public static func / (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in return left / right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger./=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885191).
|
||||
public static func /= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func /= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs / rhs
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.%(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885003).
|
||||
public static func % (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in return left % right }
|
||||
public static func % (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in return left % right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.%=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2886158).
|
||||
public static func %= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func %= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs % rhs
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.&(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017613).
|
||||
public static func & (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in return left & right }
|
||||
public static func & (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in return left & right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.&=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885976).
|
||||
public static func &= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func &= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs & rhs
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.|(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017645).
|
||||
public static func | (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in return left | right }
|
||||
public static func | (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in return left | right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.|=(_:_:)`]().
|
||||
public static func |= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func |= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs | rhs
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.^(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2884669).
|
||||
public static func ^ (lhs: Failable<T, Validations>, rhs: Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
return Failable.map(lhs, rhs) { left, right in return left ^ right }
|
||||
public static func ^ (lhs: Validated<T, Validations>, rhs: Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
return Validated.map(lhs, rhs) { left, right in return left ^ right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.^=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017635).
|
||||
public static func ^= (lhs: inout Failable<T, Validations>, rhs: Failable<T, Validations>) {
|
||||
public static func ^= (lhs: inout Validated<T, Validations>, rhs: Validated<T, Validations>) {
|
||||
lhs = lhs ^ rhs
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.>>=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2926011).
|
||||
public static func >>= <RHS>(lhs: inout Failable<T, Validations>, rhs: RHS) where RHS : BinaryInteger {
|
||||
public static func >>= <RHS>(lhs: inout Validated<T, Validations>, rhs: RHS) where RHS : BinaryInteger {
|
||||
lhs = lhs.map { $0 >> rhs }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.<<=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2926303).
|
||||
public static func <<= <RHS>(lhs: inout Failable<T, Validations>, rhs: RHS) where RHS : BinaryInteger {
|
||||
public static func <<= <RHS>(lhs: inout Validated<T, Validations>, rhs: RHS) where RHS : BinaryInteger {
|
||||
lhs = lhs.map { $0 << rhs }
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.%(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885003).
|
||||
public func % <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func % <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: BinaryInteger
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left % right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left % right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.&(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017613).
|
||||
public func & <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func & <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: BinaryInteger
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left & right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left & right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.<(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885984).
|
||||
public func < <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Bool
|
||||
where T: BinaryInteger
|
||||
public func < <T, V1, Other>(lhs: Validated<T, V1>, rhs: Other) -> Bool
|
||||
where T: BinaryInteger, Other: BinaryInteger
|
||||
{
|
||||
return Failable<Bool, EmptyValidation<Bool>>(Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> Bool in left < right }).value ?? false
|
||||
switch lhs {
|
||||
case let .value(value): return value < rhs
|
||||
case .error: return false
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.^(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017635).
|
||||
public func ^ <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func ^ <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: BinaryInteger
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left ^ right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left ^ right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.|(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/3017645).
|
||||
public func | <T, V1, V2>(lhs: Failable<T, V1>, rhs: Failable<T, V2>) -> Failable<T, AppendedValidations<V1, V2>>
|
||||
public func | <T, V1, V2>(lhs: Validated<T, V1>, rhs: Validated<T, V2>) -> Validated<T, AppendedValidations<V1, V2>>
|
||||
where T: BinaryInteger
|
||||
{
|
||||
return Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left | right }
|
||||
return Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left | right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.%=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2886158).
|
||||
public func %= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: BinaryInteger {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left % right }
|
||||
public func %= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: BinaryInteger {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left % right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.&=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885976).
|
||||
public func &= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: BinaryInteger {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left & right }
|
||||
public func &= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: BinaryInteger {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left & right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.^=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2885182).
|
||||
public func ^= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: BinaryInteger {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left ^ right }
|
||||
public func ^= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: BinaryInteger {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left ^ right }
|
||||
}
|
||||
|
||||
/// See [`BinaryInteger.|=(_:_:)`](https://developer.apple.com/documentation/swift/binaryinteger/2884669).
|
||||
public func |= <T, V1, V2>(lhs: inout Failable<T, V1>, rhs: Failable<T, V2>) where T: BinaryInteger {
|
||||
lhs = Failable<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left | right }
|
||||
public func |= <T, V1, V2>(lhs: inout Validated<T, V1>, rhs: Validated<T, V2>) where T: BinaryInteger {
|
||||
lhs = Validated<T, V1>.map(lhs, rhs) { (left: T, right: T) -> T in left | right }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extension Failable: SIMDStorage where T: SIMDStorage {
|
||||
extension Validated: SIMDStorage where T: SIMDStorage {
|
||||
/// See [`SIMDStorage.Scalar`](https://developer.apple.com/documentation/swift/simdstorage/3140578-scalar)
|
||||
public typealias Scalar = Failable<T.Scalar, EmptyValidation<T.Scalar>>
|
||||
public typealias Scalar = AlwaysValidated<T.Scalar>
|
||||
|
||||
/// See [`SIMDStorage.scalarCount`](https://developer.apple.com/documentation/swift/simdstorage/3140580-scalarcount)
|
||||
public var scalarCount: Int {
|
||||
|
@ -9,7 +9,7 @@ extension Failable: SIMDStorage where T: SIMDStorage {
|
|||
|
||||
/// See [`SIMDStorage.init()`](https://developer.apple.com/documentation/swift/simdstorage/3140579-init).
|
||||
public init() {
|
||||
self = Failable(T())
|
||||
self = Validated(initialValue: T())
|
||||
}
|
||||
|
||||
/// See [`subscript(_:)`](https://developer.apple.com/documentation/swift/simdstorage/3140581-subscript).
|
||||
|
@ -25,7 +25,7 @@ extension Failable: SIMDStorage where T: SIMDStorage {
|
|||
}
|
||||
}
|
||||
|
||||
extension Failable: SIMD where T: SIMD {
|
||||
extension Validated: SIMD where T: SIMD {
|
||||
/// See [`SIMD.MaskStorage`](https://developer.apple.com/documentation/swift/simd/3139486-maskstorage).
|
||||
public typealias MaskStorage = T.MaskStorage
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/// A `Failable` type with a validation that can't fail.
|
||||
public typealias NonFailable<T> = Failable<T, EmptyValidation<T>>
|
||||
public typealias AlwaysValidated<T> = Validated<T, EmptyValidation<T>>
|
||||
|
||||
/// A type that can fail when being set because the new value does pass certain validations.
|
||||
///
|
||||
|
@ -36,91 +36,62 @@ public typealias NonFailable<T> = Failable<T, EmptyValidation<T>>
|
|||
///
|
||||
/// `Dictionary` and `Array` types are not supported for literal initialization yet because array
|
||||
/// splatting for variadic parameters is not supported yet.
|
||||
public struct Failable<T, Validations> where Validations: Validation, Validations.Supported == T {
|
||||
internal private(set) var stored: Result<T, Error>
|
||||
|
||||
init(result: Result<T, Error>) {
|
||||
self.stored = result
|
||||
|
||||
@propertyDelegate
|
||||
public enum Validated<T, Validations> where Validations: Validation, Validations.Supported == T {
|
||||
case value(T)
|
||||
case error(Error)
|
||||
|
||||
public init(by validations: Validations.Type = Validations.self, value: T) {
|
||||
self = Validated(initialValue: value)
|
||||
}
|
||||
|
||||
init(_ error: Error) {
|
||||
self.stored = .failure(error)
|
||||
public init(initialValue: T?) {
|
||||
guard let value = initialValue else {
|
||||
self = .error(ValidationError(
|
||||
identifier: "unexpectedNil",
|
||||
reason: "Cannot iniitialize value of type `\(T.self)` from `nil` value")
|
||||
)
|
||||
return
|
||||
}
|
||||
do {
|
||||
try Validations.run(value)
|
||||
self = .value(value)
|
||||
} catch let error {
|
||||
self = .error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the stored value of the current instance if it exists.
|
||||
///
|
||||
/// Thie property will return `nil` if an error is held instead.
|
||||
///
|
||||
/// You can set the stored value if the `Failable` instance by using this properties setter.
|
||||
/// The value will not be set if `T` is non-optional and `nil` is passed in.
|
||||
public var value: T? {
|
||||
get {
|
||||
guard case let .success(value) = self.stored else { return nil }
|
||||
guard case let .value(value) = self else { return nil }
|
||||
return value
|
||||
}
|
||||
set {
|
||||
if newValue == nil, !_isOptional(T.self) { return }
|
||||
guard let value = newValue else { return }
|
||||
self.stored = Result(catching: {
|
||||
|
||||
do {
|
||||
try Validations.run(value)
|
||||
return value
|
||||
})
|
||||
self = .value(value)
|
||||
} catch let error {
|
||||
self = .error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the error stored in the current instance.
|
||||
///
|
||||
/// This property returns `nil` if a value of type `T` is stored instead.
|
||||
public var error: Error? {
|
||||
guard case let .failure(error) = self.stored else { return nil }
|
||||
return error
|
||||
public func validate()throws -> Validated {
|
||||
guard case let .error(error) = self else {
|
||||
return self
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
/// Creates a new `Failable` instance.
|
||||
///
|
||||
/// - Parameter t: The orginal value for the instance.
|
||||
/// This value will be validated and the initializer will fail if it doesn't pass.
|
||||
public init(_ t: T) {
|
||||
self.stored = Result.init(catching: {
|
||||
try Validations.run(t)
|
||||
return t
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `Failable` instance.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - t: The initial value for the instance.
|
||||
/// - validation: The validation type for the instance.
|
||||
public init(_ t: T, _ validation: Validations.Type) {
|
||||
self.init(t)
|
||||
}
|
||||
|
||||
/// Initialize a new `Failable` instance from an already existing instance.
|
||||
/// This can be useful to specify the types of an ambiguous `Failable` instance.
|
||||
///
|
||||
/// - Parameter failable: The `Failable` instance to initialize with.
|
||||
public init(_ failable: Failable<T, Validations>) {
|
||||
self = failable
|
||||
}
|
||||
|
||||
/// Gets the value stored in the current instance.
|
||||
///
|
||||
/// - Returns: The stored value, of type `T`.
|
||||
/// - Throws: The error stored in the current value.
|
||||
public func get()throws -> T {
|
||||
return try self.stored.get()
|
||||
}
|
||||
|
||||
/// Verified that the current instance contains a value instead of an error.
|
||||
/// If an error is found, it will be thrown.
|
||||
///
|
||||
/// - Returns: Self, if it contains a value value.
|
||||
/// - Throws: The stored `Error` instance.
|
||||
public func verified()throws -> Failable<T, Validations> {
|
||||
switch self.stored {
|
||||
case let .failure(error): throw error
|
||||
case .success: return self
|
||||
switch self {
|
||||
case let .value(value): return value
|
||||
case let .error(error): throw error
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,10 +103,14 @@ public struct Failable<T, Validations> where Validations: Validation, Validation
|
|||
/// - value: The stored value of the current instance that will be converted.
|
||||
///
|
||||
/// - Returns: A new `Failable` instance that uses the value returned by the `transform` closure.
|
||||
public func map<Value, NewValidations>(_ transform: (_ value: T)throws -> Value) -> Failable<Value, NewValidations> {
|
||||
switch self.stored {
|
||||
case let .success(value): return Failable<Value, NewValidations>(result: Result(catching: { try transform(value) }))
|
||||
case let .failure(error): return Failable<Value, NewValidations>(result: .failure(error))
|
||||
public func map<Value, NewValidations>(
|
||||
_ transform: (_ value: T)throws -> Value
|
||||
) -> Validated<Value, NewValidations> {
|
||||
switch self {
|
||||
case let .value(value):
|
||||
do { return try .init(initialValue: transform(value)) }
|
||||
catch { return .error(error) }
|
||||
case let .error(error): return .error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,10 +121,12 @@ public struct Failable<T, Validations> where Validations: Validation, Validation
|
|||
/// - value: The stored value of the current instance to convert.
|
||||
///
|
||||
/// - Returns: A new `Failable` instance with value returned by the `transform` closure.
|
||||
public func map(_ transform: (_ value: T)throws -> T) -> Failable<T, Validations> {
|
||||
switch self.stored {
|
||||
case let .success(value): return Failable(result: Result(catching: { try transform(value) }))
|
||||
case let .failure(error): return Failable(result: .failure(error))
|
||||
public func map(_ transform: (_ value: T)throws -> T) -> Validated<T, Validations> {
|
||||
switch self {
|
||||
case let .value(value):
|
||||
do { return try .init(initialValue: transform(value)) }
|
||||
catch { return .error(error) }
|
||||
case let .error(error): return .error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,16 +139,13 @@ public struct Failable<T, Validations> where Validations: Validation, Validation
|
|||
///
|
||||
/// - Returns: The `Failable` instance that was returned from the `trasnform` closure.
|
||||
public func flatMap<Value, NewValidations>(
|
||||
_ transform: (T)throws -> Failable<Value, NewValidations>
|
||||
) -> Failable<Value, NewValidations> {
|
||||
switch self.stored {
|
||||
case let .success(t):
|
||||
do {
|
||||
return try transform(t)
|
||||
} catch let error {
|
||||
return Failable<Value, NewValidations>(result: .failure(error))
|
||||
}
|
||||
case let .failure(error): return Failable<Value, NewValidations>(result: .failure(error))
|
||||
_ transform: (T)throws -> Validated<Value, NewValidations>
|
||||
) -> Validated<Value, NewValidations> {
|
||||
switch self {
|
||||
case let .value(value):
|
||||
do { return try transform(value) }
|
||||
catch { return .error(error) }
|
||||
case let .error(error): return .error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,61 +156,32 @@ public struct Failable<T, Validations> where Validations: Validation, Validation
|
|||
/// - value: The stored value of the current instance that will be converted.
|
||||
///
|
||||
/// - Returns: The `Failable` instance that was returned from the `trasnform` closure.
|
||||
public func flatMap(_ transform: (_ value: T)throws -> Failable<T, Validations>) -> Failable<T, Validations> {
|
||||
switch self.stored {
|
||||
case let .success(value):
|
||||
do {
|
||||
return try transform(value)
|
||||
} catch let error {
|
||||
return Failable(result: .failure(error))
|
||||
}
|
||||
case let .failure(error): return Failable(result: .failure(error))
|
||||
public func flatMap(_ transform: (_ value: T)throws -> Validated<T, Validations>) -> Validated<T, Validations> {
|
||||
switch self {
|
||||
case let .value(value):
|
||||
do { return try transform(value) }
|
||||
catch { return .error(error) }
|
||||
case let .error(error): return .error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accesses the value of a keypath for the stored value where the stored value type
|
||||
/// and the keypath value type are equivalent.
|
||||
///
|
||||
/// - Parameter path: The keypath of the value to access.
|
||||
/// - Returns: A `Failable` instance with the value of the keypath.
|
||||
public subscript (keyPath path: KeyPath<T, T>) -> Failable<T, Validations> {
|
||||
return self.map { value in value[keyPath: path] }
|
||||
}
|
||||
|
||||
/// Accesses the value of a keypath for the stored value where the stored value type and keypath value type are different.
|
||||
///
|
||||
/// - Parameter path: The keypath of the value to access.
|
||||
/// - Returns: A `Failable` instance with the value of the keypath.
|
||||
public subscript <Value, NewValidations>(keyPath path: KeyPath<T, Value>) -> Failable<Value, NewValidations> {
|
||||
return self.map { value in value[keyPath: path] }
|
||||
}
|
||||
}
|
||||
|
||||
extension Failable {
|
||||
extension Validated {
|
||||
public static func map<A, B, R, AV, BV, RV>(
|
||||
_ left: Failable<A, AV>,
|
||||
_ right: Failable<B, BV>,
|
||||
_ left: Validated<A, AV>,
|
||||
_ right: Validated<B, BV>,
|
||||
closure: (A, B)throws -> R
|
||||
) -> Failable<R, RV> {
|
||||
switch (left.stored, right.stored) {
|
||||
case let (.success(l), .success(r)): return Failable<R, RV>(result: Result(catching: { try closure(l, r) }))
|
||||
case let (.failure(l), .failure(r)): return Failable<R, RV>(ValidationError.foundError(ErrorJoin(l, r)))
|
||||
case let (.success, .failure(error)): return Failable<R, RV>(ValidationError.foundError(error))
|
||||
case let (.failure(error), .success): return Failable<R, RV>(ValidationError.foundError(error))
|
||||
) -> Validated<R, RV> {
|
||||
switch (left, right) {
|
||||
case let (.value(l), .value(r)):
|
||||
do {
|
||||
return try Validated<R, RV>(initialValue: closure(l, r))
|
||||
} catch let error {
|
||||
return .error(error)
|
||||
}
|
||||
case let (.error(l), .error(r)): return .error(ValidationError.foundError(ErrorJoin(l, r)))
|
||||
case let (.value, .error(error)): return .error(ValidationError.foundError(error))
|
||||
case let (.error(error), .value): return .error(ValidationError.foundError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CustomStringConvertible {
|
||||
|
||||
/// Easily create `Failable` versions of types conforming to `CustomStringConvertible`. This includes most, if not all, core Swift types.
|
||||
///
|
||||
/// This paramater defaults to its own type, so if the validation type can be infered, you don't need to pass the paramater in.
|
||||
///
|
||||
/// var story: Failable<String, Length1028> = try "Once upon a time...".failable()
|
||||
///
|
||||
/// - Parameter validations: The validation type to use when mutating the stored value.
|
||||
public func failable<Validations>(_ validations: Validations.Type = Validations.self) -> Failable<Self, Validations> {
|
||||
return Failable(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
infix operator <~: AssignmentPrecedence
|
||||
|
||||
/// Sets the stored value of a `Failable` type.
|
||||
///
|
||||
/// You have to use this operator instead of `=` so the validations always run on the new value before it is assigned.
|
||||
///
|
||||
/// - Complexity: O(n^m), where _n_ is the number of type compatible sub-validations for the `Failable` type's sub-validations
|
||||
/// and _m_ is the depth of the sub-validations.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - root: The `Failable` instance that holds the value to be mutated.
|
||||
/// - value: The new value for the `root.value` property.
|
||||
public func <~ <T, Validations>(root: inout Failable<T, Validations>, value: T) {
|
||||
root.value = value
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
import XCTest
|
||||
@testable import Failable
|
||||
|
||||
final class FailableTests: XCTestCase {
|
||||
func testInit()throws {
|
||||
var story: NonFailable<String> = "Hello world...".failable()
|
||||
XCTAssertEqual(story.value, "Hello world...")
|
||||
|
||||
story = "Long long ago...".failable()
|
||||
XCTAssertEqual(story.value, "Long long ago...")
|
||||
}
|
||||
|
||||
func testSet()throws {
|
||||
var story: NonFailable<String> = "Hello world...".failable()
|
||||
story <~ "Long long ago..."
|
||||
|
||||
XCTAssertEqual(story.value, "Long long ago...")
|
||||
}
|
||||
|
||||
func testKeyPathSubscript()throws {
|
||||
let string = "Hello World"
|
||||
let failable: NonFailable<String> = string.failable()
|
||||
|
||||
XCTAssertEqual(failable[keyPath: \.count], string.count)
|
||||
}
|
||||
|
||||
func testEncode()throws {
|
||||
let data = Failable(["key": "value"], EmptyValidation<[String: String]>.self)
|
||||
let json = try String(data: JSONEncoder().encode(data), encoding: .utf8)
|
||||
|
||||
XCTAssertEqual(json, "{\"key\":\"value\"}")
|
||||
}
|
||||
|
||||
func testDecode()throws {
|
||||
let json = """
|
||||
{
|
||||
"key": "value"
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
let object = try JSONDecoder().decode(NonFailable<[String: String]>.self, from: json)
|
||||
|
||||
XCTAssertEqual(object.value, ["key": "value"])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
@testable import Failable
|
||||
import XCTest
|
||||
|
||||
struct IsTrue: Validation {
|
||||
static func validate(_ value: Bool) throws {
|
||||
guard value else {
|
||||
throw ValidationError(identifier: "expectedTrue", reason: "Bool value must be `true`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Test: Codable, Hashable {
|
||||
@Validated<Bool, IsTrue> var bool: Bool = nil
|
||||
}
|
||||
|
||||
final class PropertyWrapperTests: XCTestCase {
|
||||
func testWrapper() throws {
|
||||
var test = Test()
|
||||
XCTAssertEqual(test.bool, true)
|
||||
|
||||
test.bool = false
|
||||
XCTAssertNotEqual(test.bool, false)
|
||||
}
|
||||
}
|
||||
|
||||
extension Validated {
|
||||
mutating func test(_ newValue: T) throws {
|
||||
self.value = newValue
|
||||
|
||||
switch self {
|
||||
case let .error(error): throw error
|
||||
case .value: return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import XCTest
|
||||
@testable import Failable
|
||||
|
||||
fileprivate struct Data: Codable {
|
||||
@AlwaysValidated<String> var string: String
|
||||
}
|
||||
|
||||
final class ValidatedTests: XCTestCase {
|
||||
func testInit()throws {
|
||||
let story = Data(string: "Hello World...")
|
||||
_ = try story.$string.get()
|
||||
}
|
||||
|
||||
func testSet()throws {
|
||||
var story = Data(string: "Hello World...")
|
||||
_ = try story.$string.get()
|
||||
|
||||
try story.$string.test("Long long ago...")
|
||||
XCTAssertEqual(story.string, "Long long ago...")
|
||||
}
|
||||
|
||||
func testEncode()throws {
|
||||
let data = Data(string: "Hello")
|
||||
let json = try String(data: JSONEncoder().encode(data), encoding: .utf8)
|
||||
|
||||
XCTAssertEqual(json, "{\"string\":\"Hello\"}")
|
||||
}
|
||||
|
||||
func testDecode()throws {
|
||||
let json = """
|
||||
{
|
||||
"string": "hello"
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
let object = try JSONDecoder().decode(Data.self, from: json)
|
||||
|
||||
XCTAssertEqual(object.string, "hello")
|
||||
}
|
||||
}
|
|
@ -13,36 +13,34 @@ internal struct Length1028<C>: LengthValidation where C: Collection {
|
|||
|
||||
static var maxLength: Int { return 1028 }
|
||||
}
|
||||
internal typealias StringLengthArray = ElementValidation<[String], Length1028<String>>
|
||||
|
||||
fileprivate struct Lists {
|
||||
@Validated<[Bool], LengthRange10To1028<[Bool]>> var bools: [Bool]
|
||||
@Validated<[String], ElementValidation<[String], Length1028<String>>> var strings: [String]
|
||||
}
|
||||
|
||||
final class CollectionTests: XCTestCase {
|
||||
func testLengthValidation()throws {
|
||||
try XCTAssertThrowsError(Failable([], LengthRange10To1028<[Bool]>.self).get())
|
||||
var lists = Lists(bools: [], strings: [])
|
||||
_ = try lists.$bools.get()
|
||||
|
||||
try lists.$bools.test([true, true, true, false, false, false, true, true, false, false])
|
||||
try lists.$bools.test(Array(repeating: true, count: 1028))
|
||||
|
||||
var bools = Failable([true, true, true, false, false, false, true, true, false, false], LengthRange10To1028<[Bool]>.self)
|
||||
XCTAssertEqual(bools.value, [true, true, true, false, false, false, true, true, false, false])
|
||||
|
||||
bools <~ Array(repeating: true, count: 5)
|
||||
bools <~ Array(repeating: false, count: 5)
|
||||
bools <~ Array(repeating: true, count: 1029)
|
||||
bools <~ Array(repeating: false, count: 1029)
|
||||
try XCTAssertThrowsError(bools.get())
|
||||
|
||||
let array = Array(repeating: true, count: 1028)
|
||||
bools <~ array
|
||||
XCTAssertEqual(bools.value, array)
|
||||
try XCTAssertThrowsError(lists.$bools.test(Array(repeating: true, count: 5)))
|
||||
try XCTAssertThrowsError(lists.$bools.test(Array(repeating: false, count: 5)))
|
||||
try XCTAssertThrowsError(lists.$bools.test(Array(repeating: true, count: 1029)))
|
||||
try XCTAssertThrowsError(lists.$bools.test(Array(repeating: false, count: 1029)))
|
||||
}
|
||||
|
||||
func testElementValidation()throws {
|
||||
let tooLong = String(repeating: "x", count: 1029)
|
||||
let longest = String(repeating: "g", count: 1028)
|
||||
var strings = Failable<[String], StringLengthArray>(["G", "D", "A", "E"])
|
||||
XCTAssertEqual(strings.value, ["G", "D", "A", "E"])
|
||||
|
||||
strings <~ ["G", "O", "O", tooLong]
|
||||
try XCTAssertThrowsError(strings.get())
|
||||
var lists = Lists(bools: [], strings: ["G", "D", "A", "E"])
|
||||
_ = try lists.$strings.get()
|
||||
|
||||
strings <~ ["G", "OOOO", "World", longest]
|
||||
XCTAssertEqual(strings.value, ["G", "OOOO", "World", longest])
|
||||
let longest = String(repeating: "g", count: 1028)
|
||||
try lists.$strings.test(["G", "OOOO", "World", longest])
|
||||
|
||||
let tooLong = String(repeating: "x", count: 1029)
|
||||
try lists.$strings.test(["G", "O", "O", tooLong])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,44 +20,46 @@ internal struct LessThan: InRangeValidation {
|
|||
static let max: Int? = 9_999
|
||||
}
|
||||
|
||||
fileprivate struct Numbers {
|
||||
@Validated<Int, NumberThousand> var thousands: Int
|
||||
@Validated<Int, GreaterThan> var large: Int
|
||||
@Validated<Int, LessThan> var small: Int
|
||||
}
|
||||
|
||||
final class ComparableTests: XCTestCase {
|
||||
func testNumberThousand()throws {
|
||||
var int = Failable<Int, NumberThousand>(5_000)
|
||||
var numbers = Numbers(thousands: 5_000, large: 0, small: 0)
|
||||
_ = try numbers.$thousands.get()
|
||||
|
||||
try numbers.$thousands.test(9_999)
|
||||
try numbers.$thousands.test(1_000)
|
||||
|
||||
int <~ 9_999
|
||||
int <~ 1_000
|
||||
try XCTAssertNoThrow(int.get())
|
||||
|
||||
int <~ 999
|
||||
int <~ 10_000
|
||||
try XCTAssertThrowsError(int.get())
|
||||
try XCTAssertThrowsError(numbers.$thousands.test(999))
|
||||
try XCTAssertThrowsError(numbers.$thousands.test(10_000))
|
||||
}
|
||||
|
||||
func testGreaterThan()throws {
|
||||
var int = Failable<Int, GreaterThan>(5_000)
|
||||
var numbers = Numbers(thousands: 0, large: 5_000, small: 0)
|
||||
|
||||
int <~ 1_000
|
||||
int <~ 10_000
|
||||
int <~ Int.max
|
||||
try XCTAssertNoThrow(int.get())
|
||||
try numbers.$large.test(1_000)
|
||||
try numbers.$large.test(10_000)
|
||||
try numbers.$large.test(Int.max)
|
||||
|
||||
int <~ 999
|
||||
int <~ 0
|
||||
int <~ Int.min
|
||||
try XCTAssertThrowsError(int.get())
|
||||
try XCTAssertThrowsError(numbers.$large.test(999))
|
||||
try XCTAssertThrowsError(numbers.$large.test(0))
|
||||
try XCTAssertThrowsError(numbers.$large.test(Int.min))
|
||||
}
|
||||
|
||||
func testLessThan()throws {
|
||||
var int = Failable<Int, LessThan>(5_000)
|
||||
var numbers = Numbers(thousands: 0, large: 0, small: 5_000)
|
||||
_ = try numbers.$small.get()
|
||||
|
||||
int <~ 9_999
|
||||
int <~ 999
|
||||
int <~ 0
|
||||
int <~ Int.min
|
||||
try XCTAssertNoThrow(int.get())
|
||||
try numbers.$small.test(9_999)
|
||||
try numbers.$small.test(999)
|
||||
try numbers.$small.test(0)
|
||||
try numbers.$small.test(Int.min)
|
||||
|
||||
int <~ 10_000
|
||||
int <~ Int.max
|
||||
try XCTAssertThrowsError(int.get())
|
||||
try XCTAssertThrowsError(numbers.$small.test(10_000))
|
||||
try XCTAssertThrowsError(numbers.$small.test(Int.max))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,30 +3,32 @@ import XCTest
|
|||
|
||||
typealias OptionalStringLength = NotNilValidate<LengthRange10To1028<String>>
|
||||
|
||||
fileprivate struct Optionals {
|
||||
@Validated<Bool?, NotNil<Bool>> var bool: Bool
|
||||
@Validated<String?, OptionalStringLength> var string: String
|
||||
}
|
||||
|
||||
final class OptionalTests: XCTestCase {
|
||||
func testNotNil()throws {
|
||||
var optional: Failable<Bool?, NotNil<Bool>> = false
|
||||
var optionals = Optionals(bool: false, string: "")
|
||||
_ = try optionals.$bool.get()
|
||||
|
||||
try optionals.$bool.test(true)
|
||||
try optionals.$bool.test(false)
|
||||
|
||||
optional <~ true
|
||||
optional <~ false
|
||||
try XCTAssertNoThrow(optional.get())
|
||||
|
||||
optional <~ nil
|
||||
try XCTAssertThrowsError(optional.get())
|
||||
try XCTAssertThrowsError(optionals.$bool.test(nil))
|
||||
}
|
||||
|
||||
func testNotNilValidate()throws {
|
||||
var optional: Failable<String?, OptionalStringLength> = "Hello World"
|
||||
var optionals = Optionals(bool: true, string: "Hello World")
|
||||
|
||||
optional <~ "Long long ago"
|
||||
optional <~ String(repeating: "x", count: 10)
|
||||
optional <~ String(repeating: "x", count: 1028)
|
||||
optional <~ nil
|
||||
try XCTAssertNoThrow(optional.get())
|
||||
try optionals.$string.test("Long long ago")
|
||||
try optionals.$string.test(String(repeating: "x", count: 10))
|
||||
try optionals.$string.test(String(repeating: "x", count: 1028))
|
||||
try optionals.$string.test(nil)
|
||||
|
||||
optional <~ String(repeating: "x", count: 9)
|
||||
optional <~ String(repeating: "x", count: 1029)
|
||||
try XCTAssertThrowsError(optional.get())
|
||||
try XCTAssertThrowsError(optionals.$string.test(String(repeating: "x", count: 9)))
|
||||
try XCTAssertThrowsError(optionals.$string.test(String(repeating: "x", count: 1029)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,20 +5,23 @@ internal struct USPhoneNumber: RegexValidation {
|
|||
static let pattern = "1?-?\\(?[0-9]{3}\\)?-?[0-9]{3}-?[0-9]{4}"
|
||||
}
|
||||
|
||||
fileprivate struct Number {
|
||||
@Validated<String, USPhoneNumber> var phone: String
|
||||
}
|
||||
|
||||
final class StringTests: XCTestCase {
|
||||
func testUSPhoneNumber()throws {
|
||||
var number: Failable<String, USPhoneNumber> = "731-943-4316".failable()
|
||||
var number = Number(phone: "731-943-4316")
|
||||
_ = try number.$phone.get()
|
||||
|
||||
number <~ "(731)-943-4316"
|
||||
number <~ "1-731-943-4316"
|
||||
number <~ "7319434316"
|
||||
try XCTAssertNoThrow(number.get())
|
||||
try number.$phone.test("(731)-943-4316")
|
||||
try number.$phone.test("1-731-943-4316")
|
||||
try number.$phone.test("7319434316")
|
||||
|
||||
number <~ ""
|
||||
number <~ "943-4316"
|
||||
number <~ "1-800-EAT-MEAT"
|
||||
number <~ "4316-943-731"
|
||||
try XCTAssertThrowsError(number.get())
|
||||
XCTAssertThrowsError(try number.$phone.test(""))
|
||||
XCTAssertThrowsError(try number.$phone.test("943-4316"))
|
||||
XCTAssertThrowsError(try number.$phone.test("1-800-EAT-MEAT"))
|
||||
XCTAssertThrowsError(try number.$phone.test("4316-943-731"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue