Răsfoiți Sursa

Make Firestore use FirebaseDataEncoder and FirebaseDataDecoder (re-implementation of #8858) (#9465)

Morten Bek Ditlevsen 3 ani în urmă
părinte
comite
65f6cfa0bf

+ 1 - 0
CoreOnly/Tests/FirebasePodTest/Podfile

@@ -37,6 +37,7 @@ target 'FirebasePodTest' do
   pod 'FirebaseCoreDiagnostics', :path => '../../../'
   pod 'FirebaseCoreInternal', :path => '../../../'
   pod 'FirebaseCoreExtension', :path => '../../../'
+  pod 'FirebaseSharedSwift', :path => '../../../'
 
   pod 'FirebaseAnalytics' # Analytics is not open source
 end

+ 1 - 1
FirebaseFirestoreSwift.podspec

@@ -32,8 +32,8 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling,
   s.requires_arc            = true
   s.source_files = [
     'Firestore/Swift/Source/**/*.swift',
-    'Firestore/third_party/FirestoreEncoder/*.swift',
   ]
 
   s.dependency 'FirebaseFirestore', '~> 9.0'
+  s.dependency 'FirebaseSharedSwift', '~> 9.0'
 end

+ 40 - 7
FirebaseSharedSwift/Sources/third_party/FirebaseDataEncoder/FirebaseDataEncoder.swift

@@ -14,6 +14,18 @@
 
 import Foundation
 
+public protocol StructureCodingPassthroughTypeResolver {
+    static func isPassthroughType<T>(_ t: T) -> Bool
+}
+
+private struct NoPassthroughTypes: StructureCodingPassthroughTypeResolver {
+    static func isPassthroughType<T>(_ t: T) -> Bool {
+        return false
+    }
+}
+
+public protocol StructureCodingUncodedUnkeyed {}
+
 extension DecodingError {
   /// Returns a `.typeMismatch` error describing the expected type.
   ///
@@ -233,6 +245,9 @@ public class FirebaseDataEncoder {
   /// The strategy to use for encoding keys. Defaults to `.useDefaultKeys`.
   open var keyEncodingStrategy: KeyEncodingStrategy = .useDefaultKeys
 
+  /// A type that can resolve which types to 'pass through' - or leave alone while encoding. Defaults to not passing any types through.
+  open var passthroughTypeResolver: StructureCodingPassthroughTypeResolver.Type = NoPassthroughTypes.self
+
   /// Contextual user-provided information for use during encoding.
   open var userInfo: [CodingUserInfoKey : Any] = [:]
 
@@ -242,6 +257,7 @@ public class FirebaseDataEncoder {
     let dataEncodingStrategy: DataEncodingStrategy
     let nonConformingFloatEncodingStrategy: NonConformingFloatEncodingStrategy
     let keyEncodingStrategy: KeyEncodingStrategy
+    let passthroughTypeResolver: StructureCodingPassthroughTypeResolver.Type
     let userInfo: [CodingUserInfoKey : Any]
   }
 
@@ -251,6 +267,7 @@ public class FirebaseDataEncoder {
                     dataEncodingStrategy: dataEncodingStrategy,
                     nonConformingFloatEncodingStrategy: nonConformingFloatEncodingStrategy,
                     keyEncodingStrategy: keyEncodingStrategy,
+                    passthroughTypeResolver: passthroughTypeResolver,
                     userInfo: userInfo)
   }
 
@@ -501,6 +518,7 @@ fileprivate struct _JSONKeyedEncodingContainer<K : CodingKey> : KeyedEncodingCon
   }
 
   public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
+    if T.self is StructureCodingUncodedUnkeyed.Type { return }
     self.encoder.codingPath.append(key)
     defer { self.encoder.codingPath.removeLast() }
     self.container[_converted(key).stringValue] = try self.encoder.box(value)
@@ -928,6 +946,8 @@ extension __JSONEncoder {
       return (value as! NSDecimalNumber)
     } else if value is _JSONStringDictionaryEncodableMarker {
       return try self.box(value as! [String : Encodable])
+    } else if let object = value as? NSObject, self.options.passthroughTypeResolver.isPassthroughType(value) {
+      return object
     }
 
     // The value should request a container from the __JSONEncoder.
@@ -1166,6 +1186,9 @@ public class FirebaseDataDecoder {
   /// The strategy to use for decoding keys. Defaults to `.useDefaultKeys`.
   open var keyDecodingStrategy: KeyDecodingStrategy = .useDefaultKeys
 
+  /// A type that can resolve which types to 'pass through' - or leave alone while decoding. Defaults to not passing any types through.
+  open var passthroughTypeResolver: StructureCodingPassthroughTypeResolver.Type = NoPassthroughTypes.self
+
   /// Contextual user-provided information for use during decoding.
   open var userInfo: [CodingUserInfoKey : Any] = [:]
 
@@ -1175,6 +1198,7 @@ public class FirebaseDataDecoder {
     let dataDecodingStrategy: DataDecodingStrategy
     let nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy
     let keyDecodingStrategy: KeyDecodingStrategy
+    let passthroughTypeResolver: StructureCodingPassthroughTypeResolver.Type
     let userInfo: [CodingUserInfoKey : Any]
   }
 
@@ -1184,6 +1208,7 @@ public class FirebaseDataDecoder {
                     dataDecodingStrategy: dataDecodingStrategy,
                     nonConformingFloatDecodingStrategy: nonConformingFloatDecodingStrategy,
                     keyDecodingStrategy: keyDecodingStrategy,
+                    passthroughTypeResolver: passthroughTypeResolver,
                     userInfo: userInfo)
   }
 
@@ -1617,6 +1642,11 @@ fileprivate struct _JSONKeyedDecodingContainer<K : CodingKey> : KeyedDecodingCon
   }
 
   public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+    if type is StructureCodingUncodedUnkeyed.Type {
+      // Note: not pushing and popping key to codingPath since the key is
+      // not part of the decoded structure.
+      return try T.init(from: self.decoder)
+    }
     guard let entry = self.container[key.stringValue] else {
       throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key))."))
     }
@@ -2505,12 +2535,12 @@ extension __JSONDecoder {
     return try unbox_(value, as: type) as? T
   }
 
-  fileprivate func unbox_(_ value: Any, as type: Decodable.Type) throws -> Any? {
-    if type == Date.self || type == NSDate.self {
+  fileprivate func unbox_(_ value: Any, as _type: Decodable.Type) throws -> Any? {
+    if _type == Date.self || _type == NSDate.self {
       return try self.unbox(value, as: Date.self)
-    } else if type == Data.self || type == NSData.self {
+    } else if _type == Data.self || _type == NSData.self {
       return try self.unbox(value, as: Data.self)
-    } else if type == URL.self || type == NSURL.self {
+    } else if _type == URL.self || _type == NSURL.self {
       guard let urlString = try self.unbox(value, as: String.self) else {
         return nil
       }
@@ -2520,14 +2550,17 @@ extension __JSONDecoder {
                                                                 debugDescription: "Invalid URL string."))
       }
       return url
-    } else if type == Decimal.self || type == NSDecimalNumber.self {
+    } else if _type == Decimal.self || _type == NSDecimalNumber.self {
       return try self.unbox(value, as: Decimal.self)
-    } else if let stringKeyedDictType = type as? _JSONStringDictionaryDecodableMarker.Type {
+    } else if let stringKeyedDictType = _type as? _JSONStringDictionaryDecodableMarker.Type {
       return try self.unbox(value, as: stringKeyedDictType)
     } else {
       self.storage.push(container: value)
       defer { self.storage.popContainer() }
-      return try type.init(from: self)
+      if self.options.passthroughTypeResolver.isPassthroughType(value) && type(of: value) == _type  {
+        return value
+      }
+      return try _type.init(from: self)
     }
   }
 }

+ 3 - 0
Firestore/Example/Podfile

@@ -116,6 +116,7 @@ if is_platform(:ios)
     target 'Firestore_IntegrationTests_iOS' do
       inherit! :search_paths
 
+      pod 'FirebaseSharedSwift', :path => '../../'
       pod 'FirebaseFirestoreSwift', :path => '../../'
       pod 'GoogleBenchmark', :podspec => 'GoogleBenchmark.podspec'
       pod 'GoogleTest', :podspec => 'GoogleTest.podspec'
@@ -152,6 +153,7 @@ if is_platform(:osx)
     target 'Firestore_IntegrationTests_macOS' do
       inherit! :search_paths
 
+      pod 'FirebaseSharedSwift', :path => '../../'
       pod 'FirebaseFirestoreSwift', :path => '../../'
       pod 'GoogleBenchmark', :podspec => 'GoogleBenchmark.podspec'
       pod 'GoogleTest', :podspec => 'GoogleTest.podspec'
