Skip to content

Commit

Permalink
[skip ci] Nesting the result and the output type into ValidatingPrope…
Browse files Browse the repository at this point in the history
…rty.
  • Loading branch information
andersio committed Jun 10, 2017
1 parent 6f15906 commit 8bfb00d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 64 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# master
*Please add new entries at the top.*

1. `ValidationResult` and `ValidatorOutput` have been renamed to `ValidatingProperty.Result` and `ValidatingProperty.Decision`, respectively. (#xxxx)

# 2.0.0-alpha.2
1. In Swift 3.2 or later, you can use `map()` with the new Smart Key Paths. (#435, kudos to @sharplet)

Expand Down
6 changes: 6 additions & 0 deletions Sources/Deprecations+Removals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ public protocol BindingTargetProtocol {}
public protocol AtomicProtocol {}

// MARK: Deprecated types in ReactiveSwift 1.x.
@available(*, unavailable, renamed:"ValidationProperty.Result")
public typealias ValidationResult<Value, Error: Swift.Error> = ValidatingProperty<Value, Error>.Result

@available(*, unavailable, renamed:"ValidationProperty.Decision")
public typealias ValidatorOutput<Value, Error: Swift.Error> = ValidatingProperty<Value, Error>.Decision

extension Signal where Value == Bool {
@available(*, unavailable, renamed: "negate()")
public var negated: Signal<Bool, Error> {
Expand Down
126 changes: 63 additions & 63 deletions Sources/ValidatingProperty.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
private let setter: (Value) -> Void

/// The result of the last attempted edit of the root property.
public let result: Property<ValidationResult<Value, ValidationError>>
public let result: Property<Result>

/// The current value of the property.
///
Expand Down Expand Up @@ -59,7 +59,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
/// - validator: The closure to invoke for any proposed value to `self`.
public init<Inner: ComposableMutablePropertyProtocol>(
_ inner: Inner,
_ validator: @escaping (Value) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value) -> Decision
) where Inner.Value == Value {
getter = { inner.value }
producer = inner.producer
Expand All @@ -71,18 +71,18 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
var isSettingInnerValue = false

(result, setter) = inner.withValue { initial in
let mutableResult = MutableProperty(ValidationResult(initial, validator(initial)))
let mutableResult = MutableProperty(Result(initial, validator(initial)))

mutableResult <~ inner.signal
.filter { _ in !isSettingInnerValue }
.map { ValidationResult($0, validator($0)) }
.map { Result($0, validator($0)) }

return (Property(capturing: mutableResult), { input in
// Acquire the lock of `inner` to ensure no modification happens until
// the validation logic here completes.
inner.withValue { _ in
let writebackValue: Value? = mutableResult.modify { result in
result = ValidationResult(input, validator(input))
result = Result(input, validator(input))
return result.value
}

Expand All @@ -108,7 +108,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
/// - validator: The closure to invoke for any proposed value to `self`.
public convenience init(
_ initial: Value,
_ validator: @escaping (Value) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value) -> Decision
) {
self.init(MutableProperty(initial), validator)
}
Expand All @@ -128,7 +128,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
public convenience init<Other: PropertyProtocol>(
_ inner: MutableProperty<Value>,
with other: Other,
_ validator: @escaping (Value, Other.Value) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value, Other.Value) -> Decision
) {
// Capture a copy that reflects `other` without influencing the lifetime of
// `other`.
Expand Down Expand Up @@ -173,7 +173,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
public convenience init<Other: PropertyProtocol>(
_ initial: Value,
with other: Other,
_ validator: @escaping (Value, Other.Value) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value, Other.Value) -> Decision
) {
self.init(MutableProperty(initial), with: other, validator)
}
Expand All @@ -193,7 +193,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
public convenience init<U, E>(
_ inner: MutableProperty<Value>,
with other: ValidatingProperty<U, E>,
_ validator: @escaping (Value, U) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value, U) -> Decision
) {
self.init(inner, with: other, validator)
}
Expand All @@ -212,7 +212,7 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
public convenience init<U, E>(
_ initial: Value,
with other: ValidatingProperty<U, E>,
_ validator: @escaping (Value, U) -> ValidatorOutput<Value, ValidationError>
_ validator: @escaping (Value, U) -> Decision
) {
// Capture only `other.result` but not `other`.
let otherValidations = other.result
Expand Down Expand Up @@ -254,74 +254,74 @@ public final class ValidatingProperty<Value, ValidationError: Swift.Error>: Muta
}
}
}
}

/// Represents a decision of a validator of a validating property made on a
/// proposed value.
public enum ValidatorOutput<Value, Error: Swift.Error> {
/// The proposed value is valid.
case valid
/// Represents a decision of a validator of a validating property made on a
/// proposed value.
public enum Decision {
/// The proposed value is valid.
case valid

/// The proposed value is invalid, but the validator coerces it into a
/// replacement which it deems valid.
case coerced(Value, Error?)
/// The proposed value is invalid, but the validator coerces it into a
/// replacement which it deems valid.
case coerced(Value, ValidationError?)

/// The proposed value is invalid.
case invalid(Error)
}
/// The proposed value is invalid.
case invalid(ValidationError)
}

/// Represents the result of the validation performed by a validating property.
public enum ValidationResult<Value, Error: Swift.Error> {
/// The proposed value is valid.
case valid(Value)
/// Represents the result of the validation performed by a validating property.
public enum Result {
/// The proposed value is valid.
case valid(Value)

/// The proposed value is invalid, but the validator was able to coerce it
/// into a replacement which it deemed valid.
case coerced(replacement: Value, proposed: Value, error: Error?)
/// The proposed value is invalid, but the validator was able to coerce it
/// into a replacement which it deemed valid.
case coerced(replacement: Value, proposed: Value, error: ValidationError?)

/// The proposed value is invalid.
case invalid(Value, Error)
/// The proposed value is invalid.
case invalid(Value, ValidationError)

/// Whether the value is invalid.
public var isInvalid: Bool {
if case .invalid = self {
return true
} else {
return false
/// Whether the value is invalid.
public var isInvalid: Bool {
if case .invalid = self {
return true
} else {
return false
}
}
}

/// Extract the valid value, or `nil` if the value is invalid.
public var value: Value? {
switch self {
case let .valid(value):
return value
case let .coerced(value, _, _):
return value
case .invalid:
return nil
/// Extract the valid value, or `nil` if the value is invalid.
public var value: Value? {
switch self {
case let .valid(value):
return value
case let .coerced(value, _, _):
return value
case .invalid:
return nil
}
}
}

/// Extract the error if the value is invalid.
public var error: Error? {
if case let .invalid(_, error) = self {
return error
} else {
return nil
/// Extract the error if the value is invalid.
public var error: ValidationError? {
if case let .invalid(_, error) = self {
return error
} else {
return nil
}
}
}

fileprivate init(_ value: Value, _ output: ValidatorOutput<Value, Error>) {
switch output {
case .valid:
self = .valid(value)
fileprivate init(_ value: Value, _ decision: Decision) {
switch decision {
case .valid:
self = .valid(value)

case let .coerced(replacement, error):
self = .coerced(replacement: replacement, proposed: value, error: error)
case let .coerced(replacement, error):
self = .coerced(replacement: replacement, proposed: value, error: error)

case let .invalid(error):
self = .invalid(value, error)
case let .invalid(error):
self = .invalid(value, error)
}
}
}
}
2 changes: 1 addition & 1 deletion Tests/ReactiveSwiftTests/ValidatingPropertySpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ private enum FlattenedResult<Value: Equatable>: Equatable {
case valid(Value)
case coerced(Value, Value, TestError?)

init(_ result: ValidationResult<Value, TestError>) {
init(_ result: ValidatingProperty<Value, TestError>.Result) {
switch result {
case let .valid(value):
self = .valid(value)
Expand Down

0 comments on commit 8bfb00d

Please sign in to comment.