TeraUserMessageClassifier.swift (8246B)
1 import Foundation 2 import RadrootsKit 3 4 enum TeraUserMessageClassifier { 5 static func key( 6 for error: Error, 7 fallback: TeraUserMessageKey 8 ) -> TeraUserMessageKey { 9 runtimeKey(for: error, fallback: fallback) 10 ?? platformKey(for: error) 11 ?? identityCustodyKey(for: error) 12 ?? fallback 13 } 14 15 private static func runtimeKey( 16 for error: Error, 17 fallback: TeraUserMessageKey 18 ) -> TeraUserMessageKey? { 19 if error is CancellationError { 20 return .operationOutcomeUnknown 21 } 22 if let error = error as? TeraRuntimeClientError { 23 return runtimeClientKey(error, fallback: fallback) 24 } 25 if let failure = error as? TeraRuntimeFailure { 26 return failure.messageKey(fallback: fallback) 27 } 28 if error is TeraConfigurationError { 29 return .configurationInvalid 30 } 31 if error is TeraIdentityStoreError { 32 return .identityOperationFailed 33 } 34 return nil 35 } 36 37 private static func identityCustodyKey(for error: Error) -> TeraUserMessageKey? { 38 error is RadrootsIdentityCustodyError ? .secureStateUnavailable : nil 39 } 40 41 private static func platformKey(for error: Error) -> TeraUserMessageKey? { 42 if let error = error as? RadrootsCaptureIntakeError { 43 return captureKey(error) 44 } 45 if let error = error as? RadrootsBackgroundTransferError { 46 return backgroundTransferKey(error) 47 } 48 if let error = error as? RadrootsDocumentInterchangeError { 49 return documentKey(error) 50 } 51 if let error = error as? RadrootsAppLocalStateResetError { 52 return localStateResetKey(error) 53 } 54 if let error = error as? RadrootsAppleMediaPreparationError { 55 return mediaPreparationKey(error) 56 } 57 return secondaryPlatformKey(for: error) 58 } 59 60 private static func secondaryPlatformKey( 61 for error: Error 62 ) -> TeraUserMessageKey? { 63 if let error = error as? RadrootsTelemetryError { 64 return telemetryKey(error) 65 } 66 if let error = error as? RadrootsExternalActionError { 67 return externalActionKey(error) 68 } 69 if let error = error as? RadrootsAppleFileError { 70 return fileKey(error) 71 } 72 if let error = error as? RadrootsLocationServicesError { 73 return locationKey(error) 74 } 75 if let error = error as? RadrootsUserPresenceError { 76 return userPresenceKey(error) 77 } 78 return tertiaryPlatformKey(for: error) 79 } 80 81 private static func tertiaryPlatformKey( 82 for error: Error 83 ) -> TeraUserMessageKey? { 84 if let error = error as? RadrootsBackgroundTaskError { 85 return backgroundTaskKey(error) 86 } 87 if let error = error as? RadrootsAppleSecurityError { 88 return securityKey(error) 89 } 90 if let error = error as? RadrootsAppleMobileStoreError { 91 return mobileStoreKey(error) 92 } 93 if let error = error as? RadrootsVerifiedArtifactAccessError { 94 return verifiedArtifactKey(error) 95 } 96 return nil 97 } 98 99 private static func runtimeClientKey( 100 _ error: TeraRuntimeClientError, 101 fallback: TeraUserMessageKey 102 ) -> TeraUserMessageKey { 103 switch error { 104 case .invalidBufferCapacity: .invalidRequest 105 case .notRunning: .runtimeUnavailable 106 case .superseded: .operationOutcomeUnknown 107 case let .startup(failure): failure.messageKey(fallback: .startupFailed) 108 case let .subscription(failure): failure.messageKey(fallback: .runtimeObservationUnavailable) 109 case let .shutdown(failure): failure.messageKey(fallback: .shutdownFailed) 110 case let .status(failure), let .today(failure), let .add(failure), let .support(failure): 111 failure.messageKey(fallback: fallback) 112 } 113 } 114 115 private static func captureKey( 116 _ error: RadrootsCaptureIntakeError 117 ) -> TeraUserMessageKey { 118 switch error { 119 case .invalidRequest: .invalidRequest 120 case .spaceInsufficient: .storageFull 121 case .unavailable: .addMediaUnavailable 122 case .permissionDenied: .permissionDenied 123 case .userCancelled: .operationCancelled 124 case .transientFailure: .tryAgain 125 case .permanentFailure: .addMediaUnavailable 126 } 127 } 128 129 private static func backgroundTransferKey( 130 _ error: RadrootsBackgroundTransferError 131 ) -> TeraUserMessageKey { 132 switch error { 133 case .invalidRequest: .invalidRequest 134 case .unavailable: .backgroundTransferUnavailable 135 case .transferFailure: .backgroundTransferFailed 136 case .persistenceFailure: .secureStateUnavailable 137 case .spaceInsufficient: .storageFull 138 case .receiptCapacityExceeded: .receiptCapacityExceeded 139 } 140 } 141 142 private static func documentKey( 143 _ error: RadrootsDocumentInterchangeError 144 ) -> TeraUserMessageKey { 145 switch error { 146 case .invalidRequest: .invalidRequest 147 case .notFound: .fileOperationFailed 148 case .userCancelled: .operationCancelled 149 case .permissionDenied: .permissionDenied 150 case .transientFailure: .tryAgain 151 case .permanentFailure: .fileOperationFailed 152 } 153 } 154 155 private static func localStateResetKey( 156 _ error: RadrootsAppLocalStateResetError 157 ) -> TeraUserMessageKey { 158 switch error { 159 case .invalidRequest: .invalidRequest 160 case .fileSystemFailure, .keychainFailure: .secureStateUnavailable 161 } 162 } 163 164 private static func mediaPreparationKey( 165 _ error: RadrootsAppleMediaPreparationError 166 ) -> TeraUserMessageKey { 167 switch error { 168 case .invalidRequest: .invalidRequest 169 case .unavailable, .preparationFailure: .addMediaUnavailable 170 } 171 } 172 173 private static func telemetryKey( 174 _ error: RadrootsTelemetryError 175 ) -> TeraUserMessageKey { 176 switch error { 177 case .invalidRequest: .invalidRequest 178 } 179 } 180 181 private static func externalActionKey( 182 _ error: RadrootsExternalActionError 183 ) -> TeraUserMessageKey { 184 switch error { 185 case .invalidRequest: .invalidRequest 186 case .blockedByPolicy, .unavailable: .permissionDenied 187 case .transientFailure: .tryAgain 188 case .permanentFailure: .runtimeOperationFailed 189 } 190 } 191 192 private static func fileKey( 193 _ error: RadrootsAppleFileError 194 ) -> TeraUserMessageKey { 195 switch error { 196 case .spaceInsufficient: .storageFull 197 case .invalidRequest: .invalidRequest 198 case .notFound, .permanentFailure: .fileOperationFailed 199 case .permissionDenied: .permissionDenied 200 case .transientFailure: .tryAgain 201 } 202 } 203 204 private static func locationKey( 205 _ error: RadrootsLocationServicesError 206 ) -> TeraUserMessageKey { 207 switch error { 208 case .invalidRequest: .invalidRequest 209 case .permissionDenied: .permissionDenied 210 case .unavailable, .timeout, .cancelled, .transientFailure, .permanentFailure: 211 .locationUnavailable 212 } 213 } 214 215 private static func userPresenceKey( 216 _ error: RadrootsUserPresenceError 217 ) -> TeraUserMessageKey { 218 switch error { 219 case .invalidRequest: .invalidRequest 220 case .userCancelled: .operationCancelled 221 case .permissionDenied: .permissionDenied 222 case .unavailable, .timeout, .transientFailure, .permanentFailure: 223 .userPresenceUnavailable 224 } 225 } 226 227 private static func backgroundTaskKey( 228 _ error: RadrootsBackgroundTaskError 229 ) -> TeraUserMessageKey { 230 switch error { 231 case .invalidRequest: .invalidRequest 232 case .unavailable, .schedulerFailure: .runtimeUnavailable 233 } 234 } 235 236 private static func securityKey( 237 _ error: RadrootsAppleSecurityError 238 ) -> TeraUserMessageKey { 239 switch error { 240 case .invalidRequest: .invalidRequest 241 case .permissionDenied: .permissionDenied 242 case .userCancelled: .operationCancelled 243 case .notFound, .transientFailure, .unavailable, .permanentFailure, 244 .keychainFailure: 245 .secureStateUnavailable 246 } 247 } 248 249 private static func mobileStoreKey( 250 _ error: RadrootsAppleMobileStoreError 251 ) -> TeraUserMessageKey { 252 switch error { 253 case .invalidPublicKey: .invalidRequest 254 case .protectedDataUnavailable, .invalidDirectoryLayout, .fileSystemFailure: 255 .secureStateUnavailable 256 } 257 } 258 259 private static func verifiedArtifactKey( 260 _ error: RadrootsVerifiedArtifactAccessError 261 ) -> TeraUserMessageKey { 262 switch error { 263 case .invalidDescriptor: .invalidRequest 264 case .protectedDataUnavailable: .secureStateUnavailable 265 case .artifactUnavailable, .artifactCorrupt, .fileSystemFailure: 266 .fileOperationFailed 267 } 268 } 269 }