@@ -181,6 +183,7 @@ if is_platform(:tvos)
     target 'Firestore_IntegrationTests_tvOS' do
       inherit! :search_paths
 
+      pod 'FirebaseSharedSwift', :path => '../../'
       pod 'FirebaseFirestoreSwift', :path => '../../'
       pod 'GoogleBenchmark', :podspec => 'GoogleBenchmark.podspec'
       pod 'GoogleTest', :podspec => 'GoogleTest.podspec'

+ 11 - 0
Firestore/Swift/CHANGELOG.md

@@ -1,3 +1,14 @@
+# 10.0.0
+- [changed] `Firestore.Encoder` and `Firestore.Decoder` now wraps the shared `FirebaseDataEncoder` and `FirebaseDataDecoder` types which provides new customization options for encoding and decoding date to and from Firestore - similar to the options present on `JSONEncoder` and `JSONDecoder` from `Foundation`.
+- [added] `Firestore.Encoder.KeyEncodingStrategy`
+- [added] `Firestore.Encoder.DateEncodingStrategy`
+- [added] `Firestore.Encoder.DataEncodingStrategy`
+- [added] `Firestore.Encoder.NonConformingFloatEncodingStrategy`
+- [added] `Firestore.Decoder.KeyDecodingStrategy`
+- [added] `Firestore.Decoder.DateDecodingStrategy`
+- [added] `Firestore.Decoder.DataDecodingStrategy`
+- [added] `Firestore.Decoder.NonConformingFloatDecodingStrategy`
+
 # 9.0.0
 - [added] **Breaking change:** `FirebaseFirestoreSwift` has exited beta and is
   now generally available for use.

+ 9 - 6
Firestore/Swift/Source/Codable/CodablePassThroughTypes.swift

@@ -15,12 +15,15 @@
  */
 
 import Foundation
+import FirebaseSharedSwift
 import FirebaseFirestore
 
-internal func isFirestorePassthroughType<T: Any>(_ value: T) -> Bool {
-  return
-    T.self == GeoPoint.self ||
-    T.self == Timestamp.self ||
-    T.self == FieldValue.self ||
-    T.self == DocumentReference.self
+internal struct FirestorePassthroughTypes: StructureCodingPassthroughTypeResolver {
+  static func isPassthroughType<T>(_ t: T) -> Bool {
+    return
+      t is GeoPoint ||
+      t is Timestamp ||
+      t is FieldValue ||
+      t is DocumentReference
+  }
 }

+ 2 - 1
Firestore/Swift/Source/Codable/CollectionReference+WriteEncodable.swift

@@ -35,6 +35,7 @@ public extension CollectionReference {
                                  encoder: Firestore.Encoder = Firestore.Encoder(),
                                  completion: ((Error?) -> Void)? = nil) throws
     -> DocumentReference {
-    return addDocument(data: try encoder.encode(value), completion: completion)
+    let encoded = try encoder.encode(value)
+    return addDocument(data: encoded, completion: completion)
   }
 }

+ 11 - 4
Firestore/Swift/Source/Codable/DocumentID.swift

@@ -15,6 +15,10 @@
  */
 
 import FirebaseFirestore
+import FirebaseSharedSwift
+
+let documentRefUserInfoKey =
+  CodingUserInfoKey(rawValue: "DocumentRefUserInfoKey")!
 
 /// A type that can initialize itself from a Firestore `DocumentReference`,
 /// which makes it suitable for use with the `@DocumentID` property wrapper.
