diff --git a/Sources/CassandraClient/Errors.swift b/Sources/CassandraClient/Errors.swift index 11754da..b00b4c2 100644 --- a/Sources/CassandraClient/Errors.swift +++ b/Sources/CassandraClient/Errors.swift @@ -20,6 +20,41 @@ extension CassandraClient { private enum Code: Equatable { case rowsExhausted case disconnected + + // lib errors + case badParams(String) + case noStreams(String) + case unableToInit(String) + case messageEncode(String) + case hostResolution(String) + case unexpectedResponse(String) + case requestQueueFull(String) + case noAvailableIOThread(String) + case writeError(String) + case noHostsAvailable(String) + case indexOutOfBounds(String) + case invalidItemCount(String) + case invalidValueType(String) + case requestTimedOut(String) + case unableToSetKeyspace(String) + case callbackAlreadySet(String) + case invalidStatementType(String) + case nameDoesNotExist(String) + case unableToDetermineProtocol(String) + case nullValue(String) + case notImplemented(String) + case unableToConnect(String) + case unableToClose(String) + case noPagingState(String) + case parameterUnset(String) + case invalidErrorResultType(String) + case invalidFutureType(String) + case internalError(String) + case invalidCustomType(String) + case invalidData(String) + case notEnoughData(String) + case invalidState(String) + case noCustomPayload(String) // server errors case serverError(String) case protocolError(String) @@ -39,6 +74,14 @@ extension CassandraClient { case serverConfigError(String) case alreadyExists(String) case unprepared(String) + // ssl errors + case sslInvalidCert(String) + case sslInvalidPrivateKey(String) + case sslNoPeerCert(String) + case sslInvalidPeerCert(String) + case sslIdentityMismatch(String) + case sslProtocolError(String) + case sslClosed(String) // catch all case other(code: UInt32, description: String?) } @@ -61,6 +104,72 @@ extension CassandraClient { init(_ error: CassError, message: String? = .none) { let message = message ?? "" switch error { + case CASS_ERROR_LIB_BAD_PARAMS: + self = .badParams(message) + case CASS_ERROR_LIB_NO_STREAMS: + self = .noStreams(message) + case CASS_ERROR_LIB_UNABLE_TO_INIT: + self = .unableToInit(message) + case CASS_ERROR_LIB_MESSAGE_ENCODE: + self = .messageEncode(message) + case CASS_ERROR_LIB_HOST_RESOLUTION: + self = .hostResolution(message) + case CASS_ERROR_LIB_UNEXPECTED_RESPONSE: + self = .unexpectedResponse(message) + case CASS_ERROR_LIB_REQUEST_QUEUE_FULL: + self = .requestQueueFull(message) + case CASS_ERROR_LIB_NO_AVAILABLE_IO_THREAD: + self = .noAvailableIOThread(message) + case CASS_ERROR_LIB_WRITE_ERROR: + self = .writeError(message) + case CASS_ERROR_LIB_NO_HOSTS_AVAILABLE: + self = .noHostsAvailable(message) + case CASS_ERROR_LIB_INDEX_OUT_OF_BOUNDS: + self = .indexOutOfBounds(message) + case CASS_ERROR_LIB_INVALID_ITEM_COUNT: + self = .invalidItemCount(message) + case CASS_ERROR_LIB_INVALID_VALUE_TYPE: + self = .invalidValueType(message) + case CASS_ERROR_LIB_REQUEST_TIMED_OUT: + self = .requestTimedOut(message) + case CASS_ERROR_LIB_UNABLE_TO_SET_KEYSPACE: + self = .unableToSetKeyspace(message) + case CASS_ERROR_LIB_CALLBACK_ALREADY_SET: + self = .callbackAlreadySet(message) + case CASS_ERROR_LIB_INVALID_STATEMENT_TYPE: + self = .invalidStatementType(message) + case CASS_ERROR_LIB_NAME_DOES_NOT_EXIST: + self = .nameDoesNotExist(message) + case CASS_ERROR_LIB_UNABLE_TO_DETERMINE_PROTOCOL: + self = .unableToDetermineProtocol(message) + case CASS_ERROR_LIB_NULL_VALUE: + self = .nullValue(message) + case CASS_ERROR_LIB_NOT_IMPLEMENTED: + self = .notImplemented(message) + case CASS_ERROR_LIB_UNABLE_TO_CONNECT: + self = .unableToConnect(message) + case CASS_ERROR_LIB_UNABLE_TO_CLOSE: + self = .unableToClose(message) + case CASS_ERROR_LIB_NO_PAGING_STATE: + self = .noPagingState(message) + case CASS_ERROR_LIB_PARAMETER_UNSET: + self = .parameterUnset(message) + case CASS_ERROR_LIB_INVALID_ERROR_RESULT_TYPE: + self = .invalidErrorResultType(message) + case CASS_ERROR_LIB_INVALID_FUTURE_TYPE: + self = .invalidFutureType(message) + case CASS_ERROR_LIB_INTERNAL_ERROR: + self = .internalError(message) + case CASS_ERROR_LIB_INVALID_CUSTOM_TYPE: + self = .invalidCustomType(message) + case CASS_ERROR_LIB_INVALID_DATA: + self = .invalidData(message) + case CASS_ERROR_LIB_NOT_ENOUGH_DATA: + self = .notEnoughData(message) + case CASS_ERROR_LIB_INVALID_STATE: + self = .invalidState(message) + case CASS_ERROR_LIB_NO_CUSTOM_PAYLOAD: + self = .noCustomPayload(message) case CASS_ERROR_SERVER_SERVER_ERROR: self = .serverError(message) case CASS_ERROR_SERVER_PROTOCOL_ERROR: @@ -97,72 +206,23 @@ extension CassandraClient { self = .alreadyExists(message) case CASS_ERROR_SERVER_UNPREPARED: self = .unprepared(message) + case CASS_ERROR_SSL_INVALID_CERT: + self = .sslInvalidCert(message) + case CASS_ERROR_SSL_INVALID_PRIVATE_KEY: + self = .sslInvalidPrivateKey(message) + case CASS_ERROR_SSL_NO_PEER_CERT: + self = .sslNoPeerCert(message) + case CASS_ERROR_SSL_INVALID_PEER_CERT: + self = .sslInvalidPeerCert(message) + case CASS_ERROR_SSL_IDENTITY_MISMATCH: + self = .sslIdentityMismatch(message) + case CASS_ERROR_SSL_PROTOCOL_ERROR: + self = .sslProtocolError(message) + case CASS_ERROR_SSL_CLOSED: + self = .sslClosed(message) default: self = .other(code: error.rawValue, description: message) } - - // FIXME: map rest of errors - /* - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_BAD_PARAMS, 1, "Bad parameters") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NO_STREAMS, 2, "No streams available") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNABLE_TO_INIT, 3, "Unable to initialize") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_MESSAGE_ENCODE, 4, "Unable to encode message") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_HOST_RESOLUTION, 5, "Unable to resolve host") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNEXPECTED_RESPONSE, 6, "Unexpected response from server") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_REQUEST_QUEUE_FULL, 7, "The request queue is full") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NO_AVAILABLE_IO_THREAD, 8, "No available IO threads") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_WRITE_ERROR, 9, "Write error") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NO_HOSTS_AVAILABLE, 10, "No hosts available") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INDEX_OUT_OF_BOUNDS, 11, "Index out of bounds") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_ITEM_COUNT, 12, "Invalid item count") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_VALUE_TYPE, 13, "Invalid value type") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_REQUEST_TIMED_OUT, 14, "Request timed out") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNABLE_TO_SET_KEYSPACE, 15, "Unable to set keyspace") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_CALLBACK_ALREADY_SET, 16, "Callback already set") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_STATEMENT_TYPE, 17, "Invalid statement type") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NAME_DOES_NOT_EXIST, 18, "No value or column for name") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNABLE_TO_DETERMINE_PROTOCOL, 19, "Unable to find supported protocol version") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NULL_VALUE, 20, "NULL value specified") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NOT_IMPLEMENTED, 21, "Not implemented") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNABLE_TO_CONNECT, 22, "Unable to connect") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_UNABLE_TO_CLOSE, 23, "Unable to close") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NO_PAGING_STATE, 24, "No paging state") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_PARAMETER_UNSET, 25, "Parameter unset") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_ERROR_RESULT_TYPE, 26, "Invalid error result type") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_FUTURE_TYPE, 27, "Invalid future type") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INTERNAL_ERROR, 28, "Internal error") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_CUSTOM_TYPE, 29, "Invalid custom type") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_DATA, 30, "Invalid data") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NOT_ENOUGH_DATA, 31, "Not enough data") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_INVALID_STATE, 32, "Invalid state") \ - XX(CASS_ERROR_SOURCE_LIB, CASS_ERROR_LIB_NO_CUSTOM_PAYLOAD, 33, "No custom payload") \ - - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_SERVER_ERROR, 0x0000, "Server error") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_PROTOCOL_ERROR, 0x000A, "Protocol error") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_BAD_CREDENTIALS, 0x0100, "Bad credentials") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_UNAVAILABLE, 0x1000, "Unavailable") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_OVERLOADED, 0x1001, "Overloaded") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_IS_BOOTSTRAPPING, 0x1002, "Is bootstrapping") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_TRUNCATE_ERROR, 0x1003, "Truncate error") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_WRITE_TIMEOUT, 0x1100, "Write timeout") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_READ_TIMEOUT, 0x1200, "Read timeout") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_READ_FAILURE, 0x1300, "Read failure") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_FUNCTION_FAILURE, 0x1400, "Function failure") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_WRITE_FAILURE, 0x1500, "Write failure") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_SYNTAX_ERROR, 0x2000, "Syntax error") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_UNAUTHORIZED, 0x2100, "Unauthorized") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_INVALID_QUERY, 0x2200, "Invalid query") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_CONFIG_ERROR, 0x2300, "Configuration error") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_ALREADY_EXISTS, 0x2400, "Already exists") \ - XX(CASS_ERROR_SOURCE_SERVER, CASS_ERROR_SERVER_UNPREPARED, 0x2500, "Unprepared") \ - - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_INVALID_CERT, 1, "Unable to load certificate") \ - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_INVALID_PRIVATE_KEY, 2, "Unable to load private key") \ - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_NO_PEER_CERT, 3, "No peer certificate") \ - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_INVALID_PEER_CERT, 4, "Invalid peer certificate") \ - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_IDENTITY_MISMATCH, 5, "Certificate does not match host or IP address") \ - XX(CASS_ERROR_SOURCE_SSL, CASS_ERROR_SSL_PROTOCOL_ERROR, 6, "Protocol error") - */ } public var description: String { @@ -171,6 +231,72 @@ extension CassandraClient { return "Rows exhausted" case .disconnected: return "Disconnected" + case .badParams(let description): + return "Bad parameters: \(description)" + case .noStreams(let description): + return "No streams available: \(description)" + case .unableToInit(let description): + return "Unable to initialize: \(description)" + case .messageEncode(let description): + return "Unable to encode message: \(description)" + case .hostResolution(let description): + return "Unable to resolve host: \(description)" + case .unexpectedResponse(let description): + return "Unexpected response from server: \(description)" + case .requestQueueFull(let description): + return "The request queue is full: \(description)" + case .noAvailableIOThread(let description): + return "No available IO threads: \(description)" + case .writeError(let description): + return "Write error: \(description)" + case .noHostsAvailable(let description): + return "No hosts available: \(description)" + case .indexOutOfBounds(let description): + return "Index out of bounds: \(description)" + case .invalidItemCount(let description): + return "Invalid item count: \(description)" + case .invalidValueType(let description): + return "Invalid value type: \(description)" + case .requestTimedOut(let description): + return "Request timed out: \(description)" + case .unableToSetKeyspace(let description): + return "Unable to set keyspace: \(description)" + case .callbackAlreadySet(let description): + return "Callback already set: \(description)" + case .invalidStatementType(let description): + return "Invalid statement type: \(description)" + case .nameDoesNotExist(let description): + return "No value or column for name: \(description)" + case .unableToDetermineProtocol(let description): + return "Unable to find supported protocol version: \(description)" + case .nullValue(let description): + return "NULL value specified: \(description)" + case .notImplemented(let description): + return "Not implemented: \(description)" + case .unableToConnect(let description): + return "Unable to connect: \(description)" + case .unableToClose(let description): + return "Unable to close: \(description)" + case .noPagingState(let description): + return "No paging state: \(description)" + case .parameterUnset(let description): + return "Parameter unset: \(description)" + case .invalidErrorResultType(let description): + return "Invalid error result type: \(description)" + case .invalidFutureType(let description): + return "Invalid future type: \(description)" + case .internalError(let description): + return "Internal error: \(description)" + case .invalidCustomType(let description): + return "Invalid custom type: \(description)" + case .invalidData(let description): + return "Invalid data: \(description)" + case .notEnoughData(let description): + return "Not enough data: \(description)" + case .invalidState(let description): + return "Invalid state: \(description)" + case .noCustomPayload(let description): + return "No custom payload: \(description)" case .serverError(let description): return "Server error: \(description)" case .protocolError(let description): @@ -207,6 +333,20 @@ extension CassandraClient { return "Already exists: \(description)" case .unprepared(let description): return "Unprepared: \(description)" + case .sslInvalidCert(let description): + return "Unable to load certificate: \(description)" + case .sslInvalidPrivateKey(let description): + return "Unable to load private key: \(description)" + case .sslNoPeerCert(let description): + return "No peer certificate: \(description)" + case .sslInvalidPeerCert(let description): + return "Invalid peer certificate: \(description)" + case .sslIdentityMismatch(let description): + return "Certificate does not match host or IP address: \(description)" + case .sslProtocolError(let description): + return "Protocol error: \(description)" + case .sslClosed(let description): + return "Connection closed: \(description)" case .other(let code, let description): return "Other (\(code)): \(description ?? "unknown")" } @@ -218,6 +358,72 @@ extension CassandraClient { return "Rows exhausted" case .disconnected: return "Disconnected" + case .badParams: + return "Bad parameters" + case .noStreams: + return "No streams available" + case .unableToInit: + return "Unable to initialize" + case .messageEncode: + return "Unable to encode message" + case .hostResolution: + return "Unable to resolve host" + case .unexpectedResponse: + return "Unexpected response from server" + case .requestQueueFull: + return "The request queue is full" + case .noAvailableIOThread: + return "No available IO threads" + case .writeError: + return "Write error" + case .noHostsAvailable: + return "No hosts available" + case .indexOutOfBounds: + return "Index out of bounds" + case .invalidItemCount: + return "Invalid item count" + case .invalidValueType: + return "Invalid value type" + case .requestTimedOut: + return "Request timed out" + case .unableToSetKeyspace: + return "Unable to set keyspace" + case .callbackAlreadySet: + return "Callback already set" + case .invalidStatementType: + return "Invalid statement type" + case .nameDoesNotExist: + return "No value or column for name" + case .unableToDetermineProtocol: + return "Unable to find supported protocol version" + case .nullValue: + return "NULL value specified" + case .notImplemented: + return "Not implemented" + case .unableToConnect: + return "Unable to connect" + case .unableToClose: + return "Unable to close" + case .noPagingState: + return "No paging state" + case .parameterUnset: + return "Parameter unset" + case .invalidErrorResultType: + return "Invalid error result type" + case .invalidFutureType: + return "Invalid future type" + case .internalError: + return "Internal error" + case .invalidCustomType: + return "Invalid custom type" + case .invalidData: + return "Invalid data" + case .notEnoughData: + return "Not enough data" + case .invalidState: + return "Invalid state" + case .noCustomPayload: + return "No custom payload" case .serverError: return "Server error" case .protocolError: @@ -254,6 +460,20 @@ extension CassandraClient { return "Already exists" case .unprepared: return "Unprepared" + case .sslInvalidCert: + return "Unable to load certificate" + case .sslInvalidPrivateKey: + return "Unable to load private key" + case .sslNoPeerCert: + return "No peer certificate" + case .sslInvalidPeerCert: + return "Invalid peer certificate" + case .sslIdentityMismatch: + return "Certificate does not match host or IP address" + case .sslProtocolError: + return "Protocol error" + case .sslClosed: + return "Connection closed" case .other(let code, _): return "Other (\(code))" } @@ -265,6 +485,140 @@ extension CassandraClient { /// Unexpected client connection state. public static let disconnected = Error(code: .disconnected) + // lib errors + public static func badParams(_ description: String) -> Error { + .init(code: .badParams(description)) + } + + public static func noStreams(_ description: String) -> Error { + .init(code: .noStreams(description)) + } + + public static func unableToInit(_ description: String) -> Error { + .init(code: .unableToInit(description)) + } + + public static func messageEncode(_ description: String) -> Error { + .init(code: .messageEncode(description)) + } + + public static func hostResolution(_ description: String) -> Error { + .init(code: .hostResolution(description)) + } + + public static func unexpectedResponse(_ description: String) -> Error { + .init(code: .unexpectedResponse(description)) + } + + public static func requestQueueFull(_ description: String) -> Error { + .init(code: .requestQueueFull(description)) + } + + public static func noAvailableIOThread(_ description: String) -> Error { + .init(code: .noAvailableIOThread(description)) + } + + public static func writeError(_ description: String) -> Error { + .init(code: .writeError(description)) + } + + public static func noHostsAvailable(_ description: String) -> Error { + .init(code: .noHostsAvailable(description)) + } + + public static func indexOutOfBounds(_ description: String) -> Error { + .init(code: .indexOutOfBounds(description)) + } + + public static func invalidItemCount(_ description: String) -> Error { + .init(code: .invalidItemCount(description)) + } + + public static func invalidValueType(_ description: String) -> Error { + .init(code: .invalidValueType(description)) + } + + public static func requestTimedOut(_ description: String) -> Error { + .init(code: .requestTimedOut(description)) + } + + public static func unableToSetKeyspace(_ description: String) -> Error { + .init(code: .unableToSetKeyspace(description)) + } + + public static func callbackAlreadySet(_ description: String) -> Error { + .init(code: .callbackAlreadySet(description)) + } + + public static func invalidStatementType(_ description: String) -> Error { + .init(code: .invalidStatementType(description)) + } + + public static func nameDoesNotExist(_ description: String) -> Error { + .init(code: .nameDoesNotExist(description)) + } + + public static func unableToDetermineProtocol(_ description: String) -> Error { + .init(code: .unableToDetermineProtocol(description)) + } + + public static func nullValue(_ description: String) -> Error { + .init(code: .nullValue(description)) + } + + public static func notImplemented(_ description: String) -> Error { + .init(code: .notImplemented(description)) + } + + public static func unableToConnect(_ description: String) -> Error { + .init(code: .unableToConnect(description)) + } + + public static func unableToClose(_ description: String) -> Error { + .init(code: .unableToClose(description)) + } + + public static func noPagingState(_ description: String) -> Error { + .init(code: .noPagingState(description)) + } + + public static func parameterUnset(_ description: String) -> Error { + .init(code: .parameterUnset(description)) + } + + public static func invalidErrorResultType(_ description: String) -> Error { + .init(code: .invalidErrorResultType(description)) + } + + public static func invalidFutureType(_ description: String) -> Error { + .init(code: .invalidFutureType(description)) + } + + public static func internalError(_ description: String) -> Error { + .init(code: .internalError(description)) + } + + public static func invalidCustomType(_ description: String) -> Error { + .init(code: .invalidCustomType(description)) + } + + public static func invalidData(_ description: String) -> Error { + .init(code: .invalidData(description)) + } + + public static func notEnoughData(_ description: String) -> Error { + .init(code: .notEnoughData(description)) + } + + public static func invalidState(_ description: String) -> Error { + .init(code: .invalidState(description)) + } + + public static func noCustomPayload(_ description: String) -> Error { + .init(code: .noCustomPayload(description)) + } + + // server errors public static func serverError(_ description: String) -> Error { .init(code: .serverError(description)) } @@ -337,6 +691,35 @@ extension CassandraClient { .init(code: .unprepared(description)) } + // ssl errors + public static func sslInvalidCert(_ description: String) -> Error { + .init(code: .sslInvalidCert(description)) + } + + public static func sslInvalidPrivateKey(_ description: String) -> Error { + .init(code: .sslInvalidPrivateKey(description)) + } + + public static func sslNoPeerCert(_ description: String) -> Error { + .init(code: .sslNoPeerCert(description)) + } + + public static func sslInvalidPeerCert(_ description: String) -> Error { + .init(code: .sslInvalidPeerCert(description)) + } + + public static func sslIdentityMismatch(_ description: String) -> Error { + .init(code: .sslIdentityMismatch(description)) + } + + public static func sslProtocolError(_ description: String) -> Error { + .init(code: .sslProtocolError(description)) + } + + public static func sslClosed(_ description: String) -> Error { + .init(code: .sslClosed(description)) + } + public static func other(code: UInt32, description: String?) -> Error { .init(code: .other(code: code, description: description)) }