@@ -10,20 +10,16 @@ import GoodExtensions
1010
1111// MARK: - Validation errors
1212
13- public protocol ValidationError : Error , Equatable {
14-
15- var localizedDescription : String { get }
16-
17- }
13+ public protocol ValidationError : LocalizedError { }
1814
1915public enum InternalValidationError : ValidationError {
2016
2117 case alwaysError
2218 case required
2319 case mismatch
24- case external( String )
20+ case external( MainSupplier < String > )
2521
26- public var localizedDescription : String {
22+ public var errorDescription : String ? {
2723 switch self {
2824 case . alwaysError:
2925 " Error "
@@ -35,7 +31,9 @@ public enum InternalValidationError: ValidationError {
3531 " Elements do not match "
3632
3733 case . external( let description) :
38- description
34+ MainActor . assumeIsolated {
35+ description ( )
36+ }
3937 }
4038 }
4139
@@ -46,18 +44,18 @@ public enum InternalValidationError: ValidationError {
4644public extension Criterion {
4745
4846 /// Always succeeds
49- nonisolated static let alwaysValid = Criterion { _ in true }
47+ static let alwaysValid = Criterion { _ in true }
5048
5149 /// Always fails
52- nonisolated static let alwaysError = Criterion { _ in false }
50+ static let alwaysError = Criterion { _ in false }
5351 . failWith ( error: InternalValidationError . alwaysError)
5452
5553 /// Accepts any input with length > 0, excluding leading/trailing whitespace
56- nonisolated static let nonEmpty = Criterion { !( $0 ?? " " ) . trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty }
54+ static let nonEmpty = Criterion { !( $0 ?? " " ) . trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty }
5755 . failWith ( error: InternalValidationError . required)
5856
5957 /// Accepts an input if it is equal with another input
60- nonisolated static func matches( _ other: String ? ) -> Criterion {
58+ static func matches( _ other: String ? ) -> Criterion {
6159 Criterion { this in this == other }
6260 . failWith ( error: InternalValidationError . mismatch)
6361 }
@@ -69,14 +67,14 @@ public extension Criterion {
6967 ///
7068 /// If input is empty, validation **succeeds** and input is deemed valid.
7169 /// If input is non-empty, validation continues by criterion specified as a parameter.
72- nonisolated static func acceptEmpty( _ criterion: Criterion ) -> Criterion {
70+ static func acceptEmpty( _ criterion: Criterion ) -> Criterion {
7371 Criterion { Criterion . nonEmpty. validate ( input: $0) ? criterion. validate ( input: $0) : true }
7472 . failWith ( error: criterion. error)
7573 }
7674
77- nonisolated static func external( error: @autoclosure @escaping Supplier < ( any Error ) ? > ) -> Criterion {
75+ static func external( error: @MainActor @escaping ( ) -> ( any LocalizedError ) ? ) -> Criterion {
7876 Criterion { _ in error ( ) . isNil }
79- . failWith ( error: InternalValidationError . external ( error ( ) ? . localizedDescription ?? " " ) )
77+ . failWith ( error: InternalValidationError . external { error ( ) ? . localizedDescription ?? " " } )
8078 }
8179
8280}
0 commit comments