@@ -76,7 +80,7 @@ internal protocol DocumentIDProtocol {
 /// Firestore.Encoder leads to an error.
 @propertyWrapper
 public struct DocumentID<Value: DocumentIDWrappable & Codable>:
-  DocumentIDProtocol, Codable {
+  DocumentIDProtocol, Codable, StructureCodingUncodedUnkeyed {
   var value: Value?
 
   public init(wrappedValue value: Value?) {
@@ -101,9 +105,12 @@ public struct DocumentID<Value: DocumentIDWrappable & Codable>:
   // MARK: - `Codable` implementation.
 
   public init(from decoder: Decoder) throws {
-    throw FirestoreDecodingError.decodingIsNotSupported(
-      "DocumentID values can only be decoded with Firestore.Decoder"
-    )
+    guard let reference = decoder.userInfo[documentRefUserInfoKey] as? DocumentReference else {
+      throw FirestoreDecodingError.decodingIsNotSupported(
+        "Could not find DocumentReference for user info key: \(documentRefUserInfoKey)"
+      )
+    }
+    try self.init(from: reference)
   }
 
   public func encode(to encoder: Encoder) throws {

+ 6 - 3
Firestore/Swift/Source/Codable/DocumentReference+WriteEncodable.swift

@@ -34,7 +34,8 @@ public extension DocumentReference {
   func setData<T: Encodable>(from value: T,
                              encoder: Firestore.Encoder = Firestore.Encoder(),
                              completion: ((Error?) -> Void)? = nil) throws {
-    setData(try encoder.encode(value), completion: completion)
+    let encoded = try encoder.encode(value)
+    setData(encoded, completion: completion)
   }
 
   /// Encodes an instance of `Encodable` and overwrites the encoded data
@@ -57,7 +58,8 @@ public extension DocumentReference {
                              merge: Bool,
                              encoder: Firestore.Encoder = Firestore.Encoder(),
                              completion: ((Error?) -> Void)? = nil) throws {
-    setData(try encoder.encode(value), merge: merge, completion: completion)
+    let encoded = try encoder.encode(value)
+    setData(encoded, merge: merge, completion: completion)
   }
 
   /// Encodes an instance of `Encodable` and writes the encoded data to the document referred
@@ -84,6 +86,7 @@ public extension DocumentReference {
                              mergeFields: [Any],
                              encoder: Firestore.Encoder = Firestore.Encoder(),
                              completion: ((Error?) -> Void)? = nil) throws {
-    setData(try encoder.encode(value), mergeFields: mergeFields, completion: completion)
+    let encoded = try encoder.encode(value)
+    setData(encoded, mergeFields: mergeFields, completion: completion)
   }
 }

+ 110 - 0
Firestore/Swift/Source/Codable/EncoderDecoder.swift

@@ -0,0 +1,110 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import FirebaseFirestore
+import FirebaseSharedSwift
+import Foundation
+
+public extension Firestore {
+  class Encoder {
+    public typealias DateEncodingStrategy = FirebaseDataEncoder.DateEncodingStrategy
+    public typealias DataEncodingStrategy = FirebaseDataEncoder.DataEncodingStrategy
+    public typealias NonConformingFloatEncodingStrategy = FirebaseDataEncoder
+      .NonConformingFloatEncodingStrategy
+    public typealias KeyEncodingStrategy = FirebaseDataEncoder.KeyEncodingStrategy
+
+    /// The strategy to use in encoding dates. Defaults to `.timestamp`.
+    public var dateEncodingStrategy: DateEncodingStrategy = .timestamp
+
+    /// The strategy to use in encoding binary data. Defaults to `.base64`.
+    public var dataEncodingStrategy: DataEncodingStrategy = .base64
+
+    /// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
+    public var nonConformingFloatEncodingStrategy: NonConformingFloatEncodingStrategy = .throw
+
+    /// The strategy to use for encoding keys. Defaults to `.useDefaultKeys`.
+    public var keyEncodingStrategy: KeyEncodingStrategy = .useDefaultKeys
+
+    /// Contextual user-provided information for use during encoding.
+    public var userInfo: [CodingUserInfoKey: Any] = [:]
+
+    public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
+      let encoder = FirebaseDataEncoder()
+      encoder.dateEncodingStrategy = dateEncodingStrategy
+      encoder.dataEncodingStrategy = dataEncodingStrategy
+      encoder.nonConformingFloatEncodingStrategy = nonConformingFloatEncodingStrategy
+      encoder.keyEncodingStrategy = keyEncodingStrategy
+      encoder.passthroughTypeResolver = FirestorePassthroughTypes.self
+      encoder.userInfo = userInfo
+      let encoded = try encoder.encode(value)
+      guard let dictionaryValue = encoded as? [String: Any] else {
+        throw EncodingError
+          .invalidValue(value,
+                        EncodingError
+                          .Context(codingPath: [],
+                                   debugDescription: "Top-level \(T.self) is not allowed."))
+      }
+      return dictionaryValue
+    }
+
+    public init() {}
+  }
+
+  class Decoder {
+    public typealias DateDecodingStrategy = FirebaseDataDecoder.DateDecodingStrategy
+    public typealias DataDecodingStrategy = FirebaseDataDecoder.DataDecodingStrategy
+    public typealias NonConformingFloatDecodingStrategy = FirebaseDataDecoder
+      .NonConformingFloatDecodingStrategy
+    public typealias KeyDecodingStrategy = FirebaseDataDecoder.KeyDecodingStrategy
+
+    /// The strategy to use in decoding dates. Defaults to `.timestamp`.
+    public var dateDecodingStrategy: DateDecodingStrategy = .timestamp
+
+    /// The strategy to use in decoding binary data. Defaults to `.base64`.
+    public var dataDecodingStrategy: DataDecodingStrategy = .base64
+
+    /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
+    public var nonConformingFloatDecodingStrategy: NonConformingFloatDecodingStrategy = .throw
+
+    /// The strategy to use for decoding keys. Defaults to `.useDefaultKeys`.
+    public var keyDecodingStrategy: KeyDecodingStrategy = .useDefaultKeys
+
+    /// Contextual user-provided information for use during decoding.
+    public var userInfo: [CodingUserInfoKey: Any] = [:]
+
+    public func decode<T: Decodable>(_ t: T.Type, from data: Any) throws -> T {
+      let decoder = FirebaseDataDecoder()
+      decoder.dateDecodingStrategy = dateDecodingStrategy
+      decoder.dataDecodingStrategy = dataDecodingStrategy
+      decoder.nonConformingFloatDecodingStrategy = nonConformingFloatDecodingStrategy
+      decoder.keyDecodingStrategy = keyDecodingStrategy
+      decoder.passthroughTypeResolver = FirestorePassthroughTypes.self
+      decoder.userInfo = userInfo
+      // configure for firestore
+      return try decoder.decode(t, from: data)
+    }
+
+    public func decode<T: Decodable>(_ t: T.Type, from data: Any,
+                                     in reference: DocumentReference?) throws -> T {
+      if let reference = reference {
+        userInfo[documentRefUserInfoKey] = reference
+      }
+      return try decode(T.self, from: data)
+    }
+
+    public init() {}
+  }
+}

+ 29 - 0
Firestore/Swift/Source/Codable/TimestampDecodingStrategy.swift

@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Foundation
+import FirebaseFirestore
+
+public extension Firestore.Decoder.DateDecodingStrategy {
+  /// Decode the `Date` from a Firestore `Timestamp`
+  static var timestamp: Firestore.Decoder.DateDecodingStrategy {
+    return .custom { decoder in
+      let container = try decoder.singleValueContainer()
+      let value = try container.decode(Timestamp.self)
+      return value.dateValue()
+    }
+  }
+}

+ 28 - 0
Firestore/Swift/Source/Codable/TimestampEncodingStrategy.swift

@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import FirebaseFirestore
+import Foundation
+
+public extension Firestore.Encoder.DateEncodingStrategy {
+  /// Encode the `Date` as a Firestore `Timestamp`.
+  static var timestamp: Firestore.Encoder.DateEncodingStrategy {
+    return .custom { date, encoder in
+      var container = encoder.singleValueContainer()
+      try container.encode(Timestamp(date: date))
+    }
+  }
+}

+ 6 - 3
Firestore/Swift/Source/Codable/Transaction+WriteEncodable.swift

@@ -34,7 +34,8 @@ public extension Transaction {
                              forDocument doc: DocumentReference,
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> Transaction {
-    setData(try encoder.encode(value), forDocument: doc)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc)
     return self
   }
 
@@ -58,7 +59,8 @@ public extension Transaction {
                              merge: Bool,
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> Transaction {
-    setData(try encoder.encode(value), forDocument: doc, merge: merge)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc, merge: merge)
     return self
   }
 
@@ -86,7 +88,8 @@ public extension Transaction {
                              mergeFields: [Any],
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> Transaction {
-    setData(try encoder.encode(value), forDocument: doc, mergeFields: mergeFields)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc, mergeFields: mergeFields)
     return self
   }
 }

+ 6 - 3
Firestore/Swift/Source/Codable/WriteBatch+WriteEncodable.swift

@@ -34,7 +34,8 @@ public extension WriteBatch {
                              forDocument doc: DocumentReference,
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> WriteBatch {
-    setData(try encoder.encode(value), forDocument: doc)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc)
     return self
   }
 
@@ -58,7 +59,8 @@ public extension WriteBatch {
                              merge: Bool,
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> WriteBatch {
-    setData(try encoder.encode(value), forDocument: doc, merge: merge)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc, merge: merge)
     return self
   }
 
@@ -86,7 +88,8 @@ public extension WriteBatch {
                              mergeFields: [Any],
                              encoder: Firestore.Encoder = Firestore
                                .Encoder()) throws -> WriteBatch {
-    setData(try encoder.encode(value), forDocument: doc, mergeFields: mergeFields)
+    let encoded = try encoder.encode(value)
+    setData(encoded, forDocument: doc, mergeFields: mergeFields)
     return self
   }
 }

+ 7 - 16
Firestore/Swift/Tests/Codable/FirestoreEncoderTests.swift

@@ -134,7 +134,7 @@ class FirestoreEncoderTests: XCTestCase {
       let date: Date
     }
     let date = Date(timeIntervalSinceReferenceDate: 0)
-    assertThat(Model(date: date)).roundTrips(to: ["date": date])
+    assertThat(Model(date: date)).roundTrips(to: ["date": Timestamp(date: date)])
   }
 
   func testTimestampCanDecodeAsDate() {
@@ -564,26 +564,17 @@ class FirestoreEncoderTests: XCTestCase {
       .failsEncodingWithJSONEncoder()
   }
 
-  func testDecodingDocumentIDWithConfictingFieldsThrows() throws {
+  func testDecodingDocumentIDWithConfictingFieldsDoesNotThrow() throws {
     struct Model: Codable, Equatable {
       var name: String
       @DocumentID var docId: DocumentReference?
     }
 
-    do {
-      _ = try Firestore.Decoder().decode(
-        Model.self,
-        from: ["name": "abc", "docId": "Causing conflict"],
-        in: FSTTestDocRef("abc/123")
-      )
-      XCTFail("Failed to throw")
-    } catch let FirestoreDecodingError.fieldNameConflict(msg) {
-      XCTAssertEqual(msg, "Field name [\"docId\"] was found from document \"abc/123\", "
-        + "cannot assign the document reference to this field.")
-      return
-    } catch {
-      XCTFail("Unrecognized error: \(error)")
-    }
+    _ = try Firestore.Decoder().decode(
+      Model.self,
+      from: ["name": "abc", "docId": "Does not cause conflict"],
+      in: FSTTestDocRef("abc/123")
+    )
   }
 }
 

+ 0 - 1167
Firestore/third_party/FirestoreEncoder/FirestoreDecoder.swift

@@ -1,1167 +0,0 @@
-// This file is derived from swift/stdlib/public/SDK/Foundation/JSONEncoder.swift
-// and swift/stdlib/public/SDK/Foundation/PlistEncoder.swift
-
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-import FirebaseFirestore
-import Foundation
-
-public extension Firestore {
-  struct Decoder {
-    fileprivate static let documentRefUserInfoKey =
-      CodingUserInfoKey(rawValue: "DocumentRefUserInfoKey")
-
-    public init() {}
-    /// Returns an instance of specified type from a Firestore document.
-    ///
-    /// If exists in `container`, Firestore specific types are recognized, and
-    /// passed through to `Decodable` implementations. This means types below
-    /// in `container` are directly supported:
-    ///   - GeoPoint
-    ///   - Timestamp
-    ///   - DocumentReference
-    ///
-    /// - Parameters:
-    ///   - A type to decode a document to.
-    ///   - container: A Map keyed of String representing a Firestore document.
-    ///   - document: A reference to the Firestore Document that is being
-    ///             decoded.
-    /// - Returns: An instance of specified type by the first parameter.
-    public func decode<T: Decodable>(_: T.Type,
-                                     from container: Any,
-                                     in document: DocumentReference? = nil) throws -> T {
-      let decoder = _FirestoreDecoder(referencing: container)
-      if let doc = document {
-        decoder.userInfo[Firestore.Decoder.documentRefUserInfoKey!] = doc
-      }
-
-      guard let value = try decoder.unbox(container, as: T.self) else {
-        throw DecodingError.valueNotFound(
-          T.self,
-          DecodingError.Context(codingPath: [],
-                                debugDescription: "The given dictionary was invalid")
-        )
-      }
-      return value
-    }
-  }
-}
-
-class _FirestoreDecoder: Decoder {
-  // `_FirestoreDecoder`
-
-  // MARK: Properties
-
-  /// A stack of data containers storing data containers to decode. When a new data
-  /// container is being decoded, a corresponding storage is pushed to the stack;
-  /// and when that container (and all of its children containers) has been decoded,
-  /// it is popped out such that the decoding can proceed with new top storage.
-  fileprivate var storage: _FirestoreDecodingStorage
-
-  /// The path to the current point in the container tree. Given the root container, one could
-  /// conceptually reconstruct `storage` by following `codingPath` from the root container.
-  public fileprivate(set) var codingPath: [CodingKey]
-
-  /// Contextual user-provided information for use during encoding.
-  public var userInfo: [CodingUserInfoKey: Any] = [:]
-
-  // MARK: - Initialization
-
-  /// Initializes `self` with the given top-level container and options.
-  init(referencing container: Any, at codingPath: [CodingKey] = []) {
-    storage = _FirestoreDecodingStorage()
-    storage.push(container: container)
-    self.codingPath = codingPath
-  }
-
-  // MARK: - Decoder Methods
-
-  public func container<Key>(keyedBy _: Key.Type) throws -> KeyedDecodingContainer<Key> {
-    guard !(storage.topContainer is NSNull) else {
-      throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
-                                        DecodingError.Context(codingPath: codingPath,
-                                                              debugDescription: "Cannot get keyed decoding container -- found null value instead."))
-    }
-
-    guard let topContainer = storage.topContainer as? [String: Any] else {
-      let context = DecodingError
-        .Context(codingPath: codingPath, debugDescription: "Not a dictionary")
-      throw DecodingError.typeMismatch([String: Any].self, context)
-    }
-
-    let container = _FirestoreKeyedDecodingContainer<Key>(referencing: self, wrapping: topContainer)
-    return KeyedDecodingContainer(container)
-  }
-
-  public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
-    guard !(storage.topContainer is NSNull) else {
-      throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
-                                        DecodingError.Context(codingPath: codingPath,
-                                                              debugDescription: "Cannot get unkeyed decoding container -- found null value instead."))
-    }
-
-    guard let topContainer = storage.topContainer as? [Any] else {
-      let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Not an array")
-      throw DecodingError.typeMismatch([Any].self, context)
-    }
-
-    return _FirestoreUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
-  }
-
-  public func singleValueContainer() throws -> SingleValueDecodingContainer {
-    return self
-  }
-}
-
-private struct _FirestoreDecodingStorage {
-  // MARK: Properties
-
-  /// The container stack.
-  /// Elements may be any one of the plist types (NSNumber, Date, String, Array, [String : Any]).
-  fileprivate private(set) var containers: [Any] = []
-
-  // MARK: - Initialization
-
-  /// Initializes `self` with no containers.
-  fileprivate init() {}
-
-  // MARK: - Modifying the Stack
-
-  fileprivate var count: Int {
-    return containers.count
-  }
-
-  fileprivate var topContainer: Any {
-    precondition(containers.count > 0, "Empty container stack.")
-    return containers.last!
-  }
-
-  fileprivate mutating func push(container: Any) {
-    containers.append(container)
-  }
-
-  fileprivate mutating func popContainer() {
-    precondition(containers.count > 0, "Empty container stack.")
-    containers.removeLast()
-  }
-}
-
-private struct _FirestoreKeyedDecodingContainer<K: CodingKey>: KeyedDecodingContainerProtocol {
-  typealias Key = K
-
-  // MARK: Properties
-
-  /// A reference to the decoder we're reading from.
-  private let decoder: _FirestoreDecoder
-
-  /// A reference to the container we're reading from.
-  private let container: [String: Any]
-
-  /// The path of coding keys taken to get to this point in decoding.
-  public private(set) var codingPath: [CodingKey]
-
-  // MARK: - Initialization
-
-  /// Initializes `self` by referencing the given decoder and container.
-  fileprivate init(referencing decoder: _FirestoreDecoder, wrapping container: [String: Any]) {
-    self.decoder = decoder
-    self.container = container
-    codingPath = decoder.codingPath
-  }
-
-  // MARK: - KeyedDecodingContainerProtocol Methods
-
-  public var allKeys: [Key] {
-    return container.keys.compactMap { Key(stringValue: $0) }
-  }
-
-  public func contains(_ key: Key) -> Bool {
-    return container[key.stringValue] != nil
-  }
-
-  public func decodeNil(forKey key: Key) throws -> Bool {
-    let entry = try require(key: key)
-    return entry is NSNull
-  }
-
-  public func decode(_: Bool.Type, forKey key: Key) throws -> Bool {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Bool.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Int.Type, forKey key: Key) throws -> Int {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Int.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Int8.Type, forKey key: Key) throws -> Int8 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Int8.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Int16.Type, forKey key: Key) throws -> Int16 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Int16.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Int32.Type, forKey key: Key) throws -> Int32 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Int32.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Int64.Type, forKey key: Key) throws -> Int64 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Int64.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: UInt.Type, forKey key: Key) throws -> UInt {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: UInt.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: UInt8.Type, forKey key: Key) throws -> UInt8 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: UInt8.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: UInt16.Type, forKey key: Key) throws -> UInt16 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: UInt16.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: UInt32.Type, forKey key: Key) throws -> UInt32 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: UInt32.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: UInt64.Type, forKey key: Key) throws -> UInt64 {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: UInt64.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Float.Type, forKey key: Key) throws -> Float {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Float.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: Double.Type, forKey key: Key) throws -> Double {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: Double.self)
-    return try require(value: value)
-  }
-
-  public func decode(_: String.Type, forKey key: Key) throws -> String {
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: String.self)
-    return try require(value: value)
-  }
-
-  public func decode<T: Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
-    #if compiler(>=5.1)
-      if let type = type as? DocumentIDProtocol.Type {
-        let docRef = decoder.userInfo[
-          Firestore.Decoder.documentRefUserInfoKey!
-        ] as! DocumentReference?
-
-        if contains(key) {
-          let docPath = (docRef != nil) ? docRef!.path : "nil"
-          var codingPathCopy = codingPath.map { key in key.stringValue }
-          codingPathCopy.append(key.stringValue)
-
-          throw FirestoreDecodingError.fieldNameConflict("Field name " +
-            "\(codingPathCopy) was found from document \"\(docPath)\", " +
-            "cannot assign the document reference to this field.")
-        }
-
-        return try type.init(from: docRef) as! T
-      }
-    #endif // compiler(>=5.1)
-
-    let entry = try require(key: key)
-
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value = try decoder.unbox(entry, as: T.self)
-    return try require(value: value)
-  }
-
-  private func require(key: Key) throws -> Any {
-    if let entry = container[key.stringValue] {
-      return entry
-    }
-
-    let description = "No value associated with key \(key) (\"\(key.stringValue)\")."
-    let context = DecodingError
-      .Context(codingPath: decoder.codingPath, debugDescription: description)
-    throw DecodingError.keyNotFound(key, context)
-  }
-
-  private func require<T>(value: T?) throws -> T {
-    if let value = value {
-      return value
-    }
-
-    let message = "Expected \(T.self) value but found null instead."
-    let context = DecodingError.Context(codingPath: decoder.codingPath, debugDescription: message)
-    throw DecodingError.valueNotFound(T.self, context)
-  }
-
-  public func nestedContainer<NestedKey>(keyedBy _: NestedKey.Type,
-                                         forKey key: Key) throws
-    -> KeyedDecodingContainer<NestedKey> {
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    guard let value = self.container[key.stringValue] else {
-      throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
-                                        DecodingError.Context(codingPath: codingPath,
-                                                              debugDescription: "Cannot get nested keyed container -- no value found for key \"\(key.stringValue)\""))
-    }
-
-    guard let dictionary = value as? [String: Any] else {
-      throw DecodingError
-        ._typeMismatch(at: codingPath, expectation: [String: Any].self, reality: value)
-    }
-
-    let container = _FirestoreKeyedDecodingContainer<NestedKey>(referencing: decoder,
-                                                                wrapping: dictionary)
-    return KeyedDecodingContainer(container)
-  }
-
-  public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    guard let value = container[key.stringValue] else {
-      throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
-                                        DecodingError.Context(codingPath: codingPath,
-                                                              debugDescription: "Cannot get nested unkeyed container -- no value found for key \"\(key.stringValue)\""))
-    }
-
-    guard let array = value as? [Any] else {
-      let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Not an array")
-      throw DecodingError.typeMismatch([Any].self, context)
-    }
-
-    return _FirestoreUnkeyedDecodingContainer(referencing: decoder, wrapping: array)
-  }
-
-  private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
-    decoder.codingPath.append(key)
-    defer { self.decoder.codingPath.removeLast() }
-
-    let value: Any = container[key.stringValue] ?? NSNull()
-    return _FirestoreDecoder(referencing: value, at: decoder.codingPath)
-  }
-
-  public func superDecoder() throws -> Decoder {
-    return try _superDecoder(forKey: _FirestoreKey.super)
-  }
-
-  public func superDecoder(forKey key: Key) throws -> Decoder {
-    return try _superDecoder(forKey: key)
-  }
-}
-
-private struct _FirestoreUnkeyedDecodingContainer: UnkeyedDecodingContainer {
-  // MARK: Properties
-
-  /// A reference to the decoder we're reading from.
-  private let decoder: _FirestoreDecoder
-
-  /// A reference to the container we're reading from.
-  private let container: [Any]
-
-  /// The path of coding keys taken to get to this point in decoding.
-  public private(set) var codingPath: [CodingKey]
-
-  /// The index of the element we're about to decode.
-  public private(set) var currentIndex: Int
-
-  // MARK: - Initialization
-
-  /// Initializes `self` by referencing the given decoder and container.
-  fileprivate init(referencing decoder: _FirestoreDecoder, wrapping container: [Any]) {
-    self.decoder = decoder
-    self.container = container
-    codingPath = decoder.codingPath
-    currentIndex = 0
-  }
-
-  // MARK: - UnkeyedDecodingContainer Methods
-
-  public var count: Int? {
-    return container.count
-  }
-
-  public var isAtEnd: Bool {
-    return currentIndex >= count!
-  }
-
-  public mutating func decodeNil() throws -> Bool {
-    try expectNotAtEnd()
-
-    if container[currentIndex] is NSNull {
-      currentIndex += 1
-      return true
-    } else {
-      return false
-    }
-  }
-
-  public mutating func decode(_: Bool.Type) throws -> Bool {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Bool.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Int.Type) throws -> Int {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Int.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Int8.Type) throws -> Int8 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Int8.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Int16.Type) throws -> Int16 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Int16.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Int32.Type) throws -> Int32 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Int32.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Int64.Type) throws -> Int64 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Int64.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: UInt.Type) throws -> UInt {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: UInt.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: UInt8.Type) throws -> UInt8 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: UInt8.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: UInt16.Type) throws -> UInt16 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: UInt16.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: UInt32.Type) throws -> UInt32 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: UInt32.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: UInt64.Type) throws -> UInt64 {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: UInt64.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Float.Type) throws -> Float {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Float.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: Double.Type) throws -> Double {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: Double.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode(_: String.Type) throws -> String {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: String.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func decode<T: Decodable>(_: T.Type) throws -> T {
-    try expectNotAtEnd()
-
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    let decoded = try decoder.unbox(container[currentIndex], as: T.self)
-    return try require(value: decoded)
-  }
-
-  public mutating func nestedContainer<NestedKey>(keyedBy _: NestedKey
-    .Type) throws -> KeyedDecodingContainer<NestedKey> {
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    try expectNotAtEnd()
-
-    let value = self.container[currentIndex]
-    try requireNotNSNull(value)
-
-    guard let dictionary = value as? [String: Any] else {
-      throw DecodingError
-        ._typeMismatch(at: codingPath, expectation: [String: Any].self, reality: value)
-    }
-
-    currentIndex += 1
-    let container = _FirestoreKeyedDecodingContainer<NestedKey>(referencing: decoder,
-                                                                wrapping: dictionary)
-    return KeyedDecodingContainer(container)
-  }
-
-  public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    try expectNotAtEnd()
-
-    let value = container[currentIndex]
-    try requireNotNSNull(value)
-
-    guard let array = value as? [Any] else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: [Any].self, reality: value)
-    }
-
-    currentIndex += 1
-    return _FirestoreUnkeyedDecodingContainer(referencing: decoder, wrapping: array)
-  }
-
-  public mutating func superDecoder() throws -> Decoder {
-    decoder.codingPath.append(_FirestoreKey(index: currentIndex))
-    defer { self.decoder.codingPath.removeLast() }
-
-    try expectNotAtEnd()
-
-    let value = container[currentIndex]
-    currentIndex += 1
-    return _FirestoreDecoder(referencing: value, at: decoder.codingPath)
-  }
-
-  private func expectNotAtEnd() throws {
-    guard !isAtEnd else {
-      throw DecodingError
-        .valueNotFound(Any?.self,
-                       DecodingError
-                         .Context(codingPath: decoder
-                           .codingPath + [_FirestoreKey(index: currentIndex)],
-                           debugDescription: "Unkeyed container is at end."))
-    }
-  }
-
-  private func requireNotNSNull(_ value: Any) throws {
-    if !(value is NSNull) {
-      return
-    }
-
-    let description = "Cannot get keyed decoding container -- found null value instead."
-    let context = DecodingError.Context(codingPath: codingPath, debugDescription: description)
-    throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self, context)
-  }
-
-  private mutating func require<T>(value: T?) throws -> T {
-    guard let value = value else {
-      let message = "Expected \(T.self) value but found null instead."
-      let context = DecodingError
-        .Context(codingPath: decoder.codingPath + [_FirestoreKey(index: currentIndex)],
-                 debugDescription: message)
-      throw DecodingError.valueNotFound(T.self, context)
-    }
-
-    currentIndex += 1
-    return value
-  }
-}
-
-extension _FirestoreDecoder: SingleValueDecodingContainer {
-  // MARK: SingleValueDecodingContainer Methods
-
-  private func expectNonNull<T>(_ type: T.Type) throws {
-    guard !decodeNil() else {
-      throw DecodingError
-        .valueNotFound(type,
-                       DecodingError
-                         .Context(codingPath: codingPath,
-                                  debugDescription: "Expected \(type) but found null value instead."))
-    }
-  }
-
-  public func decodeNil() -> Bool {
-    return storage.topContainer is NSNull
-  }
-
-  public func decode(_: Bool.Type) throws -> Bool {
-    try expectNonNull(Bool.self)
-    return try unbox(storage.topContainer, as: Bool.self)!
-  }
-
-  public func decode(_: Int.Type) throws -> Int {
-    try expectNonNull(Int.self)
-    return try unbox(storage.topContainer, as: Int.self)!
-  }
-
-  public func decode(_: Int8.Type) throws -> Int8 {
-    try expectNonNull(Int8.self)
-    return try unbox(storage.topContainer, as: Int8.self)!
-  }
-
-  public func decode(_: Int16.Type) throws -> Int16 {
-    try expectNonNull(Int16.self)
-    return try unbox(storage.topContainer, as: Int16.self)!
-  }
-
-  public func decode(_: Int32.Type) throws -> Int32 {
-    try expectNonNull(Int32.self)
-    return try unbox(storage.topContainer, as: Int32.self)!
-  }
-
-  public func decode(_: Int64.Type) throws -> Int64 {
-    try expectNonNull(Int64.self)
-    return try unbox(storage.topContainer, as: Int64.self)!
-  }
-
-  public func decode(_: UInt.Type) throws -> UInt {
-    try expectNonNull(UInt.self)
-    return try unbox(storage.topContainer, as: UInt.self)!
-  }
-
-  public func decode(_: UInt8.Type) throws -> UInt8 {
-    try expectNonNull(UInt8.self)
-    return try unbox(storage.topContainer, as: UInt8.self)!
-  }
-
-  public func decode(_: UInt16.Type) throws -> UInt16 {
-    try expectNonNull(UInt16.self)
-    return try unbox(storage.topContainer, as: UInt16.self)!
-  }
-
-  public func decode(_: UInt32.Type) throws -> UInt32 {
-    try expectNonNull(UInt32.self)
-    return try unbox(storage.topContainer, as: UInt32.self)!
-  }
-
-  public func decode(_: UInt64.Type) throws -> UInt64 {
-    try expectNonNull(UInt64.self)
-    return try unbox(storage.topContainer, as: UInt64.self)!
-  }
-
-  public func decode(_: Float.Type) throws -> Float {
-    try expectNonNull(Float.self)
-    return try unbox(storage.topContainer, as: Float.self)!
-  }
-
-  public func decode(_: Double.Type) throws -> Double {
-    try expectNonNull(Double.self)
-    return try unbox(storage.topContainer, as: Double.self)!
-  }
-
-  public func decode(_: String.Type) throws -> String {
-    try expectNonNull(String.self)
-    return try unbox(storage.topContainer, as: String.self)!
-  }
-
-  public func decode<T: Decodable>(_: T.Type) throws -> T {
-    try expectNonNull(T.self)
-    return try unbox(storage.topContainer, as: T.self)!
-  }
-}
-
-extension _FirestoreDecoder {
-  /// Returns the given value unboxed from a container.
-  func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
-    guard !(value is NSNull) else { return nil }
-
-    if let number = value as? NSNumber {
-      // TODO: Add a flag to coerce non-boolean numbers into Bools?
-      if number === kCFBooleanTrue as NSNumber {
-        return true
-      } else if number === kCFBooleanFalse as NSNumber {
-        return false
-      }
-    }
-
-    throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-  }
-
-  func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let int = number.intValue
-    guard NSNumber(value: int) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return int
-  }
-
-  func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let int8 = number.int8Value
-    guard NSNumber(value: int8) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return int8
-  }
-
-  func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let int16 = number.int16Value
-    guard NSNumber(value: int16) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return int16
-  }
-
-  func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let int32 = number.int32Value
-    guard NSNumber(value: int32) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return int32
-  }
-
-  func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let int64 = number.int64Value
-    guard NSNumber(value: int64) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return int64
-  }
-
-  func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let uint = number.uintValue
-    guard NSNumber(value: uint) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return uint
-  }
-
-  func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let uint8 = number.uint8Value
-    guard NSNumber(value: uint8) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return uint8
-  }
-
-  func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let uint16 = number.uint16Value
-    guard NSNumber(value: uint16) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return uint16
-  }
-
-  func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let uint32 = number.uint32Value
-    guard NSNumber(value: uint32) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return uint32
-  }
-
-  func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let number = value as? NSNumber, number !== kCFBooleanTrue,
-          number !== kCFBooleanFalse else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    let uint64 = number.uint64Value
-    guard NSNumber(value: uint64) == number else {
-      throw DecodingError
-        .dataCorrupted(DecodingError
-          .Context(codingPath: codingPath,
-                   debugDescription: "Decoded number <\(number)> does not fit in \(type)."))
-    }
-
-    return uint64
-  }
-
-  func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
-    guard !(value is NSNull) else { return nil }
-
-    if let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse {
-      // We are willing to return a Float by losing precision:
-      // * If the original value was integral,
-      //   * and the integral value was > Float.greatestFiniteMagnitude, we will fail
-      //   * and the integral value was <= Float.greatestFiniteMagnitude, we are willing to lose precision past 2^24
-      // * If it was a Float, you will get back the precise value
-      // * If it was a Double or Decimal, you will get back the nearest approximation if it will fit
-      let double = number.doubleValue
-      guard abs(double) <= Double(Float.greatestFiniteMagnitude) else {
-        throw DecodingError
-          .dataCorrupted(DecodingError
-            .Context(codingPath: codingPath,
-                     debugDescription: "Decoded number \(number) does not fit in \(type)."))
-      }
-
-      return Float(double)
-    }
-
-    throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-  }
-
-  func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
-    guard !(value is NSNull) else { return nil }
-
-    if let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse {
-      // We are always willing to return the number as a Double:
-      // * If the original value was integral, it is guaranteed to fit in a Double; we are willing to lose precision past 2^53 if you encoded a UInt64 but requested a Double
-      // * If it was a Float or Double, you will get back the precise value
-      // * If it was Decimal, you will get back the nearest approximation
-      return number.doubleValue
-    }
-
-    throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-  }
-
-  func unbox(_ value: Any, as type: String.Type) throws -> String? {
-    guard !(value is NSNull) else { return nil }
-
-    guard let string = value as? String else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-
-    return string
-  }
-
-  func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
-    guard !(value is NSNull) else { return nil }
-    // Firestore returns all dates as Timestamp, converting it to Date so it can be used in custom objects.
-    if let timestamp = value as? Timestamp {
-      return timestamp.dateValue()
-    }
-    guard let date = value as? Date else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-    return date
-  }
-
-  func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
-    guard !(value is NSNull) else { return nil }
-    guard let data = value as? Data else {
-      throw DecodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
-    }
-    return data
-  }
-
-  func unbox(_ value: Any, as _: Decimal.Type) throws -> Decimal? {
-    guard !(value is NSNull) else { return nil }
-
-    // Attempt to bridge from NSDecimalNumber.
-    if let decimal = value as? Decimal {
-      return decimal
-    } else {
-      let doubleValue = try unbox(value, as: Double.self)!
-      return Decimal(doubleValue)
-    }
-  }
-
-  func unbox<T: Decodable>(_ value: Any, as _: T.Type) throws -> T? {
-    if T.self == Date.self || T.self == NSDate.self {
-      guard let date = try unbox(value, as: Date.self) else { return nil }
-      return (date as! T)
-    }
-    if T.self == Data.self || T.self == NSData.self {
-      guard let data = try unbox(value, as: Data.self) else { return nil }
-      return (data as! T)
-    }
-    if T.self == URL.self || T.self == NSURL.self {
-      guard let urlString = try unbox(value, as: String.self) else {
-        return nil
-      }
-      guard let url = URL(string: urlString) else {
-        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
-                                                                debugDescription: "Invalid URL string."))
-      }
-      return (url as! T)
-    }
-    if T.self == Decimal.self || T.self == NSDecimalNumber.self {
-      guard let decimal = try unbox(value, as: Decimal.self) else { return nil }
-      return (decimal as! T)
-    }
-    if let v = value as? T {
-      if isFirestorePassthroughType(v) {
-        // All the native Firestore types that should not be encoded
-        return (value as! T)
-      }
-    }
-
-    // Decoding an embedded container, this requires expanding the storage stack and
-    // then restore after decoding.
-    storage.push(container: value)
-    let decoded = try T(from: self)
-    storage.popContainer()
-    return decoded
-  }
-}
-
-extension DecodingError {
-  static func _typeMismatch(at path: [CodingKey], expectation: Any.Type,
-                            reality: Any) -> DecodingError {
-    let description =
-      "Expected to decode \(expectation) but found \(_typeDescription(of: reality)) instead."
-    return .typeMismatch(expectation, Context(codingPath: path, debugDescription: description))
-  }
-
-  fileprivate static func _typeDescription(of value: Any) -> String {
-    if value is NSNull {
-      return "a null value"
-    } else if value is NSNumber /* FIXME: If swift-corelibs-foundation isn't updated to use NSNumber, this check will be necessary: || value is Int || value is Double */ {
-      return "a number"
-    } else if value is String {
-      return "a string/data"
-    } else if value is [Any] {
-      return "an array"
-    } else if value is [String: Any] {
-      return "a dictionary"
-    } else {
-      return "\(type(of: value))"
-    }
-  }
-}

+ 0 - 655
Firestore/third_party/FirestoreEncoder/FirestoreEncoder.swift

@@ -1,655 +0,0 @@
-// This file is derived from swift/stdlib/public/SDK/Foundation/JSONEncoder.swift
-// and swift/stdlib/public/SDK/Foundation/PlistEncoder.swift
-
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-import FirebaseFirestore
-import Foundation
-
-public extension Firestore {
-  struct Encoder {
-    public init() {}
-    /// Returns encoded data that Firestore API recognizes.
-    ///
-    /// If possible, all types will be converted to compatible types Firestore
-    /// can handle. This means certain Firestore specific types will be encoded
-    /// as pass-through: this encoder will only pass those types along since that
-    /// is what Firestore can handle. The same types will be encoded differently
-    /// with other encoders (for example: JSONEncoder).
-    ///
-    /// The Firestore pass-through types are:
-    ///   - GeoPoint
-    ///   - Timestamp
-    ///   - DocumentReference
-    ///
-    /// - Parameter value: The Encodable object to convert to encoded data.
-    /// - Returns: A Map keyed by String representing a document Firestore
-    ///            API can work with.
-    public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
-      // SelfDocumentID, DocumentReference and FieldValue cannot be
-      // encoded directly.
-      guard T.self != DocumentReference.self,
-            T.self != FieldValue.self else {
-        throw EncodingError
-          .invalidValue(value,
-                        EncodingError
-                          .Context(codingPath: [],
-                                   debugDescription: "Top-level \(T.self) is not allowed."))
-      }
-      guard let topLevel = try _FirestoreEncoder().box_(value) else {
-        throw EncodingError.invalidValue(value,
-                                         EncodingError.Context(codingPath: [],
-                                                               debugDescription: "Top-level \(T.self) did not encode any values."))
-      }
-
-      // This is O(n) check. Consider refactoring box_ to return [String: Any].
-      guard let dict = topLevel as? [String: Any] else {
-        throw EncodingError.invalidValue(value,
-                                         EncodingError.Context(codingPath: [],
-                                                               debugDescription: "Top-level \(T.self) encoded not as dictionary."))
-      }
-      return dict
-    }
-  }
-}
-
-private class _FirestoreEncoder: Encoder {
-  /// A stack of data containers storing encoded results. When a new object is being encoded,
-  /// a corresponding storage is pushed to the stack; and when the field and all of its children objects
-  /// are encoded, the stoage should have the entire encoded result for the sub-tree, it is then poped
-  /// out and written to the proper place of the new stack top container by referencing to the top of `codingPath`.
-  fileprivate var storage: _FirestoreEncodingStorage
-  /// An array used as a stack to keep track of where in the encoded data tree the encoder is trying to process
-  /// at the moment.
-  public fileprivate(set) var codingPath: [CodingKey]
-  public var userInfo: [CodingUserInfoKey: Any] = [:]
-
-  init() {
-    storage = _FirestoreEncodingStorage()
-    codingPath = []
-  }
-
-  /// Returns whether we should allocate new container to store encoded result for the current
-  /// codingPath.
-  ///
-  /// `true` if no container has been allocated for this coding path; `false` otherwise.
-  fileprivate var shouldAllocateNewContainer: Bool {
-    // The encoder starts with storage.count == codingPath.count == 0, which means it is encoding the root
-    // object without any container allocated, so when a container is requested, it must be allocated
-    // first. When a container is requested again with the same codingPath however, for another field from the root object possibly,
-    // because now storage.count == codingPath + 1, we should not allocate new containers because there are
-    // already encoded results in the container. This relation between the two stacks is maintained
-    // throughout the encoding process.
-    return storage.count == codingPath.count
-  }
-
-  // MARK: - Encoder Methods
-
-  public func container<Key>(keyedBy _: Key.Type) -> KeyedEncodingContainer<Key> {
-    // If an existing keyed container was already requested, return that one.
-    let topContainer: NSMutableDictionary
-    if shouldAllocateNewContainer {
-      // We haven't yet pushed a container at this level; do so here.
-      topContainer = storage.pushKeyedContainer()
-    } else {
-      guard let container = storage.containers.last as? NSMutableDictionary else {
-        preconditionFailure(
-          "Attempt to push new keyed encoding container when already previously encoded at this path."
-        )
-      }
-
-      topContainer = container
-    }
-
-    let container = _FirestoreKeyedEncodingContainer<Key>(referencing: self, codingPath: codingPath,
-                                                          wrapping: topContainer)
-    return KeyedEncodingContainer(container)
-  }
-
-  public func unkeyedContainer() -> UnkeyedEncodingContainer {
-    // If an existing unkeyed container was already requested, return that one.
-    let topContainer: NSMutableArray
-    if shouldAllocateNewContainer {
-      // We haven't yet pushed a container at this level; do so here.
-      topContainer = storage.pushUnkeyedContainer()
-    } else {
-      guard let container = storage.containers.last as? NSMutableArray else {
-        preconditionFailure(
-          "Attempt to push new unkeyed encoding container when already previously encoded at this path."
-        )
-      }
-
-      topContainer = container
-    }
-
-    return _FirestoreUnkeyedEncodingContainer(referencing: self, codingPath: codingPath,
-                                              wrapping: topContainer)
-  }
-
-  public func singleValueContainer() -> SingleValueEncodingContainer {
-    return self
-  }
-}
-
-private struct _FirestoreEncodingStorage {
-  // MARK: Properties
-
-  /// The container stack.
-  /// Elements may be any one of the plist types (NSNumber, NSString, NSDate, NSArray, NSDictionary).
-  fileprivate private(set) var containers: [NSObject] = []
-
-  // MARK: - Initialization
-
-  /// Initializes `self` with no containers.
-  fileprivate init() {}
-
-  // MARK: - Modifying the Stack
-
-  fileprivate var count: Int {
-    return containers.count
-  }
-
-  fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
-    let dictionary = NSMutableDictionary()
-    containers.append(dictionary)
-    return dictionary
-  }
-
-  fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
-    let array = NSMutableArray()
-    containers.append(array)
-    return array
-  }
-
-  fileprivate mutating func push(container: NSObject) {
-    containers.append(container)
-  }
-
-  fileprivate mutating func popContainer() -> NSObject {
-    precondition(containers.count > 0, "Empty container stack.")
-    let ret = containers.popLast()!
-    return ret
-  }
-}
-
-private struct _FirestoreKeyedEncodingContainer<K: CodingKey>: KeyedEncodingContainerProtocol {
-  typealias Key = K
-
-  // MARK: Properties
-
-  /// A reference to the encoder we're writing to.
-  private let encoder: _FirestoreEncoder
-
-  /// A reference to the container we're writing to.
-  private let container: NSMutableDictionary
-
-  /// The path of coding keys taken to get to this point in encoding.
-  public private(set) var codingPath: [CodingKey]
-
-  // MARK: - Initialization
-
-  /// Initializes `self` with the given references.
-  fileprivate init(referencing encoder: _FirestoreEncoder,
-                   codingPath: [CodingKey],
-                   wrapping container: NSMutableDictionary) {
-    self.encoder = encoder
-    self.codingPath = codingPath
-    self.container = container
-  }
-
-  // MARK: - KeyedEncodingContainerProtocol Methods
-
-  public mutating func encodeNil(forKey key: Key) throws { container[key.stringValue] = NSNull() }
-  public mutating func encode(_ value: Bool, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Int, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Int8, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Int16, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Int32, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Int64, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: UInt, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: UInt8, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: UInt16, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: UInt32, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: UInt64, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: String, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Float, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode(_ value: Double, forKey key: Key) throws {
-    container[key.stringValue] = encoder.box(value)
-  }
-
-  public mutating func encode<T: Encodable>(_ value: T, forKey key: Key) throws {
-    #if compiler(>=5.1)
-      // `DocumentID`-annotated fields are ignored during encoding.
-      if T.self is DocumentIDProtocol.Type {
-        return
-      }
-    #endif // compiler(>=5.1)
-
-    encoder.codingPath.append(key)
-    defer {
-      encoder.codingPath.removeLast()
-    }
-    container[key.stringValue] = try encoder.box(value)
-  }
-
-  public mutating func nestedContainer<NestedKey>(keyedBy _: NestedKey.Type,
-                                                  forKey key: Key)
-    -> KeyedEncodingContainer<NestedKey> {
-    let dictionary = NSMutableDictionary()
-    self.container[key.stringValue] = dictionary
-
-    codingPath.append(key)
-    defer {
-      codingPath.removeLast()
-    }
-
-    let container = _FirestoreKeyedEncodingContainer<NestedKey>(referencing: encoder,
-                                                                codingPath: codingPath,
-                                                                wrapping: dictionary)
-    return KeyedEncodingContainer(container)
-  }
-
-  public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
-    let array = NSMutableArray()
-    container[key.stringValue] = array
-
-    codingPath.append(key)
-    defer {
-      codingPath.removeLast()
-    }
-    return _FirestoreUnkeyedEncodingContainer(referencing: encoder, codingPath: codingPath,
-                                              wrapping: array)
-  }
-
-  public mutating func superEncoder() -> Encoder {
-    return _FirestoreReferencingEncoder(referencing: encoder, at: _FirestoreKey.super,
-                                        wrapping: container)
-  }
-
-  public mutating func superEncoder(forKey key: Key) -> Encoder {
-    return _FirestoreReferencingEncoder(referencing: encoder, at: key, wrapping: container)
-  }
-}
-
-private struct _FirestoreUnkeyedEncodingContainer: UnkeyedEncodingContainer {
-  // MARK: Properties
-
-  /// A reference to the encoder we're writing to.
-  private let encoder: _FirestoreEncoder
-
-  /// A reference to the container we're writing to.
-  private let container: NSMutableArray
-
-  /// The path of coding keys taken to get to this point in encoding.
-  public private(set) var codingPath: [CodingKey]
-
-  /// The number of elements encoded into the container.
-  public var count: Int {
-    return container.count
-  }
-
-  // MARK: - Initialization
-
-  /// Initializes `self` with the given references.
-  fileprivate init(referencing encoder: _FirestoreEncoder,
-                   codingPath: [CodingKey],
-                   wrapping container: NSMutableArray) {
-    self.encoder = encoder
-    self.codingPath = codingPath
-    self.container = container
-  }
-
-  // MARK: - UnkeyedEncodingContainer Methods
-
-  public mutating func encodeNil() throws { container.add(NSNull()) }
-  public mutating func encode(_ value: Bool) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Int) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Int8) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Int16) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Int32) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Int64) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: UInt) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: UInt8) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: UInt16) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: UInt32) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: UInt64) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Float) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: Double) throws { container.add(encoder.box(value)) }
-  public mutating func encode(_ value: String) throws { container.add(encoder.box(value)) }
-
-  public mutating func encode<T: Encodable>(_ value: T) throws {
-    encoder.codingPath.append(_FirestoreKey(index: count))
-    defer { encoder.codingPath.removeLast()
-    }
-    container.add(try encoder.box(value))
-  }
-
-  public mutating func nestedContainer<NestedKey>(keyedBy _: NestedKey
-    .Type) -> KeyedEncodingContainer<NestedKey> {
-    codingPath.append(_FirestoreKey(index: count))
-    defer {
-      self.codingPath.removeLast()
-    }
-
-    let dictionary = NSMutableDictionary()
-    self.container.add(dictionary)
-
-    let container = _FirestoreKeyedEncodingContainer<NestedKey>(referencing: encoder,
-                                                                codingPath: codingPath,
-                                                                wrapping: dictionary)
-    return KeyedEncodingContainer(container)
-  }
-
-  public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
-    codingPath.append(_FirestoreKey(index: count))
-    defer {
-      self.codingPath.removeLast()
-    }
-
-    let array = NSMutableArray()
-    container.add(array)
-    return _FirestoreUnkeyedEncodingContainer(referencing: encoder, codingPath: codingPath,
-                                              wrapping: array)
-  }
-
-  public mutating func superEncoder() -> Encoder {
-    return _FirestoreReferencingEncoder(referencing: encoder, at: container.count,
-                                        wrapping: container)
-  }
-}
-
-struct _FirestoreKey: CodingKey {
-  public var stringValue: String
-  public var intValue: Int?
-
-  public init?(stringValue: String) {
-    self.stringValue = stringValue
-    intValue = nil
-  }
-
-  public init?(intValue: Int) {
-    stringValue = "\(intValue)"
-    self.intValue = intValue
-  }
-
-  init(index: Int) {
-    stringValue = "Index \(index)"
-    intValue = index
-  }
-
-  static let `super` = _FirestoreKey(stringValue: "super")!
-}
-
-extension _FirestoreEncoder {
-  /// Returns the given value boxed in a container appropriate for pushing onto the container stack.
-  fileprivate func box(_ value: Bool) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Int) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Int8) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Int16) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Int32) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Int64) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: UInt) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: UInt8) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: UInt16) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: UInt32) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: UInt64) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Float) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: Double) -> NSObject { return NSNumber(value: value) }
-  fileprivate func box(_ value: String) -> NSObject { return NSString(string: value) }
-
-  fileprivate func box<T: Encodable>(_ value: T) throws -> NSObject {
-    return try box_(value) ?? NSDictionary()
-  }
-
-  func box_<T: Encodable>(_ value: T) throws -> NSObject? {
-    if T.self == Date.self || T.self == NSDate.self {
-      return (value as! NSDate)
-    } else if T.self == Data.self || T.self == NSData.self {
-      return (value as! NSData)
-    } else if T.self == URL.self || T.self == NSURL.self {
-      return box((value as! URL).absoluteString)
-    } else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
-      return (value as! NSDecimalNumber)
-    } else if isFirestorePassthroughType(value) {
-      // This is a native Firestore types that we don't need to encode.
-      return (value as! NSObject)
-    }
-
-    // The value should request a container from the _FirestoreEncoder.
-    let depth = storage.count
-    do {
-      try value.encode(to: self)
-    } catch {
-      // If the value pushed a container before throwing, pop it back off to restore state.
-      if storage.count > depth {
-        _ = storage.popContainer()
-      }
-
-      throw error
-    }
-
-    // The top container should be a new container.
-    guard storage.count > depth else {
-      return nil
-    }
-
-    return storage.popContainer()
-  }
-}
-
-extension _FirestoreEncoder: SingleValueEncodingContainer {
-  // MARK: - SingleValueEncodingContainer Methods
-
-  private func assertCanEncodeNewValue() {
-    precondition(shouldAllocateNewContainer,
-                 "Attempt to encode value through single value container when previously value already encoded.")
-  }
-
-  public func encodeNil() throws {
-    assertCanEncodeNewValue()
-    storage.push(container: NSNull())
-  }
-
-  public func encode(_ value: Bool) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Int) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Int8) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Int16) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Int32) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Int64) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: UInt) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: UInt8) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: UInt16) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: UInt32) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: UInt64) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: String) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Float) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode(_ value: Double) throws {
-    assertCanEncodeNewValue()
-    storage.push(container: box(value))
-  }
-
-  public func encode<T: Encodable>(_ value: T) throws {
-    assertCanEncodeNewValue()
-    try storage.push(container: box(value))
-  }
-}
-
-/// Special subclass of `_FirestoreEncoder` used by `superEncoder`.
-/// It inherits the codingPath from the referencing `_FirestoreEncoder` but uses its own
-/// storage. The encoded result will be written back to the referencing encoder's storage
-/// when it is `deinit`-ed.
-private class _FirestoreReferencingEncoder: _FirestoreEncoder {
-  // MARK: Reference types.
-
-  /// The type of container we're referencing, and where to write the encoded result to.
-  private enum Reference {
-    /// Referencing a specific index in an array container.
-    case array(NSMutableArray, Int)
-
-    /// Referencing a specific key in a dictionary container.
-    case dictionary(NSMutableDictionary, String)
-  }
-
-  // MARK: - Properties
-
-  /// The encoder we're referencing.
-  private let encoder: _FirestoreEncoder
-
-  /// The container reference itself.
-  private let reference: Reference
-
-  // MARK: - Initialization
-
-  /// Initializes `self` by referencing the given array container in the given encoder.
-  fileprivate init(referencing encoder: _FirestoreEncoder,
-                   at index: Int,
-                   wrapping array: NSMutableArray) {
-    self.encoder = encoder
-    reference = .array(array, index)
-    super.init()
-    codingPath = encoder.codingPath
-
-    codingPath.append(_FirestoreKey(index: index))
-  }
-
-  /// Initializes `self` by referencing the given dictionary container in the given encoder.
-  fileprivate init(referencing encoder: _FirestoreEncoder,
-                   at key: CodingKey,
-                   wrapping dictionary: NSMutableDictionary) {
-    self.encoder = encoder
-    reference = .dictionary(dictionary, key.stringValue)
-    super.init()
-    codingPath = encoder.codingPath
-    codingPath.append(key)
-  }
-
-  // MARK: - Coding Path Operations
-
-  override fileprivate var shouldAllocateNewContainer: Bool {
-    // With a regular encoder, the storage and coding path grow together.
-    // A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
-    // We have to take this into account.
-    return storage.count == codingPath.count - encoder.codingPath.count - 1
-  }
-
-  // MARK: - Deinitialization
-
-  // Finalizes `self` by writing the contents of our storage to the referenced encoder's storage.
-  deinit {
-    let value: Any
-    switch storage.count {
-    case 0: value = NSDictionary()
-    case 1: value = self.storage.popContainer()
-    default: fatalError("Referencing encoder deallocated with multiple containers on stack.")
-    }
-
-    switch self.reference {
-    case let .array(array, index):
-      array.insert(value, at: index)
-
-    case let .dictionary(dictionary, key):
-      dictionary[NSString(string: key)] = value
-    }
-  }
-}

+ 0 - 211
Firestore/third_party/FirestoreEncoder/LICENSE

@@ -1,211 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-    1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-    2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-    3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-    4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-    5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-    6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-    7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-    8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-    9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-    END OF TERMS AND CONDITIONS
-
-    APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-    Copyright [yyyy] [name of copyright owner]
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
-
-
-## Runtime Library Exception to the Apache 2.0 License: ##
-
-
-    As an exception, if you use this Software to compile your source code and
-    portions of this Software are embedded into the binary product as a result,
-    you may redistribute such product without providing attribution as would
-    otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.

+ 0 - 19
Firestore/third_party/FirestoreEncoder/METADATA

@@ -1,19 +0,0 @@
-name: "Swift stdlib"
-description:
-  "This is the FirestoreEncoder and FirestoreDecoder, which are heavily "
-  "modified derivatives of the JSONEncoder and JSONDecoder from the Swift "
-  "stdlib's Foundation framework."
-
-third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://swift.org/"
-  }
-  url {
-    type: GIT
-    value: "https://github.com/apple/swift"
-  }
-  version: "swift-DEVELOPMENT-SNAPSHOT-2019-09-04-a"
-  last_upgrade_date { year: 2019 month: 9 day: 6 }
-  license_type: NOTICE
-}

+ 1 - 4
Package.swift

@@ -719,7 +719,7 @@ let package = Package(
 
     .target(
       name: "FirebaseFirestoreSwift",
-      dependencies: ["FirebaseFirestore"],
+      dependencies: ["FirebaseFirestore", "FirebaseSharedSwift"],
       path: "Firestore",
       exclude: [
         "CHANGELOG.md",
@@ -736,12 +736,9 @@ let package = Package(
         "Swift/README.md",
         "Swift/Tests/",
         "third_party/nlohmann_json",
-        "third_party/FirestoreEncoder/LICENSE",
-        "third_party/FirestoreEncoder/METADATA",
       ],
       sources: [
         "Swift/Source/",
-        "third_party/FirestoreEncoder/",
       ]
     ),