diff --git a/Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift b/Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift index 028df677..16ac95e6 100644 --- a/Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift +++ b/Sources/PostgreSQL/Connection/PostgreSQLConnection+Query.swift @@ -40,7 +40,7 @@ extension PostgreSQLConnection { case .rowDescription(let row): currentRow = row case .parameterDescription: break case .noData: break - default: fatalError("Unexpected message during PostgreSQLParseRequest: \(message)") + default: throw PostgreSQLError(identifier: "query", reason: "Unexpected message during PostgreSQLParseRequest: \(message)") } }.flatMap(to: Void.self) { let resultFormats = resultFormat.formatCodeFactory(currentRow?.fields.map { $0.dataType } ?? []) @@ -62,12 +62,12 @@ extension PostgreSQLConnection { switch message { case .bindComplete: break case .dataRow(let data): - let row = currentRow !! "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription." + guard let row = currentRow else { throw PostgreSQLError(identifier: "query", reason: "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription.")} let parsed = try row.parse(data: data, formatCodes: resultFormats) onRow(parsed) case .close: break case .noData: break - default: fatalError("Unexpected message during PostgreSQLParseRequest: \(message)") + default: throw PostgreSQLError(identifier: "query", reason: "Unexpected message during PostgreSQLParseRequest: \(message)") } } } diff --git a/Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift b/Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift index 160f3b7b..4ecb68cd 100644 --- a/Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift +++ b/Sources/PostgreSQL/Connection/PostgreSQLConnection+SimpleQuery.swift @@ -22,11 +22,11 @@ extension PostgreSQLConnection { case .rowDescription(let row): currentRow = row case .dataRow(let data): - let row = currentRow !! "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription." + guard let row = currentRow else { throw PostgreSQLError(identifier: "simpleQuery", reason: "Unexpected PostgreSQLDataRow without preceding PostgreSQLRowDescription.") } let parsed = try row.parse(data: data, formatCodes: row.fields.map { $0.formatCode }) onRow(parsed) case .close: break // query over, waiting for `readyForQuery` - default: fatalError("Unexpected message during PostgreSQLQuery: \(message)") + default: throw PostgreSQLError(identifier: "simpleQuery", reason: "Unexpected message during PostgreSQLQuery: \(message)") } } } diff --git a/Sources/PostgreSQL/Connection/PostgreSQLConnection.swift b/Sources/PostgreSQL/Connection/PostgreSQLConnection.swift index a5d2fe5a..538b9ff6 100644 --- a/Sources/PostgreSQL/Connection/PostgreSQLConnection.swift +++ b/Sources/PostgreSQL/Connection/PostgreSQLConnection.swift @@ -128,11 +128,3 @@ public final class PostgreSQLConnection { queueStream.close() } } - -infix operator !! -internal func !!(lhs: Optional, rhs: String) -> T { - switch lhs { - case .none: fatalError(rhs) - case .some(let w): return w - } -} diff --git a/Sources/PostgreSQL/Data/PostgreSQLJSONCustomConvertible.swift b/Sources/PostgreSQL/Data/PostgreSQLJSONCustomConvertible.swift index 4ca21e1b..d7ff0887 100644 --- a/Sources/PostgreSQL/Data/PostgreSQLJSONCustomConvertible.swift +++ b/Sources/PostgreSQL/Data/PostgreSQLJSONCustomConvertible.swift @@ -14,7 +14,7 @@ extension PostgreSQLJSONCustomConvertible { /// See `PostgreSQLDataCustomConvertible.convertFromPostgreSQLData(_:)` public static func convertFromPostgreSQLData(_ data: PostgreSQLData) throws -> Self { guard let value = data.data else { - fatalError() + throw PostgreSQLError(identifier: "data", reason: "Unable to decode PostgreSQL JSON from `null` data.") } switch data.type { @@ -25,7 +25,7 @@ extension PostgreSQLJSONCustomConvertible { assert(value[0] == 0x01) return try JSONDecoder().decode(Self.self, from: value[1...]) } - default: fatalError() + default: throw PostgreSQLError(identifier: "json", reason: "Could not decode \(Self.self) from data type: \(data.type).") } } diff --git a/Sources/PostgreSQL/Message+Parse/PostgreSQLMessageDecoder.swift b/Sources/PostgreSQL/Message+Parse/PostgreSQLMessageDecoder.swift index 18cd61de..d147c9b2 100644 --- a/Sources/PostgreSQL/Message+Parse/PostgreSQLMessageDecoder.swift +++ b/Sources/PostgreSQL/Message+Parse/PostgreSQLMessageDecoder.swift @@ -35,7 +35,7 @@ final class PostgreSQLMessageDecoder { case .t: message = try .parameterDescription(decoder.decode()) default: let string = String(bytes: [type], encoding: .ascii) ?? "n/a" - fatalError("Unrecognized message type: \(string) (\(type)") + throw PostgreSQLError(identifier: "decoder", reason: "Unrecognized message type: \(string) (\(type)", possibleCauses: ["Connected to non-postgresql database"], suggestedFixes: ["Connect to postgresql database"]) } return (message, decoder.data.count) } @@ -119,7 +119,8 @@ fileprivate final class _PostgreSQLMessageDecoder: Decoder, SingleValueDecodingC } } let data = Data(bytes: bytes) - return String(data: data, encoding: .utf8) !! "Unsupported decode type: non-UTF8 string" + guard let string = String(data: data, encoding: .utf8) else { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: non-UTF8 string")} + return string } /// See SingleValueDecodingContainer.decode @@ -132,7 +133,7 @@ fileprivate final class _PostgreSQLMessageDecoder: Decoder, SingleValueDecodingC let sub: Data = data.subdata(in: data.startIndex.. Bool { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: Int.Type) throws -> Int { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: Int8.Type) throws -> Int8 { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: Int64.Type) throws -> Int64 { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: UInt.Type) throws -> UInt { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: UInt16.Type) throws -> UInt16 { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: UInt32.Type) throws -> UInt32 { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: UInt64.Type) throws -> UInt64 { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: Float.Type) throws -> Float { fatalError("Unsupported decode type: \(type)") } - func decode(_ type: Double.Type) throws -> Double { fatalError("Unsupported decode type: \(type)") } + func decode(_ type: Bool.Type) throws -> Bool { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: Int.Type) throws -> Int { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: Int8.Type) throws -> Int8 { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: Int64.Type) throws -> Int64 { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: UInt.Type) throws -> UInt { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: UInt16.Type) throws -> UInt16 { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: UInt32.Type) throws -> UInt32 { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: UInt64.Type) throws -> UInt64 { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: Float.Type) throws -> Float { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } + func decode(_ type: Double.Type) throws -> Double { throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decode type: \(type)") } } // MARK: Keyed @@ -228,7 +229,7 @@ fileprivate final class _PostgreSQLMessageKeyedDecoder: KeyedDecodingContaine } func nestedUnkeyedContainer(forKey key: K) throws -> UnkeyedDecodingContainer { - fatalError("Unsupported decoding type: nested unkeyed container") + throw PostgreSQLError(identifier: "decoder", reason: "Unsupported decoding type: nested unkeyed container") } } diff --git a/Sources/PostgreSQL/Message+Serialize/PostgreSQLMessageEncoder.swift b/Sources/PostgreSQL/Message+Serialize/PostgreSQLMessageEncoder.swift index b435e8c5..ace27974 100644 --- a/Sources/PostgreSQL/Message+Serialize/PostgreSQLMessageEncoder.swift +++ b/Sources/PostgreSQL/Message+Serialize/PostgreSQLMessageEncoder.swift @@ -34,7 +34,7 @@ final class PostgreSQLMessageEncoder { case .password(let password): identifier = .p try password.encode(to: encoder) - default: fatalError("Unsupported encodable type: \(type(of: message))") + default: throw PostgreSQLError(identifier: "encoder", reason: "Unsupported encodable type: \(type(of: message))") } encoder.updateSize() if let prefix = identifier { @@ -146,15 +146,15 @@ internal final class _PostgreSQLMessageEncoder: Encoder, SingleValueEncodingCont // Unsupported - func encode(_ value: Int) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: UInt) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: UInt16) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: UInt32) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: UInt64) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: Float) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: Double) throws { fatalError("Unsupported type: \(type(of: value))") } - func encode(_ value: Bool) throws { fatalError("Unsupported type: \(type(of: value))") } - func encodeNil() throws { fatalError("Unsupported type: nil") } + func encode(_ value: Int) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: UInt) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: UInt16) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: UInt32) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: UInt64) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: Float) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: Double) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encode(_ value: Bool) throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: \(type(of: value))") } + func encodeNil() throws { throw PostgreSQLError(identifier: "encoder", reason: "Unsupported type: nil") } } fileprivate final class _PostgreSQLMessageKeyedEncoder: KeyedEncodingContainerProtocol where K: CodingKey {