From f0350fa33e99532da3a29b667e9119045120d10c Mon Sep 17 00:00:00 2001 From: akivab Date: Fri, 8 Jan 2021 16:00:59 -0800 Subject: [PATCH 1/2] maybeDecode --- Sources/CodableFirebase/Decoder.swift | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Sources/CodableFirebase/Decoder.swift b/Sources/CodableFirebase/Decoder.swift index 4af2103..e73eabe 100644 --- a/Sources/CodableFirebase/Decoder.swift +++ b/Sources/CodableFirebase/Decoder.swift @@ -1225,13 +1225,13 @@ extension _FirebaseDecoder { } func unbox(_ value: Any, as type: T.Type) throws -> T? { - let decoded: T + let maybeDecoded: T? if T.self == Date.self || T.self == NSDate.self { guard let date = try self.unbox(value, as: Date.self) else { return nil } - decoded = date as! T + maybeDecoded = date as? T } else if T.self == Data.self || T.self == NSData.self { guard let data = try self.unbox(value, as: Data.self) else { return nil } - decoded = data as! T + maybeDecoded = data as? T } else if T.self == URL.self || T.self == NSURL.self { guard let urlString = try self.unbox(value, as: String.self) else { return nil @@ -1242,20 +1242,22 @@ extension _FirebaseDecoder { debugDescription: "Invalid URL string.")) } - decoded = (url as! T) + maybeDecoded = (url as? T) } else if T.self == Decimal.self || T.self == NSDecimalNumber.self { guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil } - decoded = decimal as! T + maybeDecoded = decimal as? T } else if T.self == IndexSet.self || T.self == NSIndexSet.self { - decoded = value as! T + maybeDecoded = value as? T } else if options.skipFirestoreTypes && (T.self is FirestoreDecodable.Type) { - decoded = value as! T + maybeDecoded = value as? T } else { self.storage.push(container: value) - decoded = try T(from: self) + maybeDecoded = try T(from: self) self.storage.popContainer() } - + guard let decoded = maybeDecoded else { + throw Exception("Can't decode type: \(value)") + } return decoded } } From 01f8230234bc3cd5b0132d145c620f89337ad2f5 Mon Sep 17 00:00:00 2001 From: akivab Date: Fri, 8 Jan 2021 16:05:56 -0800 Subject: [PATCH 2/2] add decode error test failure --- Sources/CodableFirebase/Decoder.swift | 2 +- Tests/CodableFirebaseTests/TestCodableFirestore.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/CodableFirebase/Decoder.swift b/Sources/CodableFirebase/Decoder.swift index e73eabe..2a6f93f 100644 --- a/Sources/CodableFirebase/Decoder.swift +++ b/Sources/CodableFirebase/Decoder.swift @@ -1256,7 +1256,7 @@ extension _FirebaseDecoder { self.storage.popContainer() } guard let decoded = maybeDecoded else { - throw Exception("Can't decode type: \(value)") + throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Can't decode type: \(value)")) } return decoded } diff --git a/Tests/CodableFirebaseTests/TestCodableFirestore.swift b/Tests/CodableFirebaseTests/TestCodableFirestore.swift index cd5db19..a371efe 100644 --- a/Tests/CodableFirebaseTests/TestCodableFirestore.swift +++ b/Tests/CodableFirebaseTests/TestCodableFirestore.swift @@ -140,6 +140,10 @@ class TestCodableFirestore: XCTestCase { XCTAssertEqual(try? FirestoreDecoder().decode(TopLevelWrapper.self, from: ["value": timestamp]), wrapper) } + func testDecodingTimestamp_CorruptData() { + XCTAssertThrowsError(try FirestoreDecoder().decode(TopLevelWrapper.self, from: ["value": "hello"])) + } + private func _testEncodeFailure(of value: T) { do { let _ = try FirestoreEncoder().encode(value)