medmap-ios/medmap/Models/APIError.swift
2026-08-27 23:26:14 +01:00

111 lines
3.6 KiB
Swift

// Copyright © 2025 VOID Software SA. All rights reserved.
import Foundation
/// Custom error types for API operations
enum APIError: Error, LocalizedError, Equatable {
case invalidURL
case noData
case decodingFailed(Error)
case encodingFailed(Error)
case unauthorized
case forbidden
case notFound
case serverError(statusCode: Int)
case networkError(Error)
case unexpectedResponse
case timeout
case cancelled
case custom(String)
var errorDescription: String? {
switch self {
case .invalidURL:
return "Invalid URL"
case .noData:
return "No data received from server"
case .decodingFailed(let error):
return "Failed to decode response: \(error.localizedDescription)"
case .encodingFailed(let error):
return "Failed to encode parameters: \(error.localizedDescription)"
case .unauthorized:
return "Unauthorized. Please login again."
case .forbidden:
return "Access forbidden"
case .notFound:
return "Resource not found"
case .serverError(let statusCode):
return "Server error (Status: \(statusCode))"
case .networkError(let error):
return "Network error: \(error.localizedDescription)"
case .unexpectedResponse:
return "Unexpected response from server"
case .timeout:
return "Request timeout"
case .cancelled:
return "Request cancelled"
case .custom(let message):
return message
}
}
static func == (lhs: APIError, rhs: APIError) -> Bool {
switch (lhs, rhs) {
case (.invalidURL, .invalidURL),
(.noData, .noData),
(.unauthorized, .unauthorized),
(.forbidden, .forbidden),
(.notFound, .notFound),
(.unexpectedResponse, .unexpectedResponse),
(.timeout, .timeout),
(.cancelled, .cancelled):
return true
case (.serverError(let lhsCode), .serverError(let rhsCode)):
return lhsCode == rhsCode
case (.custom(let lhsMessage), .custom(let rhsMessage)):
return lhsMessage == rhsMessage
case (.decodingFailed(let lhsError), .decodingFailed(let rhsError)):
return lhsError.localizedDescription == rhsError.localizedDescription
case (.encodingFailed(let lhsError), .encodingFailed(let rhsError)):
return lhsError.localizedDescription == rhsError.localizedDescription
case (.networkError(let lhsError), .networkError(let rhsError)):
return lhsError.localizedDescription == rhsError.localizedDescription
default:
return false
}
}
}
/// Detailed server error with request/response information
struct ServerError: Error, LocalizedError {
let statusCode: Int?
let message: String?
let data: Data?
let request: URLRequest?
let response: HTTPURLResponse?
var errorDescription: String? {
if let message = message {
return message
}
if let statusCode = statusCode {
return "Server error: \(statusCode)"
}
return "Unknown server error"
}
init(
statusCode: Int? = nil,
message: String? = nil,
data: Data? = nil,
request: URLRequest? = nil,
response: HTTPURLResponse? = nil
) {
self.statusCode = statusCode
self.message = message
self.data = data
self.request = request
self.response = response
}
}