Hendi 3 년 전
커밋
0c6fc693f1
100개의 변경된 파일과 19176개의 추가작업 그리고 0개의 파일을 삭제
  1. 24 0
      Podfile
  2. 188 0
      Podfile.lock
  3. 19 0
      Pods/Alamofire/LICENSE
  4. 205 0
      Pods/Alamofire/README.md
  5. 840 0
      Pods/Alamofire/Source/AFError.swift
  6. 29 0
      Pods/Alamofire/Source/Alamofire.swift
  7. 61 0
      Pods/Alamofire/Source/AlamofireExtended.swift
  8. 91 0
      Pods/Alamofire/Source/CachedResponseHandler.swift
  9. 37 0
      Pods/Alamofire/Source/DispatchQueue+Alamofire.swift
  10. 844 0
      Pods/Alamofire/Source/EventMonitor.swift
  11. 445 0
      Pods/Alamofire/Source/HTTPHeaders.swift
  12. 54 0
      Pods/Alamofire/Source/HTTPMethod.swift
  13. 544 0
      Pods/Alamofire/Source/MultipartFormData.swift
  14. 87 0
      Pods/Alamofire/Source/MultipartUpload.swift
  15. 266 0
      Pods/Alamofire/Source/NetworkReachabilityManager.swift
  16. 115 0
      Pods/Alamofire/Source/Notifications.swift
  17. 49 0
      Pods/Alamofire/Source/OperationQueue+Alamofire.swift
  18. 184 0
      Pods/Alamofire/Source/ParameterEncoder.swift
  19. 314 0
      Pods/Alamofire/Source/ParameterEncoding.swift
  20. 167 0
      Pods/Alamofire/Source/Protector.swift
  21. 95 0
      Pods/Alamofire/Source/RedirectHandler.swift
  22. 1515 0
      Pods/Alamofire/Source/Request.swift
  23. 243 0
      Pods/Alamofire/Source/RequestInterceptor.swift
  24. 140 0
      Pods/Alamofire/Source/RequestTaskMap.swift
  25. 405 0
      Pods/Alamofire/Source/Response.swift
  26. 800 0
      Pods/Alamofire/Source/ResponseSerialization.swift
  27. 109 0
      Pods/Alamofire/Source/Result+Alamofire.swift
  28. 367 0
      Pods/Alamofire/Source/RetryPolicy.swift
  29. 606 0
      Pods/Alamofire/Source/ServerTrustEvaluation.swift
  30. 1067 0
      Pods/Alamofire/Source/Session.swift
  31. 328 0
      Pods/Alamofire/Source/SessionDelegate.swift
  32. 105 0
      Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift
  33. 973 0
      Pods/Alamofire/Source/URLEncodedFormEncoder.swift
  34. 39 0
      Pods/Alamofire/Source/URLRequest+Alamofire.swift
  35. 37 0
      Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift
  36. 247 0
      Pods/Alamofire/Source/Validation.swift
  37. 136 0
      Pods/Firebase/CoreOnly/Sources/Firebase.h
  38. 4 0
      Pods/Firebase/CoreOnly/Sources/module.modulemap
  39. 202 0
      Pods/Firebase/LICENSE
  40. 300 0
      Pods/Firebase/README.md
  41. BIN
      Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector
  42. 11 0
      Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap
  43. BIN
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics
  44. 62 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h
  45. 33 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+Consent.h
  46. 173 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h
  47. 495 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h
  48. 731 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h
  49. 29 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h
  50. 6 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h
  51. 12 0
      Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap
  52. 56 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h
  53. 62 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
  54. 860 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m
  55. 49 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h
  56. 47 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m
  57. 53 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h
  58. 79 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m
  59. 65 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m
  60. 214 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m
  61. 49 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h
  62. 28 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m
  63. 46 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m
  64. 29 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h
  65. 61 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m
  66. 44 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m
  67. 35 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h
  68. 66 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m
  69. 36 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRFirebaseUserAgent.h
  70. 98 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRFirebaseUserAgent.m
  71. 61 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m
  72. 176 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m
  73. 498 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m
  74. 32 0
      Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m
  75. 155 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h
  76. 91 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h
  77. 41 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h
  78. 34 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h
  79. 35 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h
  80. 45 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h
  81. 39 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h
  82. 44 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h
  83. 148 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h
  84. 115 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h
  85. 28 0
      Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h
  86. 127 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRApp.h
  87. 45 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRConfiguration.h
  88. 38 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRLoggerLevel.h
  89. 126 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIROptions.h
  90. 24 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h
  91. 21 0
      Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FirebaseCore.h
  92. 61 0
      Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h
  93. 34 0
      Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h
  94. 202 0
      Pods/FirebaseCore/LICENSE
  95. 300 0
      Pods/FirebaseCore/README.md
  96. 575 0
      Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
  97. 60 0
      Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c
  98. 193 0
      Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h
  99. 18 0
      Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Public/FIRCoreDiagnostics.h
  100. 0 0
      Pods/FirebaseCoreDiagnostics/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h

+ 24 - 0
Podfile

@@ -0,0 +1,24 @@
+project 'Sirani.xcodeproj'
+
+# Uncomment the next line to define a global platform for your project
+# platform :ios, '9.0'
+
+target 'Sirani' do
+  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
+  use_frameworks!
+
+  # Pods for Sirani
+  pod 'Alamofire', '~> 5.0.0-beta.5'
+  pod 'SwiftyJSON', '~> 4.0'
+  pod 'SDWebImage', '~> 4.0'
+  pod 'ImageSlideshow', '~> 1.6'
+  pod 'ImageSlideshow/SDWebImage'
+  pod 'MaterialComponents/Cards'
+  pod 'GoogleMaps', '3.1.0'
+  
+  # Pods for FirebaseStarterKit
+  pod 'Firebase/Core'
+  pod 'Firebase/Messaging'
+  pod 'Firebase/Analytics'
+
+end

+ 188 - 0
Podfile.lock

@@ -0,0 +1,188 @@
+PODS:
+  - Alamofire (5.0.5)
+  - Firebase/Analytics (7.1.0):
+    - Firebase/Core
+  - Firebase/Core (7.1.0):
+    - Firebase/CoreOnly
+    - FirebaseAnalytics (= 7.1.0)
+  - Firebase/CoreOnly (7.1.0):
+    - FirebaseCore (= 7.1.0)
+  - Firebase/Messaging (7.1.0):
+    - Firebase/CoreOnly
+    - FirebaseMessaging (~> 7.1.0)
+  - FirebaseAnalytics (7.1.0):
+    - FirebaseCore (~> 7.0)
+    - FirebaseInstallations (~> 7.0)
+    - GoogleAppMeasurement (= 7.1.0)
+    - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
+    - GoogleUtilities/MethodSwizzler (~> 7.0)
+    - GoogleUtilities/Network (~> 7.0)
+    - "GoogleUtilities/NSData+zlib (~> 7.0)"
+    - nanopb (~> 2.30906.0)
+  - FirebaseCore (7.1.0):
+    - FirebaseCoreDiagnostics (~> 7.0)
+    - GoogleUtilities/Environment (~> 7.0)
+    - GoogleUtilities/Logger (~> 7.0)
+  - FirebaseCoreDiagnostics (7.1.0):
+    - GoogleDataTransport (~> 8.0)
+    - GoogleUtilities/Environment (~> 7.0)
+    - GoogleUtilities/Logger (~> 7.0)
+    - nanopb (~> 2.30906.0)
+  - FirebaseInstallations (7.1.0):
+    - FirebaseCore (~> 7.0)
+    - GoogleUtilities/Environment (~> 7.0)
+    - GoogleUtilities/UserDefaults (~> 7.0)
+    - PromisesObjC (~> 1.2)
+  - FirebaseInstanceID (7.1.0):
+    - FirebaseCore (~> 7.0)
+    - FirebaseInstallations (~> 7.0)
+    - GoogleUtilities/Environment (~> 7.0)
+    - GoogleUtilities/UserDefaults (~> 7.0)
+  - FirebaseMessaging (7.1.0):
+    - FirebaseCore (~> 7.0)
+    - FirebaseInstanceID (~> 7.0)
+    - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
+    - GoogleUtilities/Environment (~> 7.0)
+    - GoogleUtilities/Reachability (~> 7.0)
+    - GoogleUtilities/UserDefaults (~> 7.0)
+  - GoogleAppMeasurement (7.1.0):
+    - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
+    - GoogleUtilities/MethodSwizzler (~> 7.0)
+    - GoogleUtilities/Network (~> 7.0)
+    - "GoogleUtilities/NSData+zlib (~> 7.0)"
+    - nanopb (~> 2.30906.0)
+  - GoogleDataTransport (8.0.1):
+    - nanopb (~> 2.30906.0)
+  - GoogleMaps (3.1.0):
+    - GoogleMaps/Maps (= 3.1.0)
+  - GoogleMaps/Base (3.1.0)
+  - GoogleMaps/Maps (3.1.0):
+    - GoogleMaps/Base
+  - GoogleUtilities/AppDelegateSwizzler (7.1.0):
+    - GoogleUtilities/Environment
+    - GoogleUtilities/Logger
+    - GoogleUtilities/Network
+  - GoogleUtilities/Environment (7.1.0):
+    - PromisesObjC (~> 1.2)
+  - GoogleUtilities/Logger (7.1.0):
+    - GoogleUtilities/Environment
+  - GoogleUtilities/MethodSwizzler (7.1.0):
+    - GoogleUtilities/Logger
+  - GoogleUtilities/Network (7.1.0):
+    - GoogleUtilities/Logger
+    - "GoogleUtilities/NSData+zlib"
+    - GoogleUtilities/Reachability
+  - "GoogleUtilities/NSData+zlib (7.1.0)"
+  - GoogleUtilities/Reachability (7.1.0):
+    - GoogleUtilities/Logger
+  - GoogleUtilities/UserDefaults (7.1.0):
+    - GoogleUtilities/Logger
+  - ImageSlideshow (1.9.1):
+    - ImageSlideshow/Core (= 1.9.1)
+  - ImageSlideshow/Core (1.9.1)
+  - ImageSlideshow/SDWebImage (1.9.1):
+    - ImageSlideshow/Core
+    - SDWebImage (>= 3.7)
+  - MaterialComponents/AnimationTiming (119.1.0)
+  - MaterialComponents/Availability (119.1.0)
+  - MaterialComponents/Cards (119.1.0):
+    - MaterialComponents/Elevation
+    - MaterialComponents/Ink
+    - MaterialComponents/private/Icons/ic_check_circle
+    - MaterialComponents/private/Math
+    - MaterialComponents/Ripple
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Shapes
+  - MaterialComponents/Elevation (119.1.0):
+    - MaterialComponents/Availability
+    - MaterialComponents/private/Color
+    - MaterialComponents/private/Math
+  - MaterialComponents/Ink (119.1.0):
+    - MaterialComponents/Availability
+    - MaterialComponents/private/Color
+    - MaterialComponents/private/Math
+  - MaterialComponents/private/Color (119.1.0):
+    - MaterialComponents/Availability
+  - MaterialComponents/private/Icons/Base (119.1.0)
+  - MaterialComponents/private/Icons/ic_check_circle (119.1.0):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Math (119.1.0)
+  - MaterialComponents/Ripple (119.1.0):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Availability
+    - MaterialComponents/private/Color
+    - MaterialComponents/private/Math
+  - MaterialComponents/ShadowElevations (119.1.0)
+  - MaterialComponents/ShadowLayer (119.1.0):
+    - MaterialComponents/ShadowElevations
+  - MaterialComponents/Shapes (119.1.0):
+    - MaterialComponents/private/Color
+    - MaterialComponents/private/Math
+    - MaterialComponents/ShadowLayer
+  - nanopb (2.30906.0):
+    - nanopb/decode (= 2.30906.0)
+    - nanopb/encode (= 2.30906.0)
+  - nanopb/decode (2.30906.0)
+  - nanopb/encode (2.30906.0)
+  - PromisesObjC (1.2.11)
+  - SDWebImage (4.4.8):
+    - SDWebImage/Core (= 4.4.8)
+  - SDWebImage/Core (4.4.8)
+  - SwiftyJSON (4.3.0)
+
+DEPENDENCIES:
+  - Alamofire (~> 5.0.0-beta.5)
+  - Firebase/Analytics
+  - Firebase/Core
+  - Firebase/Messaging
+  - GoogleMaps (= 3.1.0)
+  - ImageSlideshow (~> 1.6)
+  - ImageSlideshow/SDWebImage
+  - MaterialComponents/Cards
+  - SDWebImage (~> 4.0)
+  - SwiftyJSON (~> 4.0)
+
+SPEC REPOS:
+  trunk:
+    - Alamofire
+    - Firebase
+    - FirebaseAnalytics
+    - FirebaseCore
+    - FirebaseCoreDiagnostics
+    - FirebaseInstallations
+    - FirebaseInstanceID
+    - FirebaseMessaging
+    - GoogleAppMeasurement
+    - GoogleDataTransport
+    - GoogleMaps
+    - GoogleUtilities
+    - ImageSlideshow
+    - MaterialComponents
+    - nanopb
+    - PromisesObjC
+    - SDWebImage
+    - SwiftyJSON
+
+SPEC CHECKSUMS:
+  Alamofire: df2f8f826963b08b9a870791ad48e07a10090b2e
+  Firebase: 78e8dd2e39d653de6270432ad84fe8b59f7bf4e8
+  FirebaseAnalytics: 7f165a56dea86ddd5b8ce02af3bee982c683405c
+  FirebaseCore: 20046127eef0fcb8fa25df7fc12f7b97d4e48611
+  FirebaseCoreDiagnostics: 872cdb9b749b23346dddd5c1014d1babd2257de3
+  FirebaseInstallations: 3de38553e86171b5f81d83cdeef63473d37bfdb0
+  FirebaseInstanceID: 61e8d10a4192a582c6239378169d10e504ca8d91
+  FirebaseMessaging: 076054895c9260f82c7304cc7709dbf19b8f3e4a
+  GoogleAppMeasurement: 89e1a64593f968713b0506ba1b53b38a154bf9a5
+  GoogleDataTransport: e4085e6762f36a6141738f46b0153473ce57fb18
+  GoogleMaps: 5c13302e6fe6bb6e686b267196586b91cd594225
+  GoogleUtilities: f734da554aade8cc7928a31c2f3311897933a1bd
+  ImageSlideshow: 67184be896a28472bd3b906c33ce4e0734aa3d22
+  MaterialComponents: 04f29e3ec4965c29a48e13a626a0ab4bbd19e289
+  nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53
+  PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
+  SDWebImage: 783af2c3fa36291a250030c4752ee370a9a51d13
+  SwiftyJSON: 6faa0040f8b59dead0ee07436cbf76b73c08fd08
+
+PODFILE CHECKSUM: 105f4c100eddf8320c57ac256906df5b70fcf20f
+
+COCOAPODS: 1.9.0.beta.2

+ 19 - 0
Pods/Alamofire/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 205 - 0
Pods/Alamofire/README.md


+ 840 - 0
Pods/Alamofire/Source/AFError.swift

@@ -0,0 +1,840 @@
+//
+//  AFError.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
+/// their own associated reasons.
+public enum AFError: Error {
+    /// The underlying reason the `.multipartEncodingFailed` error occurred.
+    public enum MultipartEncodingFailureReason {
+        /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
+        case bodyPartURLInvalid(url: URL)
+        /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension.
+        case bodyPartFilenameInvalid(in: URL)
+        /// The file at the `fileURL` provided was not reachable.
+        case bodyPartFileNotReachable(at: URL)
+        /// Attempting to check the reachability of the `fileURL` provided threw an error.
+        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
+        /// The file at the `fileURL` provided is actually a directory.
+        case bodyPartFileIsDirectory(at: URL)
+        /// The size of the file at the `fileURL` provided was not returned by the system.
+        case bodyPartFileSizeNotAvailable(at: URL)
+        /// The attempt to find the size of the file at the `fileURL` provided threw an error.
+        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
+        /// An `InputStream` could not be created for the provided `fileURL`.
+        case bodyPartInputStreamCreationFailed(for: URL)
+        /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
+        case outputStreamCreationFailed(for: URL)
+        /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
+        case outputStreamFileAlreadyExists(at: URL)
+        /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
+        case outputStreamURLInvalid(url: URL)
+        /// The attempt to write the encoded body data to disk failed with an underlying error.
+        case outputStreamWriteFailed(error: Error)
+        /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
+        case inputStreamReadFailed(error: Error)
+    }
+
+    /// The underlying reason the `.parameterEncodingFailed` error occurred.
+    public enum ParameterEncodingFailureReason {
+        /// The `URLRequest` did not have a `URL` to encode.
+        case missingURL
+        /// JSON serialization failed with an underlying system error during the encoding process.
+        case jsonEncodingFailed(error: Error)
+        /// Custom parameter encoding failed due to the associated `Error`.
+        case customEncodingFailed(error: Error)
+    }
+
+    /// The underlying reason the `.parameterEncoderFailed` error occurred.
+    public enum ParameterEncoderFailureReason {
+        /// Possible missing components.
+        public enum RequiredComponent {
+            /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
+            case url
+            /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
+            case httpMethod(rawValue: String)
+        }
+
+        /// A `RequiredComponent` was missing during encoding.
+        case missingRequiredComponent(RequiredComponent)
+        /// The underlying encoder failed with the associated error.
+        case encoderFailed(error: Error)
+    }
+
+    /// The underlying reason the `.responseValidationFailed` error occurred.
+    public enum ResponseValidationFailureReason {
+        /// The data file containing the server response did not exist.
+        case dataFileNil
+        /// The data file containing the server response at the associated `URL` could not be read.
+        case dataFileReadFailed(at: URL)
+        /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
+        /// wildcard type.
+        case missingContentType(acceptableContentTypes: [String])
+        /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
+        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
+        /// The response status code was not acceptable.
+        case unacceptableStatusCode(code: Int)
+        /// Custom response validation failed due to the associated `Error`.
+        case customValidationFailed(error: Error)
+    }
+
+    /// The underlying reason the response serialization error occurred.
+    public enum ResponseSerializationFailureReason {
+        /// The server response contained no data or the data was zero length.
+        case inputDataNilOrZeroLength
+        /// The file containing the server response did not exist.
+        case inputFileNil
+        /// The file containing the server response could not be read from the associated `URL`.
+        case inputFileReadFailed(at: URL)
+        /// String serialization failed using the provided `String.Encoding`.
+        case stringSerializationFailed(encoding: String.Encoding)
+        /// JSON serialization failed with an underlying system error.
+        case jsonSerializationFailed(error: Error)
+        /// A `DataDecoder` failed to decode the response due to the associated `Error`.
+        case decodingFailed(error: Error)
+        /// A custom response serializer failed due to the associated `Error`.
+        case customSerializationFailed(error: Error)
+        /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
+        case invalidEmptyResponse(type: String)
+    }
+
+    /// Underlying reason a server trust evaluation error occurred.
+    public enum ServerTrustFailureReason {
+        /// The output of a server trust evaluation.
+        public struct Output {
+            /// The host for which the evaluation was performed.
+            public let host: String
+            /// The `SecTrust` value which was evaluated.
+            public let trust: SecTrust
+            /// The `OSStatus` of evaluation operation.
+            public let status: OSStatus
+            /// The result of the evaluation operation.
+            public let result: SecTrustResultType
+
+            /// Creates an `Output` value from the provided values.
+            init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
+                self.host = host
+                self.trust = trust
+                self.status = status
+                self.result = result
+            }
+        }
+
+        /// No `ServerTrustEvaluator` was found for the associated host.
+        case noRequiredEvaluator(host: String)
+        /// No certificates were found with which to perform the trust evaluation.
+        case noCertificatesFound
+        /// No public keys were found with which to perform the trust evaluation.
+        case noPublicKeysFound
+        /// During evaluation, application of the associated `SecPolicy` failed.
+        case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
+        /// During evaluation, setting the associated anchor certificates failed.
+        case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
+        /// During evaluation, creation of the revocation policy failed.
+        case revocationPolicyCreationFailed
+        /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
+        case trustEvaluationFailed(error: Error?)
+        /// Default evaluation failed with the associated `Output`.
+        case defaultEvaluationFailed(output: Output)
+        /// Host validation failed with the associated `Output`.
+        case hostValidationFailed(output: Output)
+        /// Revocation check failed with the associated `Output` and options.
+        case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
+        /// Certificate pinning failed.
+        case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
+        /// Public key pinning failed.
+        case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
+        /// Custom server trust evaluation failed due to the associated `Error`.
+        case customEvaluationFailed(error: Error)
+    }
+
+    /// The underlying reason the `.urlRequestValidationFailed`
+    public enum URLRequestValidationFailureReason {
+        /// URLRequest with GET method had body data.
+        case bodyDataInGETRequest(Data)
+    }
+
+    ///  `UploadableConvertible` threw an error in `createUploadable()`.
+    case createUploadableFailed(error: Error)
+    ///  `URLRequestConvertible` threw an error in `asURLRequest()`.
+    case createURLRequestFailed(error: Error)
+    /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
+    case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
+    /// `Request` was explicitly cancelled.
+    case explicitlyCancelled
+    /// `URLConvertible` type failed to create a valid `URL`.
+    case invalidURL(url: URLConvertible)
+    /// Multipart form encoding failed.
+    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
+    /// `ParameterEncoding` threw an error during the encoding process.
+    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
+    /// `ParameterEncoder` threw an error while running the encoder.
+    case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
+    /// `RequestAdapter` threw an error during adaptation.
+    case requestAdaptationFailed(error: Error)
+    /// `RequestRetrier` threw an error during the request retry process.
+    case requestRetryFailed(retryError: Error, originalError: Error)
+    /// Response validation failed.
+    case responseValidationFailed(reason: ResponseValidationFailureReason)
+    /// Response serialization failed.
+    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
+    /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
+    case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
+    /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
+    case sessionDeinitialized
+    /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
+    case sessionInvalidated(error: Error?)
+    /// `URLSessionTask` completed with error.
+    case sessionTaskFailed(error: Error)
+    /// `URLRequest` failed validation.
+    case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
+}
+
+extension Error {
+    /// Returns the instance cast as an `AFError`.
+    public var asAFError: AFError? {
+        return self as? AFError
+    }
+
+    /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
+    public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
+        guard let afError = self as? AFError else {
+            fatalError(message(), file: file, line: line)
+        }
+        return afError
+    }
+
+    /// Casts the instance as `AFError` or returns `defaultAFError`
+    func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
+        return self as? AFError ?? defaultAFError()
+    }
+}
+
+// MARK: - Error Booleans
+
+extension AFError {
+    /// Returns whether the instance is `.sessionDeinitialized`.
+    public var isSessionDeinitializedError: Bool {
+        if case .sessionDeinitialized = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.sessionInvalidated`.
+    public var isSessionInvalidatedError: Bool {
+        if case .sessionInvalidated = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.explicitlyCancelled`.
+    public var isExplicitlyCancelledError: Bool {
+        if case .explicitlyCancelled = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.invalidURL`.
+    public var isInvalidURLError: Bool {
+        if case .invalidURL = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isParameterEncodingError: Bool {
+        if case .parameterEncodingFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isParameterEncoderError: Bool {
+        if case .parameterEncoderFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
+    /// properties will contain the associated values.
+    public var isMultipartEncodingError: Bool {
+        if case .multipartEncodingFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isRequestAdaptationError: Bool {
+        if case .requestAdaptationFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
+    /// `responseContentType`,  `responseCode`, and `underlyingError` properties will contain the associated values.
+    public var isResponseValidationError: Bool {
+        if case .responseValidationFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
+    /// `underlyingError` properties will contain the associated values.
+    public var isResponseSerializationError: Bool {
+        if case .responseSerializationFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isServerTrustEvaluationError: Bool {
+        if case .serverTrustEvaluationFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isRequestRetryError: Bool {
+        if case .requestRetryFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isCreateUploadableError: Bool {
+        if case .createUploadableFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isCreateURLRequestError: Bool {
+        if case .createURLRequestFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
+    /// contain the associated values.
+    public var isDownloadedFileMoveError: Bool {
+        if case .downloadedFileMoveFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isSessionTaskError: Bool {
+        if case .sessionTaskFailed = self { return true }
+        return false
+    }
+}
+
+// MARK: - Convenience Properties
+
+extension AFError {
+    /// The `URLConvertible` associated with the error.
+    public var urlConvertible: URLConvertible? {
+        guard case let .invalidURL(url) = self else { return nil }
+        return url
+    }
+
+    /// The `URL` associated with the error.
+    public var url: URL? {
+        guard case let .multipartEncodingFailed(reason) = self else { return nil }
+        return reason.url
+    }
+
+    /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
+    /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
+    /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
+    public var underlyingError: Error? {
+        switch self {
+        case let .multipartEncodingFailed(reason):
+            return reason.underlyingError
+        case let .parameterEncodingFailed(reason):
+            return reason.underlyingError
+        case let .parameterEncoderFailed(reason):
+            return reason.underlyingError
+        case let .requestAdaptationFailed(error):
+            return error
+        case let .requestRetryFailed(retryError, _):
+            return retryError
+        case let .responseValidationFailed(reason):
+            return reason.underlyingError
+        case let .responseSerializationFailed(reason):
+            return reason.underlyingError
+        case let .serverTrustEvaluationFailed(reason):
+            return reason.underlyingError
+        case let .sessionInvalidated(error):
+            return error
+        case let .createUploadableFailed(error):
+            return error
+        case let .createURLRequestFailed(error):
+            return error
+        case let .downloadedFileMoveFailed(error, _, _):
+            return error
+        case let .sessionTaskFailed(error):
+            return error
+        case .explicitlyCancelled,
+             .invalidURL,
+             .sessionDeinitialized,
+             .urlRequestValidationFailed:
+            return nil
+        }
+    }
+
+    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
+    public var acceptableContentTypes: [String]? {
+        guard case let .responseValidationFailed(reason) = self else { return nil }
+        return reason.acceptableContentTypes
+    }
+
+    /// The response `Content-Type` of a `.responseValidationFailed` error.
+    public var responseContentType: String? {
+        guard case let .responseValidationFailed(reason) = self else { return nil }
+        return reason.responseContentType
+    }
+
+    /// The response code of a `.responseValidationFailed` error.
+    public var responseCode: Int? {
+        guard case let .responseValidationFailed(reason) = self else { return nil }
+        return reason.responseCode
+    }
+
+    /// The `String.Encoding` associated with a failed `.stringResponse()` call.
+    public var failedStringEncoding: String.Encoding? {
+        guard case let .responseSerializationFailed(reason) = self else { return nil }
+        return reason.failedStringEncoding
+    }
+
+    /// The `source` URL of a `.downloadedFileMoveFailed` error.
+    public var sourceURL: URL? {
+        guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
+        return source
+    }
+
+    /// The `destination` URL of a `.downloadedFileMoveFailed` error.
+    public var destinationURL: URL? {
+        guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
+        return destination
+    }
+}
+
+extension AFError.ParameterEncodingFailureReason {
+    var underlyingError: Error? {
+        switch self {
+        case let .jsonEncodingFailed(error),
+             let .customEncodingFailed(error):
+            return error
+        case .missingURL:
+            return nil
+        }
+    }
+}
+
+extension AFError.ParameterEncoderFailureReason {
+    var underlyingError: Error? {
+        switch self {
+        case let .encoderFailed(error):
+            return error
+        case .missingRequiredComponent:
+            return nil
+        }
+    }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+    var url: URL? {
+        switch self {
+        case let .bodyPartURLInvalid(url),
+             let .bodyPartFilenameInvalid(url),
+             let .bodyPartFileNotReachable(url),
+             let .bodyPartFileIsDirectory(url),
+             let .bodyPartFileSizeNotAvailable(url),
+             let .bodyPartInputStreamCreationFailed(url),
+             let .outputStreamCreationFailed(url),
+             let .outputStreamFileAlreadyExists(url),
+             let .outputStreamURLInvalid(url),
+             let .bodyPartFileNotReachableWithError(url, _),
+             let .bodyPartFileSizeQueryFailedWithError(url, _):
+            return url
+        case .outputStreamWriteFailed,
+             .inputStreamReadFailed:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case let .bodyPartFileNotReachableWithError(_, error),
+             let .bodyPartFileSizeQueryFailedWithError(_, error),
+             let .outputStreamWriteFailed(error),
+             let .inputStreamReadFailed(error):
+            return error
+        case .bodyPartURLInvalid,
+             .bodyPartFilenameInvalid,
+             .bodyPartFileNotReachable,
+             .bodyPartFileIsDirectory,
+             .bodyPartFileSizeNotAvailable,
+             .bodyPartInputStreamCreationFailed,
+             .outputStreamCreationFailed,
+             .outputStreamFileAlreadyExists,
+             .outputStreamURLInvalid:
+            return nil
+        }
+    }
+}
+
+extension AFError.ResponseValidationFailureReason {
+    var acceptableContentTypes: [String]? {
+        switch self {
+        case let .missingContentType(types),
+             let .unacceptableContentType(types, _):
+            return types
+        case .dataFileNil,
+             .dataFileReadFailed,
+             .unacceptableStatusCode,
+             .customValidationFailed:
+            return nil
+        }
+    }
+
+    var responseContentType: String? {
+        switch self {
+        case let .unacceptableContentType(_, responseType):
+            return responseType
+        case .dataFileNil,
+             .dataFileReadFailed,
+             .missingContentType,
+             .unacceptableStatusCode,
+             .customValidationFailed:
+            return nil
+        }
+    }
+
+    var responseCode: Int? {
+        switch self {
+        case let .unacceptableStatusCode(code):
+            return code
+        case .dataFileNil,
+             .dataFileReadFailed,
+             .missingContentType,
+             .unacceptableContentType,
+             .customValidationFailed:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case let .customValidationFailed(error):
+            return error
+        case .dataFileNil,
+             .dataFileReadFailed,
+             .missingContentType,
+             .unacceptableContentType,
+             .unacceptableStatusCode:
+            return nil
+        }
+    }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+    var failedStringEncoding: String.Encoding? {
+        switch self {
+        case let .stringSerializationFailed(encoding):
+            return encoding
+        case .inputDataNilOrZeroLength,
+             .inputFileNil,
+             .inputFileReadFailed(_),
+             .jsonSerializationFailed(_),
+             .decodingFailed(_),
+             .customSerializationFailed(_),
+             .invalidEmptyResponse:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case let .jsonSerializationFailed(error),
+             let .decodingFailed(error),
+             let .customSerializationFailed(error):
+            return error
+        case .inputDataNilOrZeroLength,
+             .inputFileNil,
+             .inputFileReadFailed,
+             .stringSerializationFailed,
+             .invalidEmptyResponse:
+            return nil
+        }
+    }
+}
+
+extension AFError.ServerTrustFailureReason {
+    var output: AFError.ServerTrustFailureReason.Output? {
+        switch self {
+        case let .defaultEvaluationFailed(output),
+             let .hostValidationFailed(output),
+             let .revocationCheckFailed(output, _):
+            return output
+        case .noRequiredEvaluator,
+             .noCertificatesFound,
+             .noPublicKeysFound,
+             .policyApplicationFailed,
+             .settingAnchorCertificatesFailed,
+             .revocationPolicyCreationFailed,
+             .trustEvaluationFailed,
+             .certificatePinningFailed,
+             .publicKeyPinningFailed,
+             .customEvaluationFailed:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case let .customEvaluationFailed(error):
+            return error
+        case let .trustEvaluationFailed(error):
+            return error
+        case .noRequiredEvaluator,
+             .noCertificatesFound,
+             .noPublicKeysFound,
+             .policyApplicationFailed,
+             .settingAnchorCertificatesFailed,
+             .revocationPolicyCreationFailed,
+             .defaultEvaluationFailed,
+             .hostValidationFailed,
+             .revocationCheckFailed,
+             .certificatePinningFailed,
+             .publicKeyPinningFailed:
+            return nil
+        }
+    }
+}
+
+// MARK: - Error Descriptions
+
+extension AFError: LocalizedError {
+    public var errorDescription: String? {
+        switch self {
+        case .explicitlyCancelled:
+            return "Request explicitly cancelled."
+        case let .invalidURL(url):
+            return "URL is not valid: \(url)"
+        case let .parameterEncodingFailed(reason):
+            return reason.localizedDescription
+        case let .parameterEncoderFailed(reason):
+            return reason.localizedDescription
+        case let .multipartEncodingFailed(reason):
+            return reason.localizedDescription
+        case let .requestAdaptationFailed(error):
+            return "Request adaption failed with error: \(error.localizedDescription)"
+        case let .responseValidationFailed(reason):
+            return reason.localizedDescription
+        case let .responseSerializationFailed(reason):
+            return reason.localizedDescription
+        case let .requestRetryFailed(retryError, originalError):
+            return """
+            Request retry failed with retry error: \(retryError.localizedDescription), \
+            original error: \(originalError.localizedDescription)
+            """
+        case .sessionDeinitialized:
+            return """
+            Session was invalidated without error, so it was likely deinitialized unexpectedly. \
+            Be sure to retain a reference to your Session for the duration of your requests.
+            """
+        case let .sessionInvalidated(error):
+            return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
+        case let .serverTrustEvaluationFailed(reason):
+            return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
+        case let .urlRequestValidationFailed(reason):
+            return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
+        case let .createUploadableFailed(error):
+            return "Uploadable creation failed with error: \(error.localizedDescription)"
+        case let .createURLRequestFailed(error):
+            return "URLRequest creation failed with error: \(error.localizedDescription)"
+        case let .downloadedFileMoveFailed(error, source, destination):
+            return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
+        case let .sessionTaskFailed(error):
+            return "URLSessionTask failed with error: \(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.ParameterEncodingFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .missingURL:
+            return "URL request to encode was missing a URL"
+        case let .jsonEncodingFailed(error):
+            return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
+        case let .customEncodingFailed(error):
+            return "Custom parameter encoder failed with error: \(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.ParameterEncoderFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case let .missingRequiredComponent(component):
+            return "Encoding failed due to a missing request component: \(component)"
+        case let .encoderFailed(error):
+            return "The underlying encoder failed with the error: \(error)"
+        }
+    }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case let .bodyPartURLInvalid(url):
+            return "The URL provided is not a file URL: \(url)"
+        case let .bodyPartFilenameInvalid(url):
+            return "The URL provided does not have a valid filename: \(url)"
+        case let .bodyPartFileNotReachable(url):
+            return "The URL provided is not reachable: \(url)"
+        case let .bodyPartFileNotReachableWithError(url, error):
+            return """
+            The system returned an error while checking the provided URL for reachability.
+            URL: \(url)
+            Error: \(error)
+            """
+        case let .bodyPartFileIsDirectory(url):
+            return "The URL provided is a directory: \(url)"
+        case let .bodyPartFileSizeNotAvailable(url):
+            return "Could not fetch the file size from the provided URL: \(url)"
+        case let .bodyPartFileSizeQueryFailedWithError(url, error):
+            return """
+            The system returned an error while attempting to fetch the file size from the provided URL.
+            URL: \(url)
+            Error: \(error)
+            """
+        case let .bodyPartInputStreamCreationFailed(url):
+            return "Failed to create an InputStream for the provided URL: \(url)"
+        case let .outputStreamCreationFailed(url):
+            return "Failed to create an OutputStream for URL: \(url)"
+        case let .outputStreamFileAlreadyExists(url):
+            return "A file already exists at the provided URL: \(url)"
+        case let .outputStreamURLInvalid(url):
+            return "The provided OutputStream URL is invalid: \(url)"
+        case let .outputStreamWriteFailed(error):
+            return "OutputStream write failed with error: \(error)"
+        case let .inputStreamReadFailed(error):
+            return "InputStream read failed with error: \(error)"
+        }
+    }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .inputDataNilOrZeroLength:
+            return "Response could not be serialized, input data was nil or zero length."
+        case .inputFileNil:
+            return "Response could not be serialized, input file was nil."
+        case let .inputFileReadFailed(url):
+            return "Response could not be serialized, input file could not be read: \(url)."
+        case let .stringSerializationFailed(encoding):
+            return "String could not be serialized with encoding: \(encoding)."
+        case let .jsonSerializationFailed(error):
+            return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
+        case let .invalidEmptyResponse(type):
+            return """
+            Empty response could not be serialized to type: \(type). \
+            Use Empty as the expected type for such responses.
+            """
+        case let .decodingFailed(error):
+            return "Response could not be decoded because of error:\n\(error.localizedDescription)"
+        case let .customSerializationFailed(error):
+            return "Custom response serializer failed with error:\n\(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.ResponseValidationFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .dataFileNil:
+            return "Response could not be validated, data file was nil."
+        case let .dataFileReadFailed(url):
+            return "Response could not be validated, data file could not be read: \(url)."
+        case let .missingContentType(types):
+            return """
+            Response Content-Type was missing and acceptable content types \
+            (\(types.joined(separator: ","))) do not match "*/*".
+            """
+        case let .unacceptableContentType(acceptableTypes, responseType):
+            return """
+            Response Content-Type "\(responseType)" does not match any acceptable types: \
+            \(acceptableTypes.joined(separator: ",")).
+            """
+        case let .unacceptableStatusCode(code):
+            return "Response status code was unacceptable: \(code)."
+        case let .customValidationFailed(error):
+            return "Custom response validation failed with error: \(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.ServerTrustFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case let .noRequiredEvaluator(host):
+            return "A ServerTrustEvaluating value is required for host \(host) but none was found."
+        case .noCertificatesFound:
+            return "No certificates were found or provided for evaluation."
+        case .noPublicKeysFound:
+            return "No public keys were found or provided for evaluation."
+        case .policyApplicationFailed:
+            return "Attempting to set a SecPolicy failed."
+        case .settingAnchorCertificatesFailed:
+            return "Attempting to set the provided certificates as anchor certificates failed."
+        case .revocationPolicyCreationFailed:
+            return "Attempting to create a revocation policy failed."
+        case let .trustEvaluationFailed(error):
+            return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
+        case let .defaultEvaluationFailed(output):
+            return "Default evaluation failed for host \(output.host)."
+        case let .hostValidationFailed(output):
+            return "Host validation failed for host \(output.host)."
+        case let .revocationCheckFailed(output, _):
+            return "Revocation check failed for host \(output.host)."
+        case let .certificatePinningFailed(host, _, _, _):
+            return "Certificate pinning failed for host \(host)."
+        case let .publicKeyPinningFailed(host, _, _, _):
+            return "Public key pinning failed for host \(host)."
+        case let .customEvaluationFailed(error):
+            return "Custom trust evaluation failed with error: \(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.URLRequestValidationFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case let .bodyDataInGETRequest(data):
+            return """
+            Invalid URLRequest: Requests with GET method cannot have body data:
+            \(String(decoding: data, as: UTF8.self))
+            """
+        }
+    }
+}

+ 29 - 0
Pods/Alamofire/Source/Alamofire.swift

@@ -0,0 +1,29 @@
+//
+//  Alamofire.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+/// Reference to `Session.default` for quick bootstrapping and examples.
+public let AF = Session.default
+
+/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
+let version = "5.0.5"

+ 61 - 0
Pods/Alamofire/Source/AlamofireExtended.swift

@@ -0,0 +1,61 @@
+//
+//  AlamofireExtended.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+/// Type that acts as a generic extension point for all `AlamofireExtended` types.
+public struct AlamofireExtension<ExtendedType> {
+    /// Stores the type or meta-type of any extended type.
+    public private(set) var type: ExtendedType
+
+    /// Create an instance from the provided value.
+    ///
+    /// - Parameter type: Instance being extended.
+    public init(_ type: ExtendedType) {
+        self.type = type
+    }
+}
+
+/// Protocol describing the `af` extension points for Alamofire extended types.
+public protocol AlamofireExtended {
+    /// Type being extended.
+    associatedtype ExtendedType
+
+    /// Static Alamofire extension point.
+    static var af: AlamofireExtension<ExtendedType>.Type { get set }
+    /// Instance Alamofire extension point.
+    var af: AlamofireExtension<ExtendedType> { get set }
+}
+
+public extension AlamofireExtended {
+    /// Static Alamofire extension point.
+    static var af: AlamofireExtension<Self>.Type {
+        get { return AlamofireExtension<Self>.self }
+        set {}
+    }
+
+    /// Instance Alamofire extension point.
+    var af: AlamofireExtension<Self> {
+        get { return AlamofireExtension(self) }
+        set {}
+    }
+}

+ 91 - 0
Pods/Alamofire/Source/CachedResponseHandler.swift

@@ -0,0 +1,91 @@
+//
+//  CachedResponseHandler.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that handles whether the data task should store the HTTP response in the cache.
+public protocol CachedResponseHandler {
+    /// Determines whether the HTTP response should be stored in the cache.
+    ///
+    /// The `completion` closure should be passed one of three possible options:
+    ///
+    ///   1. The cached response provided by the server (this is the most common use case).
+    ///   2. A modified version of the cached response (you may want to modify it in some way before caching).
+    ///   3. A `nil` value to prevent the cached response from being stored in the cache.
+    ///
+    /// - Parameters:
+    ///   - task:       The data task whose request resulted in the cached response.
+    ///   - response:   The cached response to potentially store in the cache.
+    ///   - completion: The closure to execute containing cached response, a modified response, or `nil`.
+    func dataTask(_ task: URLSessionDataTask,
+                  willCacheResponse response: CachedURLResponse,
+                  completion: @escaping (CachedURLResponse?) -> Void)
+}
+
+// MARK: -
+
+/// `ResponseCacher` is a convenience `CachedResponseHandler` making it easy to cache, not cache, or modify a cached
+/// response.
+public struct ResponseCacher {
+    /// Defines the behavior of the `ResponseCacher` type.
+    public enum Behavior {
+        /// Stores the cached response in the cache.
+        case cache
+        /// Prevents the cached response from being stored in the cache.
+        case doNotCache
+        /// Modifies the cached response before storing it in the cache.
+        case modify((URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)
+    }
+
+    /// Returns a `ResponseCacher` with a follow `Behavior`.
+    public static let cache = ResponseCacher(behavior: .cache)
+    /// Returns a `ResponseCacher` with a do not follow `Behavior`.
+    public static let doNotCache = ResponseCacher(behavior: .doNotCache)
+
+    /// The `Behavior` of the `ResponseCacher`.
+    public let behavior: Behavior
+
+    /// Creates a `ResponseCacher` instance from the `Behavior`.
+    ///
+    /// - Parameter behavior: The `Behavior`.
+    public init(behavior: Behavior) {
+        self.behavior = behavior
+    }
+}
+
+extension ResponseCacher: CachedResponseHandler {
+    public func dataTask(_ task: URLSessionDataTask,
+                         willCacheResponse response: CachedURLResponse,
+                         completion: @escaping (CachedURLResponse?) -> Void) {
+        switch behavior {
+        case .cache:
+            completion(response)
+        case .doNotCache:
+            completion(nil)
+        case let .modify(closure):
+            let response = closure(task, response)
+            completion(response)
+        }
+    }
+}

+ 37 - 0
Pods/Alamofire/Source/DispatchQueue+Alamofire.swift

@@ -0,0 +1,37 @@
+//
+//  DispatchQueue+Alamofire.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Dispatch
+import Foundation
+
+extension DispatchQueue {
+    /// Execute the provided closure after a `TimeInterval`.
+    ///
+    /// - Parameters:
+    ///   - delay:   `TimeInterval` to delay execution.
+    ///   - closure: Closure to execute.
+    func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
+        asyncAfter(deadline: .now() + delay, execute: closure)
+    }
+}

+ 844 - 0
Pods/Alamofire/Source/EventMonitor.swift

@@ -0,0 +1,844 @@
+//
+//  EventMonitor.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Protocol outlining the lifetime events inside Alamofire. It includes both events received from the various
+/// `URLSession` delegate protocols as well as various events from the lifetime of `Request` and its subclasses.
+public protocol EventMonitor {
+    /// The `DispatchQueue` onto which Alamofire's root `CompositeEventMonitor` will dispatch events. `.main` by default.
+    var queue: DispatchQueue { get }
+
+    // MARK: - URLSession Events
+
+    // MARK: URLSessionDelegate Events
+
+    /// Event called during `URLSessionDelegate`'s `urlSession(_:didBecomeInvalidWithError:)` method.
+    func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?)
+
+    // MARK: URLSessionTaskDelegate Events
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didReceive:completionHandler:)` method.
+    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` method.
+    func urlSession(_ session: URLSession,
+                    task: URLSessionTask,
+                    didSendBodyData bytesSent: Int64,
+                    totalBytesSent: Int64,
+                    totalBytesExpectedToSend: Int64)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:needNewBodyStream:)` method.
+    func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` method.
+    func urlSession(_ session: URLSession,
+                    task: URLSessionTask,
+                    willPerformHTTPRedirection response: HTTPURLResponse,
+                    newRequest request: URLRequest)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didFinishCollecting:)` method.
+    func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:task:didCompleteWithError:)` method.
+    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
+
+    /// Event called during `URLSessionTaskDelegate`'s `urlSession(_:taskIsWaitingForConnectivity:)` method.
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask)
+
+    // MARK: URLSessionDataDelegate Events
+
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
+
+    /// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:willCacheResponse:completionHandler:)` method.
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse)
+
+    // MARK: URLSessionDownloadDelegate Events
+
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` method.
+    func urlSession(_ session: URLSession,
+                    downloadTask: URLSessionDownloadTask,
+                    didResumeAtOffset fileOffset: Int64,
+                    expectedTotalBytes: Int64)
+
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)` method.
+    func urlSession(_ session: URLSession,
+                    downloadTask: URLSessionDownloadTask,
+                    didWriteData bytesWritten: Int64,
+                    totalBytesWritten: Int64,
+                    totalBytesExpectedToWrite: Int64)
+
+    /// Event called during `URLSessionDownloadDelegate`'s `urlSession(_:downloadTask:didFinishDownloadingTo:)` method.
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
+
+    // MARK: - Request Events
+
+    /// Event called when a `URLRequest` is first created for a `Request`. If a `RequestAdapter` is active, the
+    /// `URLRequest` will be adapted before being issued.
+    func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest)
+
+    /// Event called when the attempt to create a `URLRequest` from a `Request`'s original `URLRequestConvertible` value fails.
+    func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError)
+
+    /// Event called when a `RequestAdapter` adapts the `Request`'s initial `URLRequest`.
+    func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest)
+
+    /// Event called when a `RequestAdapter` fails to adapt the `Request`'s initial `URLRequest`.
+    func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError)
+
+    /// Event called when a final `URLRequest` is created for a `Request`.
+    func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest)
+
+    /// Event called when a `URLSessionTask` subclass instance is created for a `Request`.
+    func request(_ request: Request, didCreateTask task: URLSessionTask)
+
+    /// Event called when a `Request` receives a `URLSessionTaskMetrics` value.
+    func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics)
+
+    /// Event called when a `Request` fails due to an error created by Alamofire. e.g. When certificate pinning fails.
+    func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError)
+
+    /// Event called when a `Request`'s task completes, possibly with an error. A `Request` may receive this event
+    /// multiple times if it is retried.
+    func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?)
+
+    /// Event called when a `Request` is about to be retried.
+    func requestIsRetrying(_ request: Request)
+
+    /// Event called when a `Request` finishes and response serializers are being called.
+    func requestDidFinish(_ request: Request)
+
+    /// Event called when a `Request` receives a `resume` call.
+    func requestDidResume(_ request: Request)
+
+    /// Event called when a `Request`'s associated `URLSessionTask` is resumed.
+    func request(_ request: Request, didResumeTask task: URLSessionTask)
+
+    /// Event called when a `Request` receives a `suspend` call.
+    func requestDidSuspend(_ request: Request)
+
+    /// Event called when a `Request`'s associated `URLSessionTask` is suspended.
+    func request(_ request: Request, didSuspendTask task: URLSessionTask)
+
+    /// Event called when a `Request` receives a `cancel` call.
+    func requestDidCancel(_ request: Request)
+
+    /// Event called when a `Request`'s associated `URLSessionTask` is cancelled.
+    func request(_ request: Request, didCancelTask task: URLSessionTask)
+
+    // MARK: DataRequest Events
+
+    /// Event called when a `DataRequest` calls a `Validation`.
+    func request(_ request: DataRequest,
+                 didValidateRequest urlRequest: URLRequest?,
+                 response: HTTPURLResponse,
+                 data: Data?,
+                 withResult result: Request.ValidationResult)
+
+    /// Event called when a `DataRequest` creates a `DataResponse<Data?>` value without calling a `ResponseSerializer`.
+    func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>)
+
+    /// Event called when a `DataRequest` calls a `ResponseSerializer` and creates a generic `DataResponse<Value, AFError>`.
+    func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>)
+
+    // MARK: UploadRequest Events
+
+    /// Event called when an `UploadRequest` creates its `Uploadable` value, indicating the type of upload it represents.
+    func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable)
+
+    /// Event called when an `UploadRequest` failed to create its `Uploadable` value due to an error.
+    func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError)
+
+    /// Event called when an `UploadRequest` provides the `InputStream` from its `Uploadable` value. This only occurs if
+    /// the `InputStream` does not wrap a `Data` value or file `URL`.
+    func request(_ request: UploadRequest, didProvideInputStream stream: InputStream)
+
+    // MARK: DownloadRequest Events
+
+    /// Event called when a `DownloadRequest`'s `URLSessionDownloadTask` finishes and the temporary file has been moved.
+    func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>)
+
+    /// Event called when a `DownloadRequest`'s `Destination` closure is called and creates the destination URL the
+    /// downloaded file will be moved to.
+    func request(_ request: DownloadRequest, didCreateDestinationURL url: URL)
+
+    /// Event called when a `DownloadRequest` calls a `Validation`.
+    func request(_ request: DownloadRequest,
+                 didValidateRequest urlRequest: URLRequest?,
+                 response: HTTPURLResponse,
+                 fileURL: URL?,
+                 withResult result: Request.ValidationResult)
+
+    /// Event called when a `DownloadRequest` creates a `DownloadResponse<URL?, AFError>` without calling a `ResponseSerializer`.
+    func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>)
+
+    /// Event called when a `DownloadRequest` calls a `DownloadResponseSerializer` and creates a generic `DownloadResponse<Value, AFError>`
+    func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>)
+}
+
+extension EventMonitor {
+    /// The default queue on which `CompositeEventMonitor`s will call the `EventMonitor` methods. `.main` by default.
+    public var queue: DispatchQueue { return .main }
+
+    // MARK: Default Implementations
+
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {}
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           didReceive challenge: URLAuthenticationChallenge) {}
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           didSendBodyData bytesSent: Int64,
+                           totalBytesSent: Int64,
+                           totalBytesExpectedToSend: Int64) {}
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {}
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           willPerformHTTPRedirection response: HTTPURLResponse,
+                           newRequest request: URLRequest) {}
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           didFinishCollecting metrics: URLSessionTaskMetrics) {}
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
+    public func urlSession(_ session: URLSession,
+                           dataTask: URLSessionDataTask,
+                           willCacheResponse proposedResponse: CachedURLResponse) {}
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didResumeAtOffset fileOffset: Int64,
+                           expectedTotalBytes: Int64) {}
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didWriteData bytesWritten: Int64,
+                           totalBytesWritten: Int64,
+                           totalBytesExpectedToWrite: Int64) {}
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didFinishDownloadingTo location: URL) {}
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {}
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {}
+    public func request(_ request: Request,
+                        didAdaptInitialRequest initialRequest: URLRequest,
+                        to adaptedRequest: URLRequest) {}
+    public func request(_ request: Request,
+                        didFailToAdaptURLRequest initialRequest: URLRequest,
+                        withError error: AFError) {}
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {}
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {}
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {}
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {}
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {}
+    public func requestIsRetrying(_ request: Request) {}
+    public func requestDidFinish(_ request: Request) {}
+    public func requestDidResume(_ request: Request) {}
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {}
+    public func requestDidSuspend(_ request: Request) {}
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {}
+    public func requestDidCancel(_ request: Request) {}
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {}
+    public func request(_ request: DataRequest,
+                        didValidateRequest urlRequest: URLRequest?,
+                        response: HTTPURLResponse,
+                        data: Data?,
+                        withResult result: Request.ValidationResult) {}
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {}
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {}
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {}
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {}
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {}
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {}
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {}
+    public func request(_ request: DownloadRequest,
+                        didValidateRequest urlRequest: URLRequest?,
+                        response: HTTPURLResponse,
+                        fileURL: URL?,
+                        withResult result: Request.ValidationResult) {}
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {}
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {}
+}
+
+/// An `EventMonitor` which can contain multiple `EventMonitor`s and calls their methods on their queues.
+public final class CompositeEventMonitor: EventMonitor {
+    public let queue = DispatchQueue(label: "org.alamofire.compositeEventMonitor", qos: .background)
+
+    let monitors: [EventMonitor]
+
+    init(monitors: [EventMonitor]) {
+        self.monitors = monitors
+    }
+
+    func performEvent(_ event: @escaping (EventMonitor) -> Void) {
+        queue.async {
+            for monitor in self.monitors {
+                monitor.queue.async { event(monitor) }
+            }
+        }
+    }
+
+    public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
+        performEvent { $0.urlSession(session, didBecomeInvalidWithError: error) }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           didReceive challenge: URLAuthenticationChallenge) {
+        performEvent { $0.urlSession(session, task: task, didReceive: challenge) }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           didSendBodyData bytesSent: Int64,
+                           totalBytesSent: Int64,
+                           totalBytesExpectedToSend: Int64) {
+        performEvent {
+            $0.urlSession(session,
+                          task: task,
+                          didSendBodyData: bytesSent,
+                          totalBytesSent: totalBytesSent,
+                          totalBytesExpectedToSend: totalBytesExpectedToSend)
+        }
+    }
+
+    public func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
+        performEvent {
+            $0.urlSession(session, taskNeedsNewBodyStream: task)
+        }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           task: URLSessionTask,
+                           willPerformHTTPRedirection response: HTTPURLResponse,
+                           newRequest request: URLRequest) {
+        performEvent {
+            $0.urlSession(session,
+                          task: task,
+                          willPerformHTTPRedirection: response,
+                          newRequest: request)
+        }
+    }
+
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
+        performEvent { $0.urlSession(session, task: task, didFinishCollecting: metrics) }
+    }
+
+    public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        performEvent { $0.urlSession(session, task: task, didCompleteWithError: error) }
+    }
+
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
+        performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
+    }
+
+    public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           dataTask: URLSessionDataTask,
+                           willCacheResponse proposedResponse: CachedURLResponse) {
+        performEvent { $0.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse) }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didResumeAtOffset fileOffset: Int64,
+                           expectedTotalBytes: Int64) {
+        performEvent {
+            $0.urlSession(session,
+                          downloadTask: downloadTask,
+                          didResumeAtOffset: fileOffset,
+                          expectedTotalBytes: expectedTotalBytes)
+        }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didWriteData bytesWritten: Int64,
+                           totalBytesWritten: Int64,
+                           totalBytesExpectedToWrite: Int64) {
+        performEvent {
+            $0.urlSession(session,
+                          downloadTask: downloadTask,
+                          didWriteData: bytesWritten,
+                          totalBytesWritten: totalBytesWritten,
+                          totalBytesExpectedToWrite: totalBytesExpectedToWrite)
+        }
+    }
+
+    public func urlSession(_ session: URLSession,
+                           downloadTask: URLSessionDownloadTask,
+                           didFinishDownloadingTo location: URL) {
+        performEvent { $0.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) }
+    }
+
+    public func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
+        performEvent { $0.request(request, didCreateInitialURLRequest: urlRequest) }
+    }
+
+    public func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
+        performEvent { $0.request(request, didFailToCreateURLRequestWithError: error) }
+    }
+
+    public func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
+        performEvent { $0.request(request, didAdaptInitialRequest: initialRequest, to: adaptedRequest) }
+    }
+
+    public func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
+        performEvent { $0.request(request, didFailToAdaptURLRequest: initialRequest, withError: error) }
+    }
+
+    public func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
+        performEvent { $0.request(request, didCreateURLRequest: urlRequest) }
+    }
+
+    public func request(_ request: Request, didCreateTask task: URLSessionTask) {
+        performEvent { $0.request(request, didCreateTask: task) }
+    }
+
+    public func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
+        performEvent { $0.request(request, didGatherMetrics: metrics) }
+    }
+
+    public func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
+        performEvent { $0.request(request, didFailTask: task, earlyWithError: error) }
+    }
+
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
+        performEvent { $0.request(request, didCompleteTask: task, with: error) }
+    }
+
+    public func requestIsRetrying(_ request: Request) {
+        performEvent { $0.requestIsRetrying(request) }
+    }
+
+    public func requestDidFinish(_ request: Request) {
+        performEvent { $0.requestDidFinish(request) }
+    }
+
+    public func requestDidResume(_ request: Request) {
+        performEvent { $0.requestDidResume(request) }
+    }
+
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
+        performEvent { $0.request(request, didResumeTask: task) }
+    }
+
+    public func requestDidSuspend(_ request: Request) {
+        performEvent { $0.requestDidSuspend(request) }
+    }
+
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
+        performEvent { $0.request(request, didSuspendTask: task) }
+    }
+
+    public func requestDidCancel(_ request: Request) {
+        performEvent { $0.requestDidCancel(request) }
+    }
+
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
+        performEvent { $0.request(request, didCancelTask: task) }
+    }
+
+    public func request(_ request: DataRequest,
+                        didValidateRequest urlRequest: URLRequest?,
+                        response: HTTPURLResponse,
+                        data: Data?,
+                        withResult result: Request.ValidationResult) {
+        performEvent { $0.request(request,
+                                  didValidateRequest: urlRequest,
+                                  response: response,
+                                  data: data,
+                                  withResult: result)
+        }
+    }
+
+    public func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
+        performEvent { $0.request(request, didParseResponse: response) }
+    }
+
+    public func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
+        performEvent { $0.request(request, didParseResponse: response) }
+    }
+
+    public func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
+        performEvent { $0.request(request, didCreateUploadable: uploadable) }
+    }
+
+    public func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
+        performEvent { $0.request(request, didFailToCreateUploadableWithError: error) }
+    }
+
+    public func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
+        performEvent { $0.request(request, didProvideInputStream: stream) }
+    }
+
+    public func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
+        performEvent { $0.request(request, didFinishDownloadingUsing: task, with: result) }
+    }
+
+    public func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
+        performEvent { $0.request(request, didCreateDestinationURL: url) }
+    }
+
+    public func request(_ request: DownloadRequest,
+                        didValidateRequest urlRequest: URLRequest?,
+                        response: HTTPURLResponse,
+                        fileURL: URL?,
+                        withResult result: Request.ValidationResult) {
+        performEvent { $0.request(request,
+                                  didValidateRequest: urlRequest,
+                                  response: response,
+                                  fileURL: fileURL,
+                                  withResult: result) }
+    }
+
+    public func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
+        performEvent { $0.request(request, didParseResponse: response) }
+    }
+
+    public func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {
+        performEvent { $0.request(request, didParseResponse: response) }
+    }
+}
+
+/// `EventMonitor` that allows optional closures to be set to receive events.
+open class ClosureEventMonitor: EventMonitor {
+    /// Closure called on the `urlSession(_:didBecomeInvalidWithError:)` event.
+    open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
+
+    /// Closure called on the `urlSession(_:task:didReceive:completionHandler:)`.
+    open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> Void)?
+
+    /// Closure that receives `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)` event.
+    open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
+
+    /// Closure called on the `urlSession(_:task:needNewBodyStream:)` event.
+    open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> Void)?
+
+    /// Closure called on the `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` event.
+    open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> Void)?
+
+    /// Closure called on the `urlSession(_:task:didFinishCollecting:)` event.
+    open var taskDidFinishCollectingMetrics: ((URLSession, URLSessionTask, URLSessionTaskMetrics) -> Void)?
+
+    /// Closure called on the `urlSession(_:task:didCompleteWithError:)` event.
+    open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
+
+    /// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
+    open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
+
+    /// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
+    open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
+
+    /// Closure called on the `urlSession(_:dataTask:willCacheResponse:completionHandler:)` event.
+    open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> Void)?
+
+    /// Closure called on the `urlSession(_:downloadTask:didFinishDownloadingTo:)` event.
+    open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
+
+    /// Closure called on the `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`
+    /// event.
+    open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
+
+    /// Closure called on the `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)` event.
+    open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
+
+    // MARK: - Request Events
+
+    /// Closure called on the `request(_:didCreateInitialURLRequest:)` event.
+    open var requestDidCreateInitialURLRequest: ((Request, URLRequest) -> Void)?
+
+    /// Closure called on the `request(_:didFailToCreateURLRequestWithError:)` event.
+    open var requestDidFailToCreateURLRequestWithError: ((Request, AFError) -> Void)?
+
+    /// Closure called on the `request(_:didAdaptInitialRequest:to:)` event.
+    open var requestDidAdaptInitialRequestToAdaptedRequest: ((Request, URLRequest, URLRequest) -> Void)?
+
+    /// Closure called on the `request(_:didFailToAdaptURLRequest:withError:)` event.
+    open var requestDidFailToAdaptURLRequestWithError: ((Request, URLRequest, AFError) -> Void)?
+
+    /// Closure called on the `request(_:didCreateURLRequest:)` event.
+    open var requestDidCreateURLRequest: ((Request, URLRequest) -> Void)?
+
+    /// Closure called on the `request(_:didCreateTask:)` event.
+    open var requestDidCreateTask: ((Request, URLSessionTask) -> Void)?
+
+    /// Closure called on the `request(_:didGatherMetrics:)` event.
+    open var requestDidGatherMetrics: ((Request, URLSessionTaskMetrics) -> Void)?
+
+    /// Closure called on the `request(_:didFailTask:earlyWithError:)` event.
+    open var requestDidFailTaskEarlyWithError: ((Request, URLSessionTask, AFError) -> Void)?
+
+    /// Closure called on the `request(_:didCompleteTask:with:)` event.
+    open var requestDidCompleteTaskWithError: ((Request, URLSessionTask, AFError?) -> Void)?
+
+    /// Closure called on the `requestIsRetrying(_:)` event.
+    open var requestIsRetrying: ((Request) -> Void)?
+
+    /// Closure called on the `requestDidFinish(_:)` event.
+    open var requestDidFinish: ((Request) -> Void)?
+
+    /// Closure called on the `requestDidResume(_:)` event.
+    open var requestDidResume: ((Request) -> Void)?
+
+    /// Closure called on the `request(_:didResumeTask:)` event.
+    open var requestDidResumeTask: ((Request, URLSessionTask) -> Void)?
+
+    /// Closure called on the `requestDidSuspend(_:)` event.
+    open var requestDidSuspend: ((Request) -> Void)?
+
+    /// Closure called on the `request(_:didSuspendTask:)` event.
+    open var requestDidSuspendTask: ((Request, URLSessionTask) -> Void)?
+
+    /// Closure called on the `requestDidCancel(_:)` event.
+    open var requestDidCancel: ((Request) -> Void)?
+
+    /// Closure called on the `request(_:didCancelTask:)` event.
+    open var requestDidCancelTask: ((Request, URLSessionTask) -> Void)?
+
+    /// Closure called on the `request(_:didValidateRequest:response:data:withResult:)` event.
+    open var requestDidValidateRequestResponseDataWithResult: ((DataRequest, URLRequest?, HTTPURLResponse, Data?, Request.ValidationResult) -> Void)?
+
+    /// Closure called on the `request(_:didParseResponse:)` event.
+    open var requestDidParseResponse: ((DataRequest, DataResponse<Data?, AFError>) -> Void)?
+
+    /// Closure called on the `request(_:didCreateUploadable:)` event.
+    open var requestDidCreateUploadable: ((UploadRequest, UploadRequest.Uploadable) -> Void)?
+
+    /// Closure called on the `request(_:didFailToCreateUploadableWithError:)` event.
+    open var requestDidFailToCreateUploadableWithError: ((UploadRequest, AFError) -> Void)?
+
+    /// Closure called on the `request(_:didProvideInputStream:)` event.
+    open var requestDidProvideInputStream: ((UploadRequest, InputStream) -> Void)?
+
+    /// Closure called on the `request(_:didFinishDownloadingUsing:with:)` event.
+    open var requestDidFinishDownloadingUsingTaskWithResult: ((DownloadRequest, URLSessionTask, Result<URL, AFError>) -> Void)?
+
+    /// Closure called on the `request(_:didCreateDestinationURL:)` event.
+    open var requestDidCreateDestinationURL: ((DownloadRequest, URL) -> Void)?
+
+    /// Closure called on the `request(_:didValidateRequest:response:temporaryURL:destinationURL:withResult:)` event.
+    open var requestDidValidateRequestResponseFileURLWithResult: ((DownloadRequest, URLRequest?, HTTPURLResponse, URL?, Request.ValidationResult) -> Void)?
+
+    /// Closure called on the `request(_:didParseResponse:)` event.
+    open var requestDidParseDownloadResponse: ((DownloadRequest, DownloadResponse<URL?, AFError>) -> Void)?
+
+    public let queue: DispatchQueue
+
+    /// Creates an instance using the provided queue.
+    ///
+    /// - Parameter queue: `DispatchQueue` on which events will fired. `.main` by default.
+    public init(queue: DispatchQueue = .main) {
+        self.queue = queue
+    }
+
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
+        sessionDidBecomeInvalidWithError?(session, error)
+    }
+
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge) {
+        taskDidReceiveChallenge?(session, task, challenge)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         didSendBodyData bytesSent: Int64,
+                         totalBytesSent: Int64,
+                         totalBytesExpectedToSend: Int64) {
+        taskDidSendBodyData?(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
+    }
+
+    open func urlSession(_ session: URLSession, taskNeedsNewBodyStream task: URLSessionTask) {
+        taskNeedNewBodyStream?(session, task)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         willPerformHTTPRedirection response: HTTPURLResponse,
+                         newRequest request: URLRequest) {
+        taskWillPerformHTTPRedirection?(session, task, response, request)
+    }
+
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
+        taskDidFinishCollectingMetrics?(session, task, metrics)
+    }
+
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        taskDidComplete?(session, task, error)
+    }
+
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
+        taskIsWaitingForConnectivity?(session, task)
+    }
+
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        dataTaskDidReceiveData?(session, dataTask, data)
+    }
+
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse) {
+        dataTaskWillCacheResponse?(session, dataTask, proposedResponse)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         downloadTask: URLSessionDownloadTask,
+                         didResumeAtOffset fileOffset: Int64,
+                         expectedTotalBytes: Int64) {
+        downloadTaskDidResumeAtOffset?(session, downloadTask, fileOffset, expectedTotalBytes)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         downloadTask: URLSessionDownloadTask,
+                         didWriteData bytesWritten: Int64,
+                         totalBytesWritten: Int64,
+                         totalBytesExpectedToWrite: Int64) {
+        downloadTaskDidWriteData?(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
+    }
+
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
+        downloadTaskDidFinishDownloadingToURL?(session, downloadTask, location)
+    }
+
+    // MARK: Request Events
+
+    open func request(_ request: Request, didCreateInitialURLRequest urlRequest: URLRequest) {
+        requestDidCreateInitialURLRequest?(request, urlRequest)
+    }
+
+    open func request(_ request: Request, didFailToCreateURLRequestWithError error: AFError) {
+        requestDidFailToCreateURLRequestWithError?(request, error)
+    }
+
+    open func request(_ request: Request, didAdaptInitialRequest initialRequest: URLRequest, to adaptedRequest: URLRequest) {
+        requestDidAdaptInitialRequestToAdaptedRequest?(request, initialRequest, adaptedRequest)
+    }
+
+    open func request(_ request: Request, didFailToAdaptURLRequest initialRequest: URLRequest, withError error: AFError) {
+        requestDidFailToAdaptURLRequestWithError?(request, initialRequest, error)
+    }
+
+    open func request(_ request: Request, didCreateURLRequest urlRequest: URLRequest) {
+        requestDidCreateURLRequest?(request, urlRequest)
+    }
+
+    open func request(_ request: Request, didCreateTask task: URLSessionTask) {
+        requestDidCreateTask?(request, task)
+    }
+
+    open func request(_ request: Request, didGatherMetrics metrics: URLSessionTaskMetrics) {
+        requestDidGatherMetrics?(request, metrics)
+    }
+
+    open func request(_ request: Request, didFailTask task: URLSessionTask, earlyWithError error: AFError) {
+        requestDidFailTaskEarlyWithError?(request, task, error)
+    }
+
+    open func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
+        requestDidCompleteTaskWithError?(request, task, error)
+    }
+
+    open func requestIsRetrying(_ request: Request) {
+        requestIsRetrying?(request)
+    }
+
+    open func requestDidFinish(_ request: Request) {
+        requestDidFinish?(request)
+    }
+
+    open func requestDidResume(_ request: Request) {
+        requestDidResume?(request)
+    }
+
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
+        requestDidResumeTask?(request, task)
+    }
+
+    open func requestDidSuspend(_ request: Request) {
+        requestDidSuspend?(request)
+    }
+
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
+        requestDidSuspendTask?(request, task)
+    }
+
+    open func requestDidCancel(_ request: Request) {
+        requestDidCancel?(request)
+    }
+
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
+        requestDidCancelTask?(request, task)
+    }
+
+    open func request(_ request: DataRequest,
+                      didValidateRequest urlRequest: URLRequest?,
+                      response: HTTPURLResponse,
+                      data: Data?,
+                      withResult result: Request.ValidationResult) {
+        requestDidValidateRequestResponseDataWithResult?(request, urlRequest, response, data, result)
+    }
+
+    open func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
+        requestDidParseResponse?(request, response)
+    }
+
+    open func request(_ request: UploadRequest, didCreateUploadable uploadable: UploadRequest.Uploadable) {
+        requestDidCreateUploadable?(request, uploadable)
+    }
+
+    open func request(_ request: UploadRequest, didFailToCreateUploadableWithError error: AFError) {
+        requestDidFailToCreateUploadableWithError?(request, error)
+    }
+
+    open func request(_ request: UploadRequest, didProvideInputStream stream: InputStream) {
+        requestDidProvideInputStream?(request, stream)
+    }
+
+    open func request(_ request: DownloadRequest, didFinishDownloadingUsing task: URLSessionTask, with result: Result<URL, AFError>) {
+        requestDidFinishDownloadingUsingTaskWithResult?(request, task, result)
+    }
+
+    open func request(_ request: DownloadRequest, didCreateDestinationURL url: URL) {
+        requestDidCreateDestinationURL?(request, url)
+    }
+
+    open func request(_ request: DownloadRequest,
+                      didValidateRequest urlRequest: URLRequest?,
+                      response: HTTPURLResponse,
+                      fileURL: URL?,
+                      withResult result: Request.ValidationResult) {
+        requestDidValidateRequestResponseFileURLWithResult?(request,
+                                                            urlRequest,
+                                                            response,
+                                                            fileURL,
+                                                            result)
+    }
+
+    open func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
+        requestDidParseDownloadResponse?(request, response)
+    }
+}

+ 445 - 0
Pods/Alamofire/Source/HTTPHeaders.swift

@@ -0,0 +1,445 @@
+//
+//  HTTPHeaders.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// An order-preserving and case-insensitive representation of HTTP headers.
+public struct HTTPHeaders {
+    private var headers: [HTTPHeader] = []
+
+    /// Creates an empty instance.
+    public init() {}
+
+    /// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
+    /// name and value encountered.
+    public init(_ headers: [HTTPHeader]) {
+        self.init()
+
+        headers.forEach { update($0) }
+    }
+
+    /// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
+    /// and value encountered.
+    public init(_ dictionary: [String: String]) {
+        self.init()
+
+        dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
+    }
+
+    /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
+    ///
+    /// - Parameters:
+    ///   - name:  The `HTTPHeader` name.
+    ///   - value: The `HTTPHeader value.
+    public mutating func add(name: String, value: String) {
+        update(HTTPHeader(name: name, value: value))
+    }
+
+    /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
+    ///
+    /// - Parameter header: The `HTTPHeader` to update or append.
+    public mutating func add(_ header: HTTPHeader) {
+        update(header)
+    }
+
+    /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
+    ///
+    /// - Parameters:
+    ///   - name:  The `HTTPHeader` name.
+    ///   - value: The `HTTPHeader value.
+    public mutating func update(name: String, value: String) {
+        update(HTTPHeader(name: name, value: value))
+    }
+
+    /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
+    ///
+    /// - Parameter header: The `HTTPHeader` to update or append.
+    public mutating func update(_ header: HTTPHeader) {
+        guard let index = headers.index(of: header.name) else {
+            headers.append(header)
+            return
+        }
+
+        headers.replaceSubrange(index...index, with: [header])
+    }
+
+    /// Case-insensitively removes an `HTTPHeader`, if it exists, from the instance.
+    ///
+    /// - Parameter name: The name of the `HTTPHeader` to remove.
+    public mutating func remove(name: String) {
+        guard let index = headers.index(of: name) else { return }
+
+        headers.remove(at: index)
+    }
+
+    /// Sort the current instance by header name.
+    public mutating func sort() {
+        headers.sort { $0.name < $1.name }
+    }
+
+    /// Returns an instance sorted by header name.
+    ///
+    /// - Returns: A copy of the current instance sorted by name.
+    public func sorted() -> HTTPHeaders {
+        return HTTPHeaders(headers.sorted { $0.name < $1.name })
+    }
+
+    /// Case-insensitively find a header's value by name.
+    ///
+    /// - Parameter name: The name of the header to search for, case-insensitively.
+    ///
+    /// - Returns:        The value of header, if it exists.
+    public func value(for name: String) -> String? {
+        guard let index = headers.index(of: name) else { return nil }
+
+        return headers[index].value
+    }
+
+    /// Case-insensitively access the header with the given name.
+    ///
+    /// - Parameter name: The name of the header.
+    public subscript(_ name: String) -> String? {
+        get { return value(for: name) }
+        set {
+            if let value = newValue {
+                update(name: name, value: value)
+            } else {
+                remove(name: name)
+            }
+        }
+    }
+
+    /// The dictionary representation of all headers.
+    ///
+    /// This representation does not preserve the current order of the instance.
+    public var dictionary: [String: String] {
+        let namesAndValues = headers.map { ($0.name, $0.value) }
+
+        return Dictionary(namesAndValues, uniquingKeysWith: { _, last in last })
+    }
+}
+
+extension HTTPHeaders: ExpressibleByDictionaryLiteral {
+    public init(dictionaryLiteral elements: (String, String)...) {
+        self.init()
+
+        elements.forEach { update(name: $0.0, value: $0.1) }
+    }
+}
+
+extension HTTPHeaders: ExpressibleByArrayLiteral {
+    public init(arrayLiteral elements: HTTPHeader...) {
+        self.init(elements)
+    }
+}
+
+extension HTTPHeaders: Sequence {
+    public func makeIterator() -> IndexingIterator<[HTTPHeader]> {
+        return headers.makeIterator()
+    }
+}
+
+extension HTTPHeaders: Collection {
+    public var startIndex: Int {
+        return headers.startIndex
+    }
+
+    public var endIndex: Int {
+        return headers.endIndex
+    }
+
+    public subscript(position: Int) -> HTTPHeader {
+        return headers[position]
+    }
+
+    public func index(after i: Int) -> Int {
+        return headers.index(after: i)
+    }
+}
+
+extension HTTPHeaders: CustomStringConvertible {
+    public var description: String {
+        return headers.map { $0.description }
+            .joined(separator: "\n")
+    }
+}
+
+// MARK: - HTTPHeader
+
+/// A representation of a single HTTP header's name / value pair.
+public struct HTTPHeader: Hashable {
+    /// Name of the header.
+    public let name: String
+
+    /// Value of the header.
+    public let value: String
+
+    /// Creates an instance from the given `name` and `value`.
+    ///
+    /// - Parameters:
+    ///   - name:  The name of the header.
+    ///   - value: The value of the header.
+    public init(name: String, value: String) {
+        self.name = name
+        self.value = value
+    }
+}
+
+extension HTTPHeader: CustomStringConvertible {
+    public var description: String {
+        return "\(name): \(value)"
+    }
+}
+
+extension HTTPHeader {
+    /// Returns an `Accept` header.
+    ///
+    /// - Parameter value: The `Accept` value.
+    /// - Returns:         The header.
+    public static func accept(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Accept", value: value)
+    }
+
+    /// Returns an `Accept-Charset` header.
+    ///
+    /// - Parameter value: The `Accept-Charset` value.
+    /// - Returns:         The header.
+    public static func acceptCharset(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Accept-Charset", value: value)
+    }
+
+    /// Returns an `Accept-Language` header.
+    ///
+    /// Alamofire offers a default Accept-Language header that accumulates and encodes the system's preferred languages.
+    /// Use `HTTPHeader.defaultAcceptLanguage`.
+    ///
+    /// - Parameter value: The `Accept-Language` value.
+    ///
+    /// - Returns:         The header.
+    public static func acceptLanguage(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Accept-Language", value: value)
+    }
+
+    /// Returns an `Accept-Encoding` header.
+    ///
+    /// Alamofire offers a default accept encoding value that provides the most common values. Use
+    /// `HTTPHeader.defaultAcceptEncoding`.
+    ///
+    /// - Parameter value: The `Accept-Encoding` value.
+    ///
+    /// - Returns:         The header
+    public static func acceptEncoding(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Accept-Encoding", value: value)
+    }
+
+    /// Returns a `Basic` `Authorization` header using the `username` and `password` provided.
+    ///
+    /// - Parameters:
+    ///   - username: The username of the header.
+    ///   - password: The password of the header.
+    ///
+    /// - Returns:    The header.
+    public static func authorization(username: String, password: String) -> HTTPHeader {
+        let credential = Data("\(username):\(password)".utf8).base64EncodedString()
+
+        return authorization("Basic \(credential)")
+    }
+
+    /// Returns a `Bearer` `Authorization` header using the `bearerToken` provided
+    ///
+    /// - Parameter bearerToken: The bearer token.
+    ///
+    /// - Returns:               The header.
+    public static func authorization(bearerToken: String) -> HTTPHeader {
+        return authorization("Bearer \(bearerToken)")
+    }
+
+    /// Returns an `Authorization` header.
+    ///
+    /// Alamofire provides built-in methods to produce `Authorization` headers. For a Basic `Authorization` header use
+    /// `HTTPHeader.authorization(username:password:)`. For a Bearer `Authorization` header, use
+    /// `HTTPHeader.authorization(bearerToken:)`.
+    ///
+    /// - Parameter value: The `Authorization` value.
+    ///
+    /// - Returns:         The header.
+    public static func authorization(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Authorization", value: value)
+    }
+
+    /// Returns a `Content-Disposition` header.
+    ///
+    /// - Parameter value: The `Content-Disposition` value.
+    ///
+    /// - Returns:         The header.
+    public static func contentDisposition(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Content-Disposition", value: value)
+    }
+
+    /// Returns a `Content-Type` header.
+    ///
+    /// All Alamofire `ParameterEncoding`s and `ParameterEncoder`s set the `Content-Type` of the request, so it may not be necessary to manually
+    /// set this value.
+    ///
+    /// - Parameter value: The `Content-Type` value.
+    ///
+    /// - Returns:         The header.
+    public static func contentType(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "Content-Type", value: value)
+    }
+
+    /// Returns a `User-Agent` header.
+    ///
+    /// - Parameter value: The `User-Agent` value.
+    ///
+    /// - Returns:         The header.
+    public static func userAgent(_ value: String) -> HTTPHeader {
+        return HTTPHeader(name: "User-Agent", value: value)
+    }
+}
+
+extension Array where Element == HTTPHeader {
+    /// Case-insensitively finds the index of an `HTTPHeader` with the provided name, if it exists.
+    func index(of name: String) -> Int? {
+        let lowercasedName = name.lowercased()
+        return firstIndex { $0.name.lowercased() == lowercasedName }
+    }
+}
+
+// MARK: - Defaults
+
+public extension HTTPHeaders {
+    /// The default set of `HTTPHeaders` used by Alamofire. Includes `Accept-Encoding`, `Accept-Language`, and
+    /// `User-Agent`.
+    static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
+                                         .defaultAcceptLanguage,
+                                         .defaultUserAgent]
+}
+
+extension HTTPHeader {
+    /// Returns Alamofire's default `Accept-Encoding` header, appropriate for the encodings supported by particular OS
+    /// versions.
+    ///
+    /// See the [Accept-Encoding HTTP header documentation](https://tools.ietf.org/html/rfc7230#section-4.2.3) .
+    public static let defaultAcceptEncoding: HTTPHeader = {
+        let encodings: [String]
+        if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
+            encodings = ["br", "gzip", "deflate"]
+        } else {
+            encodings = ["gzip", "deflate"]
+        }
+
+        return .acceptEncoding(encodings.qualityEncoded())
+    }()
+
+    /// Returns Alamofire's default `Accept-Language` header, generated by querying `Locale` for the user's
+    /// `preferredLanguages`.
+    ///
+    /// See the [Accept-Language HTTP header documentation](https://tools.ietf.org/html/rfc7231#section-5.3.5).
+    public static let defaultAcceptLanguage: HTTPHeader = {
+        .acceptLanguage(Locale.preferredLanguages.prefix(6).qualityEncoded())
+    }()
+
+    /// Returns Alamofire's default `User-Agent` header.
+    ///
+    /// See the [User-Agent header documentation](https://tools.ietf.org/html/rfc7231#section-5.5.3).
+    ///
+    /// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 13.0.0) Alamofire/5.0.0`
+    public static let defaultUserAgent: HTTPHeader = {
+        let userAgent: String = {
+            if let info = Bundle.main.infoDictionary {
+                let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
+                let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
+                let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
+                let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
+
+                let osNameVersion: String = {
+                    let version = ProcessInfo.processInfo.operatingSystemVersion
+                    let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
+                    // swiftformat:disable indent
+                    let osName: String = {
+                    #if os(iOS)
+                        return "iOS"
+                    #elseif os(watchOS)
+                        return "watchOS"
+                    #elseif os(tvOS)
+                        return "tvOS"
+                    #elseif os(macOS)
+                        return "macOS"
+                    #elseif os(Linux)
+                        return "Linux"
+                    #else
+                        return "Unknown"
+                    #endif
+                    }()
+                    // swiftformat:enable indent
+
+                    return "\(osName) \(versionString)"
+                }()
+
+                let alamofireVersion = "Alamofire/\(version)"
+
+                return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
+            }
+
+            return "Alamofire"
+        }()
+
+        return .userAgent(userAgent)
+    }()
+}
+
+extension Collection where Element == String {
+    func qualityEncoded() -> String {
+        return enumerated().map { index, encoding in
+            let quality = 1.0 - (Double(index) * 0.1)
+            return "\(encoding);q=\(quality)"
+        }.joined(separator: ", ")
+    }
+}
+
+// MARK: - System Type Extensions
+
+extension URLRequest {
+    /// Returns `allHTTPHeaderFields` as `HTTPHeaders`.
+    public var headers: HTTPHeaders {
+        get { return allHTTPHeaderFields.map(HTTPHeaders.init) ?? HTTPHeaders() }
+        set { allHTTPHeaderFields = newValue.dictionary }
+    }
+}
+
+extension HTTPURLResponse {
+    /// Returns `allHeaderFields` as `HTTPHeaders`.
+    public var headers: HTTPHeaders {
+        return (allHeaderFields as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders()
+    }
+}
+
+public extension URLSessionConfiguration {
+    /// Returns `httpAdditionalHeaders` as `HTTPHeaders`.
+    var headers: HTTPHeaders {
+        get { return (httpAdditionalHeaders as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders() }
+        set { httpAdditionalHeaders = newValue.dictionary }
+    }
+}

+ 54 - 0
Pods/Alamofire/Source/HTTPMethod.swift

@@ -0,0 +1,54 @@
+//
+//  HTTPMethod.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+/// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so
+/// `HTTPMethod.get != HTTPMethod(rawValue: "get")`.
+///
+/// See https://tools.ietf.org/html/rfc7231#section-4.3
+public struct HTTPMethod: RawRepresentable, Equatable, Hashable {
+    /// `CONNECT` method.
+    public static let connect = HTTPMethod(rawValue: "CONNECT")
+    /// `DELETE` method.
+    public static let delete = HTTPMethod(rawValue: "DELETE")
+    /// `GET` method.
+    public static let get = HTTPMethod(rawValue: "GET")
+    /// `HEAD` method.
+    public static let head = HTTPMethod(rawValue: "HEAD")
+    /// `OPTIONS` method.
+    public static let options = HTTPMethod(rawValue: "OPTIONS")
+    /// `PATCH` method.
+    public static let patch = HTTPMethod(rawValue: "PATCH")
+    /// `POST` method.
+    public static let post = HTTPMethod(rawValue: "POST")
+    /// `PUT` method.
+    public static let put = HTTPMethod(rawValue: "PUT")
+    /// `TRACE` method.
+    public static let trace = HTTPMethod(rawValue: "TRACE")
+
+    public let rawValue: String
+
+    public init(rawValue: String) {
+        self.rawValue = rawValue
+    }
+}

+ 544 - 0
Pods/Alamofire/Source/MultipartFormData.swift

@@ -0,0 +1,544 @@
+//
+//  MultipartFormData.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+#if os(iOS) || os(watchOS) || os(tvOS)
+import MobileCoreServices
+#elseif os(macOS)
+import CoreServices
+#endif
+
+/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode
+/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead
+/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the
+/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for
+/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
+///
+/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
+/// and the w3 form documentation.
+///
+/// - https://www.ietf.org/rfc/rfc2388.txt
+/// - https://www.ietf.org/rfc/rfc2045.txt
+/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
+open class MultipartFormData {
+    // MARK: - Helper Types
+
+    struct EncodingCharacters {
+        static let crlf = "\r\n"
+    }
+
+    struct BoundaryGenerator {
+        enum BoundaryType {
+            case initial, encapsulated, final
+        }
+
+        static func randomBoundary() -> String {
+            return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
+        }
+
+        static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
+            let boundaryText: String
+
+            switch boundaryType {
+            case .initial:
+                boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
+            case .encapsulated:
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
+            case .final:
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
+            }
+
+            return Data(boundaryText.utf8)
+        }
+    }
+
+    class BodyPart {
+        let headers: HTTPHeaders
+        let bodyStream: InputStream
+        let bodyContentLength: UInt64
+        var hasInitialBoundary = false
+        var hasFinalBoundary = false
+
+        init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
+            self.headers = headers
+            self.bodyStream = bodyStream
+            self.bodyContentLength = bodyContentLength
+        }
+    }
+
+    // MARK: - Properties
+
+    /// Default memory threshold used when encoding `MultipartFormData`, in bytes.
+    public static let encodingMemoryThreshold: UInt64 = 10_000_000
+
+    /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
+    open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)"
+
+    /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
+    public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
+
+    /// The boundary used to separate the body parts in the encoded form data.
+    public let boundary: String
+
+    let fileManager: FileManager
+
+    private var bodyParts: [BodyPart]
+    private var bodyPartError: AFError?
+    private let streamBufferSize: Int
+
+    // MARK: - Lifecycle
+
+    /// Creates an instance.
+    ///
+    /// - Parameters:
+    ///   - fileManager: `FileManager` to use for file operations, if needed.
+    ///   - boundary: Boundary `String` used to separate body parts.
+    public init(fileManager: FileManager = .default, boundary: String? = nil) {
+        self.fileManager = fileManager
+        self.boundary = boundary ?? BoundaryGenerator.randomBoundary()
+        bodyParts = []
+
+        //
+        // The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more
+        // information, please refer to the following article:
+        //   - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
+        //
+        streamBufferSize = 1024
+    }
+
+    // MARK: - Body Parts
+
+    /// Creates a body part from the data and appends it to the instance.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// - Parameters:
+    ///   - data:     `Data` to encoding into the instance.
+    ///   - name:     Name to associate with the `Data` in the `Content-Disposition` HTTP header.
+    ///   - fileName: Filename to associate with the `Data` in the `Content-Disposition` HTTP header.
+    ///   - mimeType: MIME type to associate with the data in the `Content-Type` HTTP header.
+    public func append(_ data: Data, withName name: String, fileName: String? = nil, mimeType: String? = nil) {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+        let stream = InputStream(data: data)
+        let length = UInt64(data.count)
+
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part from the file and appends it to the instance.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
+    /// - `Content-Type: #{generated mimeType}` (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
+    /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
+    /// system associated MIME type.
+    ///
+    /// - Parameters:
+    ///   - fileURL: `URL` of the file whose content will be encoded into the instance.
+    ///   - name:    Name to associate with the file content in the `Content-Disposition` HTTP header.
+    public func append(_ fileURL: URL, withName name: String) {
+        let fileName = fileURL.lastPathComponent
+        let pathExtension = fileURL.pathExtension
+
+        if !fileName.isEmpty && !pathExtension.isEmpty {
+            let mime = mimeType(forPathExtension: pathExtension)
+            append(fileURL, withName: name, fileName: fileName, mimeType: mime)
+        } else {
+            setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL))
+        }
+    }
+
+    /// Creates a body part from the file and appends it to the instance.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
+    /// - Content-Type: #{mimeType} (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// - Parameters:
+    ///   - fileURL:  `URL` of the file whose content will be encoded into the instance.
+    ///   - name:     Name to associate with the file content in the `Content-Disposition` HTTP header.
+    ///   - fileName: Filename to associate with the file content in the `Content-Disposition` HTTP header.
+    ///   - mimeType: MIME type to associate with the file content in the `Content-Type` HTTP header.
+    public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+
+        //============================================================
+        //                 Check 1 - is file URL?
+        //============================================================
+
+        guard fileURL.isFileURL else {
+            setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL))
+            return
+        }
+
+        //============================================================
+        //              Check 2 - is file URL reachable?
+        //============================================================
+
+        do {
+            let isReachable = try fileURL.checkPromisedItemIsReachable()
+            guard isReachable else {
+                setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL))
+                return
+            }
+        } catch {
+            setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error))
+            return
+        }
+
+        //============================================================
+        //            Check 3 - is file URL a directory?
+        //============================================================
+
+        var isDirectory: ObjCBool = false
+        let path = fileURL.path
+
+        guard fileManager.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else {
+            setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL))
+            return
+        }
+
+        //============================================================
+        //          Check 4 - can the file size be extracted?
+        //============================================================
+
+        let bodyContentLength: UInt64
+
+        do {
+            guard let fileSize = try fileManager.attributesOfItem(atPath: path)[.size] as? NSNumber else {
+                setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL))
+                return
+            }
+
+            bodyContentLength = fileSize.uint64Value
+        } catch {
+            setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error))
+            return
+        }
+
+        //============================================================
+        //       Check 5 - can a stream be created from file URL?
+        //============================================================
+
+        guard let stream = InputStream(url: fileURL) else {
+            setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL))
+            return
+        }
+
+        append(stream, withLength: bodyContentLength, headers: headers)
+    }
+
+    /// Creates a body part from the stream and appends it to the instance.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
+    /// - Encoded stream data
+    /// - Multipart form boundary
+    ///
+    /// - Parameters:
+    ///   - stream:   `InputStream` to encode into the instance.
+    ///   - length:   Length, in bytes, of the stream.
+    ///   - name:     Name to associate with the stream content in the `Content-Disposition` HTTP header.
+    ///   - fileName: Filename to associate with the stream content in the `Content-Disposition` HTTP header.
+    ///   - mimeType: MIME type to associate with the stream content in the `Content-Type` HTTP header.
+    public func append(_ stream: InputStream,
+                       withLength length: UInt64,
+                       name: String,
+                       fileName: String,
+                       mimeType: String) {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part with the stream, length, and headers and appends it to the instance.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - HTTP headers
+    /// - Encoded stream data
+    /// - Multipart form boundary
+    ///
+    /// - Parameters:
+    ///   - stream:  `InputStream` to encode into the instance.
+    ///   - length:  Length, in bytes, of the stream.
+    ///   - headers: `HTTPHeaders` for the body part.
+    public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
+        let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
+        bodyParts.append(bodyPart)
+    }
+
+    // MARK: - Data Encoding
+
+    /// Encodes all appended body parts into a single `Data` value.
+    ///
+    /// - Note: This method will load all the appended body parts into memory all at the same time. This method should
+    ///         only be used when the encoded data will have a small memory footprint. For large data cases, please use
+    ///         the `writeEncodedData(to:))` method.
+    ///
+    /// - Returns: The encoded `Data`, if encoding is successful.
+    /// - Throws:  An `AFError` if encoding encounters an error.
+    public func encode() throws -> Data {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        var encoded = Data()
+
+        bodyParts.first?.hasInitialBoundary = true
+        bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in bodyParts {
+            let encodedData = try encode(bodyPart)
+            encoded.append(encodedData)
+        }
+
+        return encoded
+    }
+
+    /// Writes all appended body parts to the given file `URL`.
+    ///
+    /// This process is facilitated by reading and writing with input and output streams, respectively. Thus,
+    /// this approach is very memory efficient and should be used for large body part data.
+    ///
+    /// - Parameter fileURL: File `URL` to which to write the form data.
+    /// - Throws:            An `AFError` if encoding encounters an error.
+    public func writeEncodedData(to fileURL: URL) throws {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        if fileManager.fileExists(atPath: fileURL.path) {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL))
+        } else if !fileURL.isFileURL {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL))
+        }
+
+        guard let outputStream = OutputStream(url: fileURL, append: false) else {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL))
+        }
+
+        outputStream.open()
+        defer { outputStream.close() }
+
+        bodyParts.first?.hasInitialBoundary = true
+        bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in bodyParts {
+            try write(bodyPart, to: outputStream)
+        }
+    }
+
+    // MARK: - Private - Body Part Encoding
+
+    private func encode(_ bodyPart: BodyPart) throws -> Data {
+        var encoded = Data()
+
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        encoded.append(initialData)
+
+        let headerData = encodeHeaders(for: bodyPart)
+        encoded.append(headerData)
+
+        let bodyStreamData = try encodeBodyStream(for: bodyPart)
+        encoded.append(bodyStreamData)
+
+        if bodyPart.hasFinalBoundary {
+            encoded.append(finalBoundaryData())
+        }
+
+        return encoded
+    }
+
+    private func encodeHeaders(for bodyPart: BodyPart) -> Data {
+        let headerText = bodyPart.headers.map { "\($0.name): \($0.value)\(EncodingCharacters.crlf)" }
+            .joined()
+            + EncodingCharacters.crlf
+
+        return Data(headerText.utf8)
+    }
+
+    private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data {
+        let inputStream = bodyPart.bodyStream
+        inputStream.open()
+        defer { inputStream.close() }
+
+        var encoded = Data()
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if let error = inputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error))
+            }
+
+            if bytesRead > 0 {
+                encoded.append(buffer, count: bytesRead)
+            } else {
+                break
+            }
+        }
+
+        return encoded
+    }
+
+    // MARK: - Private - Writing Body Part to Output Stream
+
+    private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        try writeInitialBoundaryData(for: bodyPart, to: outputStream)
+        try writeHeaderData(for: bodyPart, to: outputStream)
+        try writeBodyStream(for: bodyPart, to: outputStream)
+        try writeFinalBoundaryData(for: bodyPart, to: outputStream)
+    }
+
+    private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        return try write(initialData, to: outputStream)
+    }
+
+    private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let headerData = encodeHeaders(for: bodyPart)
+        return try write(headerData, to: outputStream)
+    }
+
+    private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let inputStream = bodyPart.bodyStream
+
+        inputStream.open()
+        defer { inputStream.close() }
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if let streamError = inputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
+            }
+
+            if bytesRead > 0 {
+                if buffer.count != bytesRead {
+                    buffer = Array(buffer[0..<bytesRead])
+                }
+
+                try write(&buffer, to: outputStream)
+            } else {
+                break
+            }
+        }
+    }
+
+    private func writeFinalBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        if bodyPart.hasFinalBoundary {
+            return try write(finalBoundaryData(), to: outputStream)
+        }
+    }
+
+    // MARK: - Private - Writing Buffered Data to Output Stream
+
+    private func write(_ data: Data, to outputStream: OutputStream) throws {
+        var buffer = [UInt8](repeating: 0, count: data.count)
+        data.copyBytes(to: &buffer, count: data.count)
+
+        return try write(&buffer, to: outputStream)
+    }
+
+    private func write(_ buffer: inout [UInt8], to outputStream: OutputStream) throws {
+        var bytesToWrite = buffer.count
+
+        while bytesToWrite > 0, outputStream.hasSpaceAvailable {
+            let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
+
+            if let error = outputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error))
+            }
+
+            bytesToWrite -= bytesWritten
+
+            if bytesToWrite > 0 {
+                buffer = Array(buffer[bytesWritten..<buffer.count])
+            }
+        }
+    }
+
+    // MARK: - Private - Mime Type
+
+    private func mimeType(forPathExtension pathExtension: String) -> String {
+        if
+            let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
+            let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
+            return contentType as String
+        }
+
+        return "application/octet-stream"
+    }
+
+    // MARK: - Private - Content Headers
+
+    private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> HTTPHeaders {
+        var disposition = "form-data; name=\"\(name)\""
+        if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
+
+        var headers: HTTPHeaders = [.contentDisposition(disposition)]
+        if let mimeType = mimeType { headers.add(.contentType(mimeType)) }
+
+        return headers
+    }
+
+    // MARK: - Private - Boundary Encoding
+
+    private func initialBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary)
+    }
+
+    private func encapsulatedBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary)
+    }
+
+    private func finalBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary)
+    }
+
+    // MARK: - Private - Errors
+
+    private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) {
+        guard bodyPartError == nil else { return }
+        bodyPartError = AFError.multipartEncodingFailed(reason: reason)
+    }
+}

+ 87 - 0
Pods/Alamofire/Source/MultipartUpload.swift

@@ -0,0 +1,87 @@
+//
+//  MultipartUpload.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Internal type which encapsulates a `MultipartFormData` upload.
+final class MultipartUpload {
+    lazy var result = Result { try build() }
+
+    let isInBackgroundSession: Bool
+    let multipartFormData: MultipartFormData
+    let encodingMemoryThreshold: UInt64
+    let request: URLRequestConvertible
+    let fileManager: FileManager
+
+    init(isInBackgroundSession: Bool,
+         encodingMemoryThreshold: UInt64,
+         request: URLRequestConvertible,
+         multipartFormData: MultipartFormData) {
+        self.isInBackgroundSession = isInBackgroundSession
+        self.encodingMemoryThreshold = encodingMemoryThreshold
+        self.request = request
+        fileManager = multipartFormData.fileManager
+        self.multipartFormData = multipartFormData
+    }
+
+    func build() throws -> (request: URLRequest, uploadable: UploadRequest.Uploadable) {
+        var urlRequest = try request.asURLRequest()
+        urlRequest.setValue(multipartFormData.contentType, forHTTPHeaderField: "Content-Type")
+
+        let uploadable: UploadRequest.Uploadable
+        if multipartFormData.contentLength < encodingMemoryThreshold && !isInBackgroundSession {
+            let data = try multipartFormData.encode()
+
+            uploadable = .data(data)
+        } else {
+            let tempDirectoryURL = fileManager.temporaryDirectory
+            let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
+            let fileName = UUID().uuidString
+            let fileURL = directoryURL.appendingPathComponent(fileName)
+
+            try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
+
+            do {
+                try multipartFormData.writeEncodedData(to: fileURL)
+            } catch {
+                // Cleanup after attempted write if it fails.
+                try? fileManager.removeItem(at: fileURL)
+            }
+
+            uploadable = .file(fileURL, shouldRemove: true)
+        }
+
+        return (request: urlRequest, uploadable: uploadable)
+    }
+}
+
+extension MultipartUpload: UploadConvertible {
+    func asURLRequest() throws -> URLRequest {
+        return try result.get().request
+    }
+
+    func createUploadable() throws -> UploadRequest.Uploadable {
+        return try result.get().uploadable
+    }
+}

+ 266 - 0
Pods/Alamofire/Source/NetworkReachabilityManager.swift

@@ -0,0 +1,266 @@
+//
+//  NetworkReachabilityManager.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+#if !(os(watchOS) || os(Linux))
+
+import Foundation
+import SystemConfiguration
+
+/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both cellular and
+/// WiFi network interfaces.
+///
+/// Reachability can be used to determine background information about why a network operation failed, or to retry
+/// network requests when a connection is established. It should not be used to prevent a user from initiating a network
+/// request, as it's possible that an initial request may be required to establish reachability.
+open class NetworkReachabilityManager {
+    /// Defines the various states of network reachability.
+    public enum NetworkReachabilityStatus {
+        /// It is unknown whether the network is reachable.
+        case unknown
+        /// The network is not reachable.
+        case notReachable
+        /// The network is reachable on the associated `ConnectionType`.
+        case reachable(ConnectionType)
+
+        init(_ flags: SCNetworkReachabilityFlags) {
+            guard flags.isActuallyReachable else { self = .notReachable; return }
+
+            var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi)
+
+            if flags.isCellular { networkStatus = .reachable(.cellular) }
+
+            self = networkStatus
+        }
+
+        /// Defines the various connection types detected by reachability flags.
+        public enum ConnectionType {
+            /// The connection type is either over Ethernet or WiFi.
+            case ethernetOrWiFi
+            /// The connection type is a cellular connection.
+            case cellular
+        }
+    }
+
+    /// A closure executed when the network reachability status changes. The closure takes a single argument: the
+    /// network reachability status.
+    public typealias Listener = (NetworkReachabilityStatus) -> Void
+
+    /// Default `NetworkReachabilityManager` for the zero address and a `listenerQueue` of `.main`.
+    public static let `default` = NetworkReachabilityManager()
+
+    // MARK: - Properties
+
+    /// Whether the network is currently reachable.
+    open var isReachable: Bool { return isReachableOnCellular || isReachableOnEthernetOrWiFi }
+
+    /// Whether the network is currently reachable over the cellular interface.
+    ///
+    /// - Note: Using this property to decide whether to make a high or low bandwidth request is not recommended.
+    ///         Instead, set the `allowsCellularAccess` on any `URLRequest`s being issued.
+    ///
+    open var isReachableOnCellular: Bool { return status == .reachable(.cellular) }
+
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
+    open var isReachableOnEthernetOrWiFi: Bool { return status == .reachable(.ethernetOrWiFi) }
+
+    /// `DispatchQueue` on which reachability will update.
+    public let reachabilityQueue = DispatchQueue(label: "org.alamofire.reachabilityQueue")
+
+    /// Flags of the current reachability type, if any.
+    open var flags: SCNetworkReachabilityFlags? {
+        var flags = SCNetworkReachabilityFlags()
+
+        return (SCNetworkReachabilityGetFlags(reachability, &flags)) ? flags : nil
+    }
+
+    /// The current network reachability status.
+    open var status: NetworkReachabilityStatus {
+        return flags.map(NetworkReachabilityStatus.init) ?? .unknown
+    }
+
+    /// Mutable state storage.
+    struct MutableState {
+        /// A closure executed when the network reachability status changes.
+        var listener: Listener?
+        /// `DispatchQueue` on which listeners will be called.
+        var listenerQueue: DispatchQueue?
+        /// Previously calculated status.
+        var previousStatus: NetworkReachabilityStatus?
+    }
+
+    /// `SCNetworkReachability` instance providing notifications.
+    private let reachability: SCNetworkReachability
+
+    /// Protected storage for mutable state.
+    private let mutableState = Protector(MutableState())
+
+    // MARK: - Initialization
+
+    /// Creates an instance with the specified host.
+    ///
+    /// - Note: The `host` value must *not* contain a scheme, just the hostname.
+    ///
+    /// - Parameters:
+    ///   - host:          Host used to evaluate network reachability. Must *not* include the scheme (e.g. `https`).
+    public convenience init?(host: String) {
+        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
+
+        self.init(reachability: reachability)
+    }
+
+    /// Creates an instance that monitors the address 0.0.0.0.
+    ///
+    /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing
+    /// status of the device, both IPv4 and IPv6.
+    public convenience init?() {
+        var zero = sockaddr()
+        zero.sa_len = UInt8(MemoryLayout<sockaddr>.size)
+        zero.sa_family = sa_family_t(AF_INET)
+
+        guard let reachability = SCNetworkReachabilityCreateWithAddress(nil, &zero) else { return nil }
+
+        self.init(reachability: reachability)
+    }
+
+    private init(reachability: SCNetworkReachability) {
+        self.reachability = reachability
+    }
+
+    deinit {
+        stopListening()
+    }
+
+    // MARK: - Listening
+
+    /// Starts listening for changes in network reachability status.
+    ///
+    /// - Note: Stops and removes any existing listener.
+    ///
+    /// - Parameters:
+    ///   - queue:    `DispatchQueue` on which to call the `listener` closure. `.main` by default.
+    ///   - listener: `Listener` closure called when reachability changes.
+    ///
+    /// - Returns: `true` if listening was started successfully, `false` otherwise.
+    @discardableResult
+    open func startListening(onQueue queue: DispatchQueue = .main,
+                             onUpdatePerforming listener: @escaping Listener) -> Bool {
+        stopListening()
+
+        mutableState.write { state in
+            state.listenerQueue = queue
+            state.listener = listener
+        }
+
+        var context = SCNetworkReachabilityContext(version: 0,
+                                                   info: Unmanaged.passRetained(self).toOpaque(),
+                                                   retain: nil,
+                                                   release: nil,
+                                                   copyDescription: nil)
+        let callback: SCNetworkReachabilityCallBack = { _, flags, info in
+            guard let info = info else { return }
+
+            let instance = Unmanaged<NetworkReachabilityManager>.fromOpaque(info).takeUnretainedValue()
+            instance.notifyListener(flags)
+        }
+
+        let queueAdded = SCNetworkReachabilitySetDispatchQueue(reachability, reachabilityQueue)
+        let callbackAdded = SCNetworkReachabilitySetCallback(reachability, callback, &context)
+
+        // Manually call listener to give initial state, since the framework may not.
+        if let currentFlags = flags {
+            reachabilityQueue.async {
+                self.notifyListener(currentFlags)
+            }
+        }
+
+        return callbackAdded && queueAdded
+    }
+
+    /// Stops listening for changes in network reachability status.
+    open func stopListening() {
+        SCNetworkReachabilitySetCallback(reachability, nil, nil)
+        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
+        mutableState.write { state in
+            state.listener = nil
+            state.listenerQueue = nil
+            state.previousStatus = nil
+        }
+    }
+
+    // MARK: - Internal - Listener Notification
+
+    /// Calls the `listener` closure of the `listenerQueue` if the computed status hasn't changed.
+    ///
+    /// - Note: Should only be called from the `reachabilityQueue`.
+    ///
+    /// - Parameter flags: `SCNetworkReachabilityFlags` to use to calculate the status.
+    func notifyListener(_ flags: SCNetworkReachabilityFlags) {
+        let newStatus = NetworkReachabilityStatus(flags)
+
+        mutableState.write { state in
+            guard state.previousStatus != newStatus else { return }
+
+            state.previousStatus = newStatus
+
+            let listener = state.listener
+            state.listenerQueue?.async { listener?(newStatus) }
+        }
+    }
+}
+
+// MARK: -
+
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
+
+extension SCNetworkReachabilityFlags {
+    var isReachable: Bool { return contains(.reachable) }
+    var isConnectionRequired: Bool { return contains(.connectionRequired) }
+    var canConnectAutomatically: Bool { return contains(.connectionOnDemand) || contains(.connectionOnTraffic) }
+    var canConnectWithoutUserInteraction: Bool { return canConnectAutomatically && !contains(.interventionRequired) }
+    var isActuallyReachable: Bool { return isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
+    var isCellular: Bool {
+        #if os(iOS) || os(tvOS)
+        return contains(.isWWAN)
+        #else
+        return false
+        #endif
+    }
+
+    /// Human readable `String` for all states, to help with debugging.
+    var readableDescription: String {
+        let W = isCellular ? "W" : "-"
+        let R = isReachable ? "R" : "-"
+        let c = isConnectionRequired ? "c" : "-"
+        let t = contains(.transientConnection) ? "t" : "-"
+        let i = contains(.interventionRequired) ? "i" : "-"
+        let C = contains(.connectionOnTraffic) ? "C" : "-"
+        let D = contains(.connectionOnDemand) ? "D" : "-"
+        let l = contains(.isLocalAddress) ? "l" : "-"
+        let d = contains(.isDirect) ? "d" : "-"
+        let a = contains(.connectionAutomatic) ? "a" : "-"
+
+        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)\(a)"
+    }
+}
+#endif

+ 115 - 0
Pods/Alamofire/Source/Notifications.swift

@@ -0,0 +1,115 @@
+//
+//  Notifications.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+public extension Request {
+    /// Posted when a `Request` is resumed. The `Notification` contains the resumed `Request`.
+    static let didResumeNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResume")
+    /// Posted when a `Request` is suspended. The `Notification` contains the suspended `Request`.
+    static let didSuspendNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspend")
+    /// Posted when a `Request` is cancelled. The `Notification` contains the cancelled `Request`.
+    static let didCancelNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancel")
+    /// Posted when a `Request` is finished. The `Notification` contains the completed `Request`.
+    static let didFinishNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didFinish")
+
+    /// Posted when a `URLSessionTask` is resumed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+    static let didResumeTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResumeTask")
+    /// Posted when a `URLSessionTask` is suspended. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+    static let didSuspendTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspendTask")
+    /// Posted when a `URLSessionTask` is cancelled. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+    static let didCancelTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancelTask")
+    /// Posted when a `URLSessionTask` is completed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+    static let didCompleteTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCompleteTask")
+}
+
+// MARK: -
+
+extension Notification {
+    /// The `Request` contained by the instance's `userInfo`, `nil` otherwise.
+    public var request: Request? {
+        return userInfo?[String.requestKey] as? Request
+    }
+
+    /// Convenience initializer for a `Notification` containing a `Request` payload.
+    ///
+    /// - Parameters:
+    ///   - name:    The name of the notification.
+    ///   - request: The `Request` payload.
+    init(name: Notification.Name, request: Request) {
+        self.init(name: name, object: nil, userInfo: [String.requestKey: request])
+    }
+}
+
+extension NotificationCenter {
+    /// Convenience function for posting notifications with `Request` payloads.
+    ///
+    /// - Parameters:
+    ///   - name:    The name of the notification.
+    ///   - request: The `Request` payload.
+    func postNotification(named name: Notification.Name, with request: Request) {
+        let notification = Notification(name: name, request: request)
+        post(notification)
+    }
+}
+
+extension String {
+    /// User info dictionary key representing the `Request` associated with the notification.
+    fileprivate static let requestKey = "org.alamofire.notification.key.request"
+}
+
+/// `EventMonitor` that provides Alamofire's notifications.
+public final class AlamofireNotifications: EventMonitor {
+    public func requestDidResume(_ request: Request) {
+        NotificationCenter.default.postNotification(named: Request.didResumeNotification, with: request)
+    }
+
+    public func requestDidSuspend(_ request: Request) {
+        NotificationCenter.default.postNotification(named: Request.didSuspendNotification, with: request)
+    }
+
+    public func requestDidCancel(_ request: Request) {
+        NotificationCenter.default.postNotification(named: Request.didCancelNotification, with: request)
+    }
+
+    public func requestDidFinish(_ request: Request) {
+        NotificationCenter.default.postNotification(named: Request.didFinishNotification, with: request)
+    }
+
+    public func request(_ request: Request, didResumeTask task: URLSessionTask) {
+        NotificationCenter.default.postNotification(named: Request.didResumeTaskNotification, with: request)
+    }
+
+    public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
+        NotificationCenter.default.postNotification(named: Request.didSuspendTaskNotification, with: request)
+    }
+
+    public func request(_ request: Request, didCancelTask task: URLSessionTask) {
+        NotificationCenter.default.postNotification(named: Request.didCancelTaskNotification, with: request)
+    }
+
+    public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
+        NotificationCenter.default.postNotification(named: Request.didCompleteTaskNotification, with: request)
+    }
+}

+ 49 - 0
Pods/Alamofire/Source/OperationQueue+Alamofire.swift

@@ -0,0 +1,49 @@
+//
+//  OperationQueue+Alamofire.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+extension OperationQueue {
+    /// Creates an instance using the provided parameters.
+    ///
+    /// - Parameters:
+    ///   - qualityOfService:            `QualityOfService` to be applied to the queue. `.default` by default.
+    ///   - maxConcurrentOperationCount: Maximum concurrent operations.
+    ///                                  `OperationQueue.defaultMaxConcurrentOperationCount` by default.
+    ///   - underlyingQueue: Underlying  `DispatchQueue`. `nil` by default.
+    ///   - name:                        Name for the queue. `nil` by default.
+    ///   - startSuspended:              Whether the queue starts suspended. `false` by default.
+    convenience init(qualityOfService: QualityOfService = .default,
+                     maxConcurrentOperationCount: Int = OperationQueue.defaultMaxConcurrentOperationCount,
+                     underlyingQueue: DispatchQueue? = nil,
+                     name: String? = nil,
+                     startSuspended: Bool = false) {
+        self.init()
+        self.qualityOfService = qualityOfService
+        self.maxConcurrentOperationCount = maxConcurrentOperationCount
+        self.underlyingQueue = underlyingQueue
+        self.name = name
+        isSuspended = startSuspended
+    }
+}

+ 184 - 0
Pods/Alamofire/Source/ParameterEncoder.swift

@@ -0,0 +1,184 @@
+//
+//  ParameterEncoder.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that can encode any `Encodable` type into a `URLRequest`.
+public protocol ParameterEncoder {
+    /// Encode the provided `Encodable` parameters into `request`.
+    ///
+    /// - Parameters:
+    ///   - parameters: The `Encodable` parameter value.
+    ///   - request:    The `URLRequest` into which to encode the parameters.
+    ///
+    /// - Returns:      A `URLRequest` with the result of the encoding.
+    /// - Throws:       An `Error` when encoding fails. For Alamofire provided encoders, this will be an instance of
+    ///                 `AFError.parameterEncoderFailed` with an associated `ParameterEncoderFailureReason`.
+    func encode<Parameters: Encodable>(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest
+}
+
+/// A `ParameterEncoder` that encodes types as JSON body data.
+///
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it's set to `application/json`.
+open class JSONParameterEncoder: ParameterEncoder {
+    /// Returns an encoder with default parameters.
+    public static var `default`: JSONParameterEncoder { return JSONParameterEncoder() }
+
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.prettyPrinted`.
+    public static var prettyPrinted: JSONParameterEncoder {
+        let encoder = JSONEncoder()
+        encoder.outputFormatting = .prettyPrinted
+
+        return JSONParameterEncoder(encoder: encoder)
+    }
+
+    /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.sortedKeys`.
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    public static var sortedKeys: JSONParameterEncoder {
+        let encoder = JSONEncoder()
+        encoder.outputFormatting = .sortedKeys
+
+        return JSONParameterEncoder(encoder: encoder)
+    }
+
+    /// `JSONEncoder` used to encode parameters.
+    public let encoder: JSONEncoder
+
+    /// Creates an instance with the provided `JSONEncoder`.
+    ///
+    /// - Parameter encoder: The `JSONEncoder`. `JSONEncoder()` by default.
+    public init(encoder: JSONEncoder = JSONEncoder()) {
+        self.encoder = encoder
+    }
+
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
+                                            into request: URLRequest) throws -> URLRequest {
+        guard let parameters = parameters else { return request }
+
+        var request = request
+
+        do {
+            let data = try encoder.encode(parameters)
+            request.httpBody = data
+            if request.headers["Content-Type"] == nil {
+                request.headers.update(.contentType("application/json"))
+            }
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+        }
+
+        return request
+    }
+}
+
+/// A `ParameterEncoder` that encodes types as URL-encoded query strings to be set on the URL or as body data, depending
+/// on the `Destination` set.
+///
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it will be set to
+/// `application/x-www-form-urlencoded; charset=utf-8`.
+///
+/// Encoding behavior can be customized by passing an instance of `URLEncodedFormEncoder` to the initializer.
+open class URLEncodedFormParameterEncoder: ParameterEncoder {
+    /// Defines where the URL-encoded string should be set for each `URLRequest`.
+    public enum Destination {
+        /// Applies the encoded query string to any existing query string for `.get`, `.head`, and `.delete` request.
+        /// Sets it to the `httpBody` for all other methods.
+        case methodDependent
+        /// Applies the encoded query string to any existing query string from the `URLRequest`.
+        case queryString
+        /// Applies the encoded query string to the `httpBody` of the `URLRequest`.
+        case httpBody
+
+        /// Determines whether the URL-encoded string should be applied to the `URLRequest`'s `url`.
+        ///
+        /// - Parameter method: The `HTTPMethod`.
+        ///
+        /// - Returns:          Whether the URL-encoded string should be applied to a `URL`.
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
+            switch self {
+            case .methodDependent: return [.get, .head, .delete].contains(method)
+            case .queryString: return true
+            case .httpBody: return false
+            }
+        }
+    }
+
+    /// Returns an encoder with default parameters.
+    public static var `default`: URLEncodedFormParameterEncoder { return URLEncodedFormParameterEncoder() }
+
+    /// The `URLEncodedFormEncoder` to use.
+    public let encoder: URLEncodedFormEncoder
+
+    /// The `Destination` for the URL-encoded string.
+    public let destination: Destination
+
+    /// Creates an instance with the provided `URLEncodedFormEncoder` instance and `Destination` value.
+    ///
+    /// - Parameters:
+    ///   - encoder:     The `URLEncodedFormEncoder`. `URLEncodedFormEncoder()` by default.
+    ///   - destination: The `Destination`. `.methodDependent` by default.
+    public init(encoder: URLEncodedFormEncoder = URLEncodedFormEncoder(), destination: Destination = .methodDependent) {
+        self.encoder = encoder
+        self.destination = destination
+    }
+
+    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
+                                            into request: URLRequest) throws -> URLRequest {
+        guard let parameters = parameters else { return request }
+
+        var request = request
+
+        guard let url = request.url else {
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
+        }
+
+        guard let method = request.method else {
+            let rawValue = request.method?.rawValue ?? "nil"
+            throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.httpMethod(rawValue: rawValue)))
+        }
+
+        if destination.encodesParametersInURL(for: method),
+            var components = URLComponents(url: url, resolvingAgainstBaseURL: false) {
+            let query: String = try Result<String, Error> { try encoder.encode(parameters) }
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
+            let newQueryString = [components.percentEncodedQuery, query].compactMap { $0 }.joinedWithAmpersands()
+            components.percentEncodedQuery = newQueryString.isEmpty ? nil : newQueryString
+
+            guard let newURL = components.url else {
+                throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
+            }
+
+            request.url = newURL
+        } else {
+            if request.headers["Content-Type"] == nil {
+                request.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
+            }
+
+            request.httpBody = try Result<Data, Error> { try encoder.encode(parameters) }
+                .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
+        }
+
+        return request
+    }
+}

+ 314 - 0
Pods/Alamofire/Source/ParameterEncoding.swift

@@ -0,0 +1,314 @@
+//
+//  ParameterEncoding.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A dictionary of parameters to apply to a `URLRequest`.
+public typealias Parameters = [String: Any]
+
+/// A type used to define how a set of parameters are applied to a `URLRequest`.
+public protocol ParameterEncoding {
+    /// Creates a `URLRequest` by encoding parameters and applying them on the passed request.
+    ///
+    /// - Parameters:
+    ///   - urlRequest: `URLRequestConvertible` value onto which parameters will be encoded.
+    ///   - parameters: `Parameters` to encode onto the request.
+    ///
+    /// - Returns:      The encoded `URLRequest`.
+    /// - Throws:       Any `Error` produced during parameter encoding.
+    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
+}
+
+// MARK: -
+
+/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
+/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
+/// the HTTP body depends on the destination of the encoding.
+///
+/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
+/// `application/x-www-form-urlencoded; charset=utf-8`.
+///
+/// There is no published specification for how to encode collection types. By default the convention of appending
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
+/// square brackets appended to array keys.
+///
+/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode
+/// `true` as 1 and `false` as 0.
+public struct URLEncoding: ParameterEncoding {
+    // MARK: Helper Types
+
+    /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
+    /// resulting URL request.
+    public enum Destination {
+        /// Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` requests and
+        /// sets as the HTTP body for requests with any other HTTP method.
+        case methodDependent
+        /// Sets or appends encoded query string result to existing query string.
+        case queryString
+        /// Sets encoded query string result as the HTTP body of the URL request.
+        case httpBody
+
+        func encodesParametersInURL(for method: HTTPMethod) -> Bool {
+            switch self {
+            case .methodDependent: return [.get, .head, .delete].contains(method)
+            case .queryString: return true
+            case .httpBody: return false
+            }
+        }
+    }
+
+    /// Configures how `Array` parameters are encoded.
+    public enum ArrayEncoding {
+        /// An empty set of square brackets is appended to the key for every value. This is the default behavior.
+        case brackets
+        /// No brackets are appended. The key is encoded as is.
+        case noBrackets
+
+        func encode(key: String) -> String {
+            switch self {
+            case .brackets:
+                return "\(key)[]"
+            case .noBrackets:
+                return key
+            }
+        }
+    }
+
+    /// Configures how `Bool` parameters are encoded.
+    public enum BoolEncoding {
+        /// Encode `true` as `1` and `false` as `0`. This is the default behavior.
+        case numeric
+        /// Encode `true` and `false` as string literals.
+        case literal
+
+        func encode(value: Bool) -> String {
+            switch self {
+            case .numeric:
+                return value ? "1" : "0"
+            case .literal:
+                return value ? "true" : "false"
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    /// Returns a default `URLEncoding` instance with a `.methodDependent` destination.
+    public static var `default`: URLEncoding { return URLEncoding() }
+
+    /// Returns a `URLEncoding` instance with a `.queryString` destination.
+    public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
+
+    /// Returns a `URLEncoding` instance with an `.httpBody` destination.
+    public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
+
+    /// The destination defining where the encoded query string is to be applied to the URL request.
+    public let destination: Destination
+
+    /// The encoding to use for `Array` parameters.
+    public let arrayEncoding: ArrayEncoding
+
+    /// The encoding to use for `Bool` parameters.
+    public let boolEncoding: BoolEncoding
+
+    // MARK: Initialization
+
+    /// Creates an instance using the specified parameters.
+    ///
+    /// - Parameters:
+    ///   - destination:   `Destination` defining where the encoded query string will be applied. `.methodDependent` by
+    ///                    default.
+    ///   - arrayEncoding: `ArrayEncoding` to use. `.brackets` by default.
+    ///   - boolEncoding:  `BoolEncoding` to use. `.numeric` by default.
+    public init(destination: Destination = .methodDependent,
+                arrayEncoding: ArrayEncoding = .brackets,
+                boolEncoding: BoolEncoding = .numeric) {
+        self.destination = destination
+        self.arrayEncoding = arrayEncoding
+        self.boolEncoding = boolEncoding
+    }
+
+    // MARK: Encoding
+
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let parameters = parameters else { return urlRequest }
+
+        if let method = urlRequest.method, destination.encodesParametersInURL(for: method) {
+            guard let url = urlRequest.url else {
+                throw AFError.parameterEncodingFailed(reason: .missingURL)
+            }
+
+            if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
+                let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
+                urlComponents.percentEncodedQuery = percentEncodedQuery
+                urlRequest.url = urlComponents.url
+            }
+        } else {
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = Data(query(parameters).utf8)
+        }
+
+        return urlRequest
+    }
+
+    /// Creates a percent-escaped, URL encoded query string components from the given key-value pair recursively.
+    ///
+    /// - Parameters:
+    ///   - key:   Key of the query component.
+    ///   - value: Value of the query component.
+    ///
+    /// - Returns: The percent-escaped, URL encoded query string components.
+    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
+        var components: [(String, String)] = []
+
+        if let dictionary = value as? [String: Any] {
+            for (nestedKey, value) in dictionary {
+                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
+            }
+        } else if let array = value as? [Any] {
+            for value in array {
+                components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value)
+            }
+        } else if let value = value as? NSNumber {
+            if value.isBool {
+                components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue))))
+            } else {
+                components.append((escape(key), escape("\(value)")))
+            }
+        } else if let bool = value as? Bool {
+            components.append((escape(key), escape(boolEncoding.encode(value: bool))))
+        } else {
+            components.append((escape(key), escape("\(value)")))
+        }
+
+        return components
+    }
+
+    /// Creates a percent-escaped string following RFC 3986 for a query string key or value.
+    ///
+    /// - Parameter string: `String` to be percent-escaped.
+    ///
+    /// - Returns:          The percent-escaped `String`.
+    public func escape(_ string: String) -> String {
+        return string.addingPercentEncoding(withAllowedCharacters: .afURLQueryAllowed) ?? string
+    }
+
+    private func query(_ parameters: [String: Any]) -> String {
+        var components: [(String, String)] = []
+
+        for key in parameters.keys.sorted(by: <) {
+            let value = parameters[key]!
+            components += queryComponents(fromKey: key, value: value)
+        }
+        return components.map { "\($0)=\($1)" }.joined(separator: "&")
+    }
+}
+
+// MARK: -
+
+/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
+/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
+public struct JSONEncoding: ParameterEncoding {
+    // MARK: Properties
+
+    /// Returns a `JSONEncoding` instance with default writing options.
+    public static var `default`: JSONEncoding { return JSONEncoding() }
+
+    /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
+    public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) }
+
+    /// The options for writing the parameters as JSON data.
+    public let options: JSONSerialization.WritingOptions
+
+    // MARK: Initialization
+
+    /// Creates an instance using the specified `WritingOptions`.
+    ///
+    /// - Parameter options: `JSONSerialization.WritingOptions` to use.
+    public init(options: JSONSerialization.WritingOptions = []) {
+        self.options = options
+    }
+
+    // MARK: Encoding
+
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let parameters = parameters else { return urlRequest }
+
+        do {
+            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
+
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = data
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+        }
+
+        return urlRequest
+    }
+
+    /// Encodes any JSON compatible object into a `URLRequest`.
+    ///
+    /// - Parameters:
+    ///   - urlRequest: `URLRequestConvertible` value into which the object will be encoded.
+    ///   - jsonObject: `Any` value (must be JSON compatible` to be encoded into the `URLRequest`. `nil` by default.
+    ///
+    /// - Returns:      The encoded `URLRequest`.
+    /// - Throws:       Any `Error` produced during encoding.
+    public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let jsonObject = jsonObject else { return urlRequest }
+
+        do {
+            let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
+
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = data
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+        }
+
+        return urlRequest
+    }
+}
+
+// MARK: -
+
+extension NSNumber {
+    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
+}

+ 167 - 0
Pods/Alamofire/Source/Protector.swift

@@ -0,0 +1,167 @@
+//
+//  Protector.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+// MARK: -
+
+/// An `os_unfair_lock` wrapper.
+final class UnfairLock {
+    private let unfairLock: os_unfair_lock_t
+
+    init() {
+        unfairLock = .allocate(capacity: 1)
+        unfairLock.initialize(to: os_unfair_lock())
+    }
+
+    deinit {
+        unfairLock.deinitialize(count: 1)
+        unfairLock.deallocate()
+    }
+
+    private func lock() {
+        os_unfair_lock_lock(unfairLock)
+    }
+
+    private func unlock() {
+        os_unfair_lock_unlock(unfairLock)
+    }
+
+    /// Executes a closure returning a value while acquiring the lock.
+    ///
+    /// - Parameter closure: The closure to run.
+    ///
+    /// - Returns:           The value the closure generated.
+    func around<T>(_ closure: () -> T) -> T {
+        lock(); defer { unlock() }
+        return closure()
+    }
+
+    /// Execute a closure while acquiring the lock.
+    ///
+    /// - Parameter closure: The closure to run.
+    func around(_ closure: () -> Void) {
+        lock(); defer { unlock() }
+        return closure()
+    }
+}
+
+/// A thread-safe wrapper around a value.
+final class Protector<T> {
+    private let lock = UnfairLock()
+    private var value: T
+
+    init(_ value: T) {
+        self.value = value
+    }
+
+    /// The contained value. Unsafe for anything more than direct read or write.
+    var directValue: T {
+        get { return lock.around { value } }
+        set { lock.around { value = newValue } }
+    }
+
+    /// Synchronously read or transform the contained value.
+    ///
+    /// - Parameter closure: The closure to execute.
+    ///
+    /// - Returns:           The return value of the closure passed.
+    func read<U>(_ closure: (T) -> U) -> U {
+        return lock.around { closure(self.value) }
+    }
+
+    /// Synchronously modify the protected value.
+    ///
+    /// - Parameter closure: The closure to execute.
+    ///
+    /// - Returns:           The modified value.
+    @discardableResult
+    func write<U>(_ closure: (inout T) -> U) -> U {
+        return lock.around { closure(&self.value) }
+    }
+}
+
+extension Protector where T: RangeReplaceableCollection {
+    /// Adds a new element to the end of this protected collection.
+    ///
+    /// - Parameter newElement: The `Element` to append.
+    func append(_ newElement: T.Element) {
+        write { (ward: inout T) in
+            ward.append(newElement)
+        }
+    }
+
+    /// Adds the elements of a sequence to the end of this protected collection.
+    ///
+    /// - Parameter newElements: The `Sequence` to append.
+    func append<S: Sequence>(contentsOf newElements: S) where S.Element == T.Element {
+        write { (ward: inout T) in
+            ward.append(contentsOf: newElements)
+        }
+    }
+
+    /// Add the elements of a collection to the end of the protected collection.
+    ///
+    /// - Parameter newElements: The `Collection` to append.
+    func append<C: Collection>(contentsOf newElements: C) where C.Element == T.Element {
+        write { (ward: inout T) in
+            ward.append(contentsOf: newElements)
+        }
+    }
+}
+
+extension Protector where T == Data? {
+    /// Adds the contents of a `Data` value to the end of the protected `Data`.
+    ///
+    /// - Parameter data: The `Data` to be appended.
+    func append(_ data: Data) {
+        write { (ward: inout T) in
+            ward?.append(data)
+        }
+    }
+}
+
+extension Protector where T == Request.MutableState {
+    /// Attempts to transition to the passed `State`.
+    ///
+    /// - Parameter state: The `State` to attempt transition to.
+    ///
+    /// - Returns:         Whether the transition occurred.
+    func attemptToTransitionTo(_ state: Request.State) -> Bool {
+        return lock.around {
+            guard value.state.canTransitionTo(state) else { return false }
+
+            value.state = state
+
+            return true
+        }
+    }
+
+    /// Perform a closure while locked with the provided `Request.State`.
+    ///
+    /// - Parameter perform: The closure to perform while locked.
+    func withState(perform: (Request.State) -> Void) {
+        lock.around { perform(value.state) }
+    }
+}

+ 95 - 0
Pods/Alamofire/Source/RedirectHandler.swift

@@ -0,0 +1,95 @@
+//
+//  RedirectHandler.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that handles how an HTTP redirect response from a remote server should be redirected to the new request.
+public protocol RedirectHandler {
+    /// Determines how the HTTP redirect response should be redirected to the new request.
+    ///
+    /// The `completion` closure should be passed one of three possible options:
+    ///
+    ///   1. The new request specified by the redirect (this is the most common use case).
+    ///   2. A modified version of the new request (you may want to route it somewhere else).
+    ///   3. A `nil` value to deny the redirect request and return the body of the redirect response.
+    ///
+    /// - Parameters:
+    ///   - task:       The `URLSessionTask` whose request resulted in a redirect.
+    ///   - request:    The `URLRequest` to the new location specified by the redirect response.
+    ///   - response:   The `HTTPURLResponse` containing the server's response to the original request.
+    ///   - completion: The closure to execute containing the new `URLRequest`, a modified `URLRequest`, or `nil`.
+    func task(_ task: URLSessionTask,
+              willBeRedirectedTo request: URLRequest,
+              for response: HTTPURLResponse,
+              completion: @escaping (URLRequest?) -> Void)
+}
+
+// MARK: -
+
+/// `Redirector` is a convenience `RedirectHandler` making it easy to follow, not follow, or modify a redirect.
+public struct Redirector {
+    /// Defines the behavior of the `Redirector` type.
+    public enum Behavior {
+        /// Follow the redirect as defined in the response.
+        case follow
+        /// Do not follow the redirect defined in the response.
+        case doNotFollow
+        /// Modify the redirect request defined in the response.
+        case modify((URLSessionTask, URLRequest, HTTPURLResponse) -> URLRequest?)
+    }
+
+    /// Returns a `Redirector` with a `.follow` `Behavior`.
+    public static let follow = Redirector(behavior: .follow)
+    /// Returns a `Redirector` with a `.doNotFollow` `Behavior`.
+    public static let doNotFollow = Redirector(behavior: .doNotFollow)
+
+    /// The `Behavior` of the `Redirector`.
+    public let behavior: Behavior
+
+    /// Creates a `Redirector` instance from the `Behavior`.
+    ///
+    /// - Parameter behavior: The `Behavior`.
+    public init(behavior: Behavior) {
+        self.behavior = behavior
+    }
+}
+
+// MARK: -
+
+extension Redirector: RedirectHandler {
+    public func task(_ task: URLSessionTask,
+                     willBeRedirectedTo request: URLRequest,
+                     for response: HTTPURLResponse,
+                     completion: @escaping (URLRequest?) -> Void) {
+        switch behavior {
+        case .follow:
+            completion(request)
+        case .doNotFollow:
+            completion(nil)
+        case let .modify(closure):
+            let request = closure(task, request, response)
+            completion(request)
+        }
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1515 - 0
Pods/Alamofire/Source/Request.swift


+ 243 - 0
Pods/Alamofire/Source/RequestInterceptor.swift

@@ -0,0 +1,243 @@
+//
+//  RequestInterceptor.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
+public protocol RequestAdapter {
+    /// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
+    ///
+    /// - Parameters:
+    ///   - urlRequest: The `URLRequest` to adapt.
+    ///   - session:    The `Session` that will execute the `URLRequest`.
+    ///   - completion: The completion handler that must be called when adaptation is complete.
+    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
+}
+
+// MARK: -
+
+/// Outcome of determination whether retry is necessary.
+public enum RetryResult {
+    /// Retry should be attempted immediately.
+    case retry
+    /// Retry should be attempted after the associated `TimeInterval`.
+    case retryWithDelay(TimeInterval)
+    /// Do not retry.
+    case doNotRetry
+    /// Do not retry due to the associated `Error`.
+    case doNotRetryWithError(Error)
+}
+
+extension RetryResult {
+    var retryRequired: Bool {
+        switch self {
+        case .retry, .retryWithDelay: return true
+        default: return false
+        }
+    }
+
+    var delay: TimeInterval? {
+        switch self {
+        case let .retryWithDelay(delay): return delay
+        default: return nil
+        }
+    }
+
+    var error: Error? {
+        guard case let .doNotRetryWithError(error) = self else { return nil }
+        return error
+    }
+}
+
+/// A type that determines whether a request should be retried after being executed by the specified session manager
+/// and encountering an error.
+public protocol RequestRetrier {
+    /// Determines whether the `Request` should be retried by calling the `completion` closure.
+    ///
+    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
+    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
+    /// cleaned up after.
+    ///
+    /// - Parameters:
+    ///   - request:    `Request` that failed due to the provided `Error`.
+    ///   - session:    `Session` that produced the `Request`.
+    ///   - error:      `Error` encountered while executing the `Request`.
+    ///   - completion: Completion closure to be executed when a retry decision has been determined.
+    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
+}
+
+// MARK: -
+
+/// Type that provides both `RequestAdapter` and `RequestRetrier` functionality.
+public protocol RequestInterceptor: RequestAdapter, RequestRetrier {}
+
+extension RequestInterceptor {
+    public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+        completion(.success(urlRequest))
+    }
+
+    public func retry(_ request: Request,
+                      for session: Session,
+                      dueTo error: Error,
+                      completion: @escaping (RetryResult) -> Void) {
+        completion(.doNotRetry)
+    }
+}
+
+/// `RequestAdapter` closure definition.
+public typealias AdaptHandler = (URLRequest, Session, _ completion: @escaping (Result<URLRequest, Error>) -> Void) -> Void
+/// `RequestRetrier` closure definition.
+public typealias RetryHandler = (Request, Session, Error, _ completion: @escaping (RetryResult) -> Void) -> Void
+
+// MARK: -
+
+/// Closure-based `RequestAdapter`.
+open class Adapter: RequestInterceptor {
+    private let adaptHandler: AdaptHandler
+
+    /// Creates an instance using the provided closure.
+    ///
+    /// - Parameter adaptHandler: `AdaptHandler` closure to be executed when handling request adaptation.
+    public init(_ adaptHandler: @escaping AdaptHandler) {
+        self.adaptHandler = adaptHandler
+    }
+
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+        adaptHandler(urlRequest, session, completion)
+    }
+}
+
+// MARK: -
+
+/// Closure-based `RequestRetrier`.
+open class Retrier: RequestInterceptor {
+    private let retryHandler: RetryHandler
+
+    /// Creates an instance using the provided closure.
+    ///
+    /// - Parameter retryHandler: `RetryHandler` closure to be executed when handling request retry.
+    public init(_ retryHandler: @escaping RetryHandler) {
+        self.retryHandler = retryHandler
+    }
+
+    open func retry(_ request: Request,
+                    for session: Session,
+                    dueTo error: Error,
+                    completion: @escaping (RetryResult) -> Void) {
+        retryHandler(request, session, error, completion)
+    }
+}
+
+// MARK: -
+
+/// `RequestInterceptor` which can use multiple `RequestAdapter` and `RequestRetrier` values.
+open class Interceptor: RequestInterceptor {
+    /// All `RequestAdapter`s associated with the instance. These adapters will be run until one fails.
+    public let adapters: [RequestAdapter]
+    /// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
+    public let retriers: [RequestRetrier]
+
+    /// Creates an instance from `AdaptHandler` and `RetryHandler` closures.
+    ///
+    /// - Parameters:
+    ///   - adaptHandler: `AdaptHandler` closure to be used.
+    ///   - retryHandler: `RetryHandler` closure to be used.
+    public init(adaptHandler: @escaping AdaptHandler, retryHandler: @escaping RetryHandler) {
+        adapters = [Adapter(adaptHandler)]
+        retriers = [Retrier(retryHandler)]
+    }
+
+    /// Creates an instance from `RequestAdapter` and `RequestRetrier` values.
+    ///
+    /// - Parameters:
+    ///   - adapter: `RequestAdapter` value to be used.
+    ///   - retrier: `RequestRetrier` value to be used.
+    public init(adapter: RequestAdapter, retrier: RequestRetrier) {
+        adapters = [adapter]
+        retriers = [retrier]
+    }
+
+    /// Creates an instance from the arrays of `RequestAdapter` and `RequestRetrier` values.
+    ///
+    /// - Parameters:
+    ///   - adapters: `RequestAdapter` values to be used.
+    ///   - retriers: `RequestRetrier` values to be used.
+    public init(adapters: [RequestAdapter] = [], retriers: [RequestRetrier] = []) {
+        self.adapters = adapters
+        self.retriers = retriers
+    }
+
+    open func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
+        adapt(urlRequest, for: session, using: adapters, completion: completion)
+    }
+
+    private func adapt(_ urlRequest: URLRequest,
+                       for session: Session,
+                       using adapters: [RequestAdapter],
+                       completion: @escaping (Result<URLRequest, Error>) -> Void) {
+        var pendingAdapters = adapters
+
+        guard !pendingAdapters.isEmpty else { completion(.success(urlRequest)); return }
+
+        let adapter = pendingAdapters.removeFirst()
+
+        adapter.adapt(urlRequest, for: session) { result in
+            switch result {
+            case let .success(urlRequest):
+                self.adapt(urlRequest, for: session, using: pendingAdapters, completion: completion)
+            case .failure:
+                completion(result)
+            }
+        }
+    }
+
+    open func retry(_ request: Request,
+                    for session: Session,
+                    dueTo error: Error,
+                    completion: @escaping (RetryResult) -> Void) {
+        retry(request, for: session, dueTo: error, using: retriers, completion: completion)
+    }
+
+    private func retry(_ request: Request,
+                       for session: Session,
+                       dueTo error: Error,
+                       using retriers: [RequestRetrier],
+                       completion: @escaping (RetryResult) -> Void) {
+        var pendingRetriers = retriers
+
+        guard !pendingRetriers.isEmpty else { completion(.doNotRetry); return }
+
+        let retrier = pendingRetriers.removeFirst()
+
+        retrier.retry(request, for: session, dueTo: error) { result in
+            switch result {
+            case .retry, .retryWithDelay, .doNotRetryWithError:
+                completion(result)
+            case .doNotRetry:
+                // Only continue to the next retrier if retry was not triggered and no error was encountered
+                self.retry(request, for: session, dueTo: error, using: pendingRetriers, completion: completion)
+            }
+        }
+    }
+}

+ 140 - 0
Pods/Alamofire/Source/RequestTaskMap.swift

@@ -0,0 +1,140 @@
+//
+//  RequestTaskMap.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that maintains a two way, one to one map of `URLSessionTask`s to `Request`s.
+struct RequestTaskMap {
+    private var tasksToRequests: [URLSessionTask: Request]
+    private var requestsToTasks: [Request: URLSessionTask]
+    private var taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)]
+
+    var requests: [Request] {
+        return Array(tasksToRequests.values)
+    }
+
+    init(tasksToRequests: [URLSessionTask: Request] = [:],
+         requestsToTasks: [Request: URLSessionTask] = [:],
+         taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)] = [:]) {
+        self.tasksToRequests = tasksToRequests
+        self.requestsToTasks = requestsToTasks
+        self.taskEvents = taskEvents
+    }
+
+    subscript(_ request: Request) -> URLSessionTask? {
+        get { return requestsToTasks[request] }
+        set {
+            guard let newValue = newValue else {
+                guard let task = requestsToTasks[request] else {
+                    fatalError("RequestTaskMap consistency error: no task corresponding to request found.")
+                }
+
+                requestsToTasks.removeValue(forKey: request)
+                tasksToRequests.removeValue(forKey: task)
+                taskEvents.removeValue(forKey: task)
+
+                return
+            }
+
+            requestsToTasks[request] = newValue
+            tasksToRequests[newValue] = request
+            taskEvents[newValue] = (completed: false, metricsGathered: false)
+        }
+    }
+
+    subscript(_ task: URLSessionTask) -> Request? {
+        get { return tasksToRequests[task] }
+        set {
+            guard let newValue = newValue else {
+                guard let request = tasksToRequests[task] else {
+                    fatalError("RequestTaskMap consistency error: no request corresponding to task found.")
+                }
+
+                tasksToRequests.removeValue(forKey: task)
+                requestsToTasks.removeValue(forKey: request)
+                taskEvents.removeValue(forKey: task)
+
+                return
+            }
+
+            tasksToRequests[task] = newValue
+            requestsToTasks[newValue] = task
+            taskEvents[task] = (completed: false, metricsGathered: false)
+        }
+    }
+
+    var count: Int {
+        precondition(tasksToRequests.count == requestsToTasks.count,
+                     "RequestTaskMap.count invalid, requests.count: \(tasksToRequests.count) != tasks.count: \(requestsToTasks.count)")
+
+        return tasksToRequests.count
+    }
+
+    var eventCount: Int {
+        precondition(taskEvents.count == count, "RequestTaskMap.eventCount invalid, count: \(count) != taskEvents.count: \(taskEvents.count)")
+
+        return taskEvents.count
+    }
+
+    var isEmpty: Bool {
+        precondition(tasksToRequests.isEmpty == requestsToTasks.isEmpty,
+                     "RequestTaskMap.isEmpty invalid, requests.isEmpty: \(tasksToRequests.isEmpty) != tasks.isEmpty: \(requestsToTasks.isEmpty)")
+
+        return tasksToRequests.isEmpty
+    }
+
+    var isEventsEmpty: Bool {
+        precondition(taskEvents.isEmpty == isEmpty, "RequestTaskMap.isEventsEmpty invalid, isEmpty: \(isEmpty) != taskEvents.isEmpty: \(taskEvents.isEmpty)")
+
+        return taskEvents.isEmpty
+    }
+
+    mutating func disassociateIfNecessaryAfterGatheringMetricsForTask(_ task: URLSessionTask) -> Bool {
+        guard let events = taskEvents[task] else {
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
+        }
+
+        switch (events.completed, events.metricsGathered) {
+        case (_, true): fatalError("RequestTaskMap consistency error: duplicate metricsGatheredForTask call.")
+        case (false, false): taskEvents[task] = (completed: false, metricsGathered: true); return false
+        case (true, false): self[task] = nil; return true
+        }
+    }
+
+    mutating func disassociateIfNecessaryAfterCompletingTask(_ task: URLSessionTask) -> Bool {
+        guard let events = taskEvents[task] else {
+            fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
+        }
+
+        switch (events.completed, events.metricsGathered) {
+        case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
+        #if os(watchOS) // watchOS doesn't gather metrics, so unconditionally remove the reference and return true.
+        default: self[task] = nil; return true
+        #else
+        case (false, false): taskEvents[task] = (completed: true, metricsGathered: false); return false
+        case (false, true): self[task] = nil; return true
+        #endif
+        }
+    }
+}

+ 405 - 0
Pods/Alamofire/Source/Response.swift

@@ -0,0 +1,405 @@
+//
+//  Response.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Default type of `DataResponse` returned by Alamofire, with an `AFError` `Failure` type.
+public typealias AFDataResponse<Success> = DataResponse<Success, AFError>
+/// Default type of `DownloadResponse` returned by Alamofire, with an `AFError` `Failure` type.
+public typealias AFDownloadResponse<Success> = DownloadResponse<Success, AFError>
+
+/// Type used to store all values associated with a serialized response of a `DataRequest` or `UploadRequest`.
+public struct DataResponse<Success, Failure: Error> {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The data returned by the server.
+    public let data: Data?
+
+    /// The final metrics of the response.
+    ///
+    /// - Note: Due to `FB7624529`, collection of `URLSessionTaskMetrics` on watchOS is currently disabled.`
+    ///
+    public let metrics: URLSessionTaskMetrics?
+
+    /// The time taken to serialize the response.
+    public let serializationDuration: TimeInterval
+
+    /// The result of response serialization.
+    public let result: Result<Success, Failure>
+
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
+    public var value: Success? { return result.success }
+
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+    public var error: Failure? { return result.failure }
+
+    /// Creates a `DataResponse` instance with the specified parameters derived from the response serialization.
+    ///
+    /// - Parameters:
+    ///   - request:               The `URLRequest` sent to the server.
+    ///   - response:              The `HTTPURLResponse` from the server.
+    ///   - data:                  The `Data` returned by the server.
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DataRequest` or `UploadRequest`.
+    ///   - serializationDuration: The duration taken by serialization.
+    ///   - result:                The `Result` of response serialization.
+    public init(request: URLRequest?,
+                response: HTTPURLResponse?,
+                data: Data?,
+                metrics: URLSessionTaskMetrics?,
+                serializationDuration: TimeInterval,
+                result: Result<Success, Failure>) {
+        self.request = request
+        self.response = response
+        self.data = data
+        self.metrics = metrics
+        self.serializationDuration = serializationDuration
+        self.result = result
+    }
+}
+
+// MARK: -
+
+extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        return "\(result)"
+    }
+
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+    /// response, the server data, the duration of the network and serialization actions, and the response serialization
+    /// result.
+    public var debugDescription: String {
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
+        let responseDescription = response.map { response in
+            let sortedHeaders = response.headers.sorted()
+
+            return """
+            [Status Code]: \(response.statusCode)
+            [Headers]:
+            \(sortedHeaders)
+            """
+        } ?? "nil"
+        let responseBody = data.map { String(decoding: $0, as: UTF8.self) } ?? "None"
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
+
+        return """
+        [Request]: \(requestDescription)
+        [Request Body]: \n\(requestBody)
+        [Response]: \n\(responseDescription)
+        [Response Body]: \n\(responseBody)
+        [Data]: \(data?.description ?? "None")
+        [Network Duration]: \(metricsDescription)
+        [Serialization Duration]: \(serializationDuration)s
+        [Result]: \(result)
+        """
+    }
+}
+
+// MARK: -
+
+extension DataResponse {
+    /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `map` method with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleInt = possibleData.map { $0.count }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's
+    ///            result is a failure, returns a response wrapping the same failure.
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DataResponse<NewSuccess, Failure> {
+        return DataResponse<NewSuccess, Failure>(request: request,
+                                                 response: response,
+                                                 data: data,
+                                                 metrics: metrics,
+                                                 serializationDuration: serializationDuration,
+                                                 result: result.map(transform))
+    }
+
+    /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result
+    /// value as a parameter.
+    ///
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleObject = possibleData.tryMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's
+    ///            result is a failure, returns the same failure.
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DataResponse<NewSuccess, Error> {
+        return DataResponse<NewSuccess, Error>(request: request,
+                                               response: response,
+                                               data: data,
+                                               metrics: metrics,
+                                               serializationDuration: serializationDuration,
+                                               result: result.tryMap(transform))
+    }
+
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `mapError` function with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
+    ///
+    /// - Parameter transform: A closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DataResponse<Success, NewFailure> {
+        return DataResponse<Success, NewFailure>(request: request,
+                                                 response: response,
+                                                 data: data,
+                                                 metrics: metrics,
+                                                 serializationDuration: serializationDuration,
+                                                 result: result.mapError(transform))
+    }
+
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleObject = possibleData.tryMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DataResponse<Success, Error> {
+        return DataResponse<Success, Error>(request: request,
+                                            response: response,
+                                            data: data,
+                                            metrics: metrics,
+                                            serializationDuration: serializationDuration,
+                                            result: result.tryMapError(transform))
+    }
+}
+
+// MARK: -
+
+/// Used to store all data associated with a serialized response of a download request.
+public struct DownloadResponse<Success, Failure: Error> {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The final destination URL of the data returned from the server after it is moved.
+    public let fileURL: URL?
+
+    /// The resume data generated if the request was cancelled.
+    public let resumeData: Data?
+
+    /// The final metrics of the response.
+    ///
+    /// - Note: Due to `FB7624529`, collection of `URLSessionTaskMetrics` on watchOS is currently disabled.`
+    ///
+    public let metrics: URLSessionTaskMetrics?
+
+    /// The time taken to serialize the response.
+    public let serializationDuration: TimeInterval
+
+    /// The result of response serialization.
+    public let result: Result<Success, Failure>
+
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
+    public var value: Success? { return result.success }
+
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+    public var error: Failure? { return result.failure }
+
+    /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
+    ///
+    /// - Parameters:
+    ///   - request:               The `URLRequest` sent to the server.
+    ///   - response:              The `HTTPURLResponse` from the server.
+    ///   - temporaryURL:          The temporary destination `URL` of the data returned from the server.
+    ///   - destinationURL:        The final destination `URL` of the data returned from the server, if it was moved.
+    ///   - resumeData:            The resume `Data` generated if the request was cancelled.
+    ///   - metrics:               The `URLSessionTaskMetrics` of the `DownloadRequest`.
+    ///   - serializationDuration: The duration taken by serialization.
+    ///   - result:                The `Result` of response serialization.
+    public init(request: URLRequest?,
+                response: HTTPURLResponse?,
+                fileURL: URL?,
+                resumeData: Data?,
+                metrics: URLSessionTaskMetrics?,
+                serializationDuration: TimeInterval,
+                result: Result<Success, Failure>) {
+        self.request = request
+        self.response = response
+        self.fileURL = fileURL
+        self.resumeData = resumeData
+        self.metrics = metrics
+        self.serializationDuration = serializationDuration
+        self.result = result
+    }
+}
+
+// MARK: -
+
+extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        return "\(result)"
+    }
+
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+    /// response, the temporary and destination URLs, the resume data, the durations of the network and serialization
+    /// actions, and the response serialization result.
+    public var debugDescription: String {
+        let requestDescription = request.map { "\($0.httpMethod!) \($0)" } ?? "nil"
+        let requestBody = request?.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "None"
+        let responseDescription = response.map { response in
+            let sortedHeaders = response.headers.sorted()
+
+            return """
+            [Status Code]: \(response.statusCode)
+            [Headers]:
+            \(sortedHeaders)
+            """
+        } ?? "nil"
+        let metricsDescription = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
+        let resumeDataDescription = resumeData.map { "\($0)" } ?? "None"
+
+        return """
+        [Request]: \(requestDescription)
+        [Request Body]: \n\(requestBody)
+        [Response]: \n\(responseDescription)
+        [File URL]: \(fileURL?.path ?? "nil")
+        [ResumeData]: \(resumeDataDescription)
+        [Network Duration]: \(metricsDescription)
+        [Serialization Duration]: \(serializationDuration)s
+        [Result]: \(result)
+        """
+    }
+}
+
+// MARK: -
+
+extension DownloadResponse {
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `map` method with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleInt = possibleData.map { $0.count }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's
+    ///            result is a failure, returns a response wrapping the same failure.
+    public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> DownloadResponse<NewSuccess, Failure> {
+        return DownloadResponse<NewSuccess, Failure>(request: request,
+                                                     response: response,
+                                                     fileURL: fileURL,
+                                                     resumeData: resumeData,
+                                                     metrics: metrics,
+                                                     serializationDuration: serializationDuration,
+                                                     result: result.map(transform))
+    }
+
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleObject = possibleData.tryMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this
+    /// instance's result is a failure, returns the same failure.
+    public func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> DownloadResponse<NewSuccess, Error> {
+        return DownloadResponse<NewSuccess, Error>(request: request,
+                                                   response: response,
+                                                   fileURL: fileURL,
+                                                   resumeData: resumeData,
+                                                   metrics: metrics,
+                                                   serializationDuration: serializationDuration,
+                                                   result: result.tryMap(transform))
+    }
+
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `mapError` function with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
+    ///
+    /// - Parameter transform: A closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
+    public func mapError<NewFailure: Error>(_ transform: (Failure) -> NewFailure) -> DownloadResponse<Success, NewFailure> {
+        return DownloadResponse<Success, NewFailure>(request: request,
+                                                     response: response,
+                                                     fileURL: fileURL,
+                                                     resumeData: resumeData,
+                                                     metrics: metrics,
+                                                     serializationDuration: serializationDuration,
+                                                     result: result.mapError(transform))
+    }
+
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleObject = possibleData.tryMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
+    public func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> DownloadResponse<Success, Error> {
+        return DownloadResponse<Success, Error>(request: request,
+                                                response: response,
+                                                fileURL: fileURL,
+                                                resumeData: resumeData,
+                                                metrics: metrics,
+                                                serializationDuration: serializationDuration,
+                                                result: result.tryMapError(transform))
+    }
+}

+ 800 - 0
Pods/Alamofire/Source/ResponseSerialization.swift

@@ -0,0 +1,800 @@
+//
+//  ResponseSerialization.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+// MARK: Protocols
+
+/// The type to which all data response serializers must conform in order to serialize a response.
+public protocol DataResponseSerializerProtocol {
+    /// The type of serialized object to be created.
+    associatedtype SerializedObject
+
+    /// Serialize the response `Data` into the provided type..
+    ///
+    /// - Parameters:
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
+    ///   - response: `HTTPURLResponse` received from the server, if any.
+    ///   - data:     `Data` returned from the server, if any.
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
+    ///
+    /// - Returns:    The `SerializedObject`.
+    /// - Throws:     Any `Error` produced during serialization.
+    func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> SerializedObject
+}
+
+/// The type to which all download response serializers must conform in order to serialize a response.
+public protocol DownloadResponseSerializerProtocol {
+    /// The type of serialized object to be created.
+    associatedtype SerializedObject
+
+    /// Serialize the downloaded response `Data` from disk into the provided type..
+    ///
+    /// - Parameters:
+    ///   - request:  `URLRequest` which was used to perform the request, if any.
+    ///   - response: `HTTPURLResponse` received from the server, if any.
+    ///   - fileURL:  File `URL` to which the response data was downloaded.
+    ///   - error:    `Error` produced by Alamofire or the underlying `URLSession` during the request.
+    ///
+    /// - Returns:    The `SerializedObject`.
+    /// - Throws:     Any `Error` produced during serialization.
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> SerializedObject
+}
+
+/// A serializer that can handle both data and download responses.
+public protocol ResponseSerializer: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol {
+    /// `DataPreprocessor` used to prepare incoming `Data` for serialization.
+    var dataPreprocessor: DataPreprocessor { get }
+    /// `HTTPMethod`s for which empty response bodies are considered appropriate.
+    var emptyRequestMethods: Set<HTTPMethod> { get }
+    /// HTTP response codes for which empty response bodies are considered appropriate.
+    var emptyResponseCodes: Set<Int> { get }
+}
+
+/// Type used to preprocess `Data` before it handled by a serializer.
+public protocol DataPreprocessor {
+    /// Process           `Data` before it's handled by a serializer.
+    /// - Parameter data: The raw `Data` to process.
+    func preprocess(_ data: Data) throws -> Data
+}
+
+/// `DataPreprocessor` that returns passed `Data` without any transform.
+public struct PassthroughPreprocessor: DataPreprocessor {
+    public init() {}
+
+    public func preprocess(_ data: Data) throws -> Data { return data }
+}
+
+/// `DataPreprocessor` that trims Google's typical `)]}',\n` XSSI JSON header.
+public struct GoogleXSSIPreprocessor: DataPreprocessor {
+    public init() {}
+
+    public func preprocess(_ data: Data) throws -> Data {
+        return (data.prefix(6) == Data(")]}',\n".utf8)) ? data.dropFirst(6) : data
+    }
+}
+
+extension ResponseSerializer {
+    /// Default `DataPreprocessor`. `PassthroughPreprocessor` by default.
+    public static var defaultDataPreprocessor: DataPreprocessor { return PassthroughPreprocessor() }
+    /// Default `HTTPMethod`s for which empty response bodies are considered appropriate. `[.head]` by default.
+    public static var defaultEmptyRequestMethods: Set<HTTPMethod> { return [.head] }
+    /// HTTP response codes for which empty response bodies are considered appropriate. `[204, 205]` by default.
+    public static var defaultEmptyResponseCodes: Set<Int> { return [204, 205] }
+
+    public var dataPreprocessor: DataPreprocessor { return Self.defaultDataPreprocessor }
+    public var emptyRequestMethods: Set<HTTPMethod> { return Self.defaultEmptyRequestMethods }
+    public var emptyResponseCodes: Set<Int> { return Self.defaultEmptyResponseCodes }
+
+    /// Determines whether the `request` allows empty response bodies, if `request` exists.
+    ///
+    /// - Parameter request: `URLRequest` to evaluate.
+    ///
+    /// - Returns:           `Bool` representing the outcome of the evaluation, or `nil` if `request` was `nil`.
+    public func requestAllowsEmptyResponseData(_ request: URLRequest?) -> Bool? {
+        return request.flatMap { $0.httpMethod }
+            .flatMap(HTTPMethod.init)
+            .map { emptyRequestMethods.contains($0) }
+    }
+
+    /// Determines whether the `response` allows empty response bodies, if `response` exists`.
+    ///
+    /// - Parameter response: `HTTPURLResponse` to evaluate.
+    ///
+    /// - Returns:            `Bool` representing the outcome of the evaluation, or `nil` if `response` was `nil`.
+    public func responseAllowsEmptyResponseData(_ response: HTTPURLResponse?) -> Bool? {
+        return response.flatMap { $0.statusCode }
+            .map { emptyResponseCodes.contains($0) }
+    }
+
+    /// Determines whether `request` and `response` allow empty response bodies.
+    ///
+    /// - Parameters:
+    ///   - request:  `URLRequest` to evaluate.
+    ///   - response: `HTTPURLResponse` to evaluate.
+    ///
+    /// - Returns:    `true` if `request` or `response` allow empty bodies, `false` otherwise.
+    public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
+        return (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
+    }
+}
+
+/// By default, any serializer declared to conform to both types will get file serialization for free, as it just feeds
+/// the data read from disk into the data response serializer.
+public extension DownloadResponseSerializerProtocol where Self: DataResponseSerializerProtocol {
+    func serializeDownload(request: URLRequest?, response: HTTPURLResponse?, fileURL: URL?, error: Error?) throws -> Self.SerializedObject {
+        guard error == nil else { throw error! }
+
+        guard let fileURL = fileURL else {
+            throw AFError.responseSerializationFailed(reason: .inputFileNil)
+        }
+
+        let data: Data
+        do {
+            data = try Data(contentsOf: fileURL)
+        } catch {
+            throw AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))
+        }
+
+        do {
+            return try serialize(request: request, response: response, data: data, error: error)
+        } catch {
+            throw error
+        }
+    }
+}
+
+// MARK: - Default
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse<Data?>) -> Void) -> Self {
+        appendResponseSerializer {
+            // Start work that should be on the serialization queue.
+            let result = AFResult<Data?>(value: self.data, error: self.error)
+            // End work that should be on the serialization queue.
+
+            self.underlyingQueue.async {
+                let response = DataResponse(request: self.request,
+                                            response: self.response,
+                                            data: self.data,
+                                            metrics: self.metrics,
+                                            serializationDuration: 0,
+                                            result: result)
+
+                self.eventMonitor?.request(self, didParseResponse: response)
+
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+            }
+        }
+
+        return self
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data.
+    ///   - completionHandler:  The code to be executed once the request has finished.
+    ///
+    /// - Returns:              The request.
+    @discardableResult
+    public func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
+                                                                     responseSerializer: Serializer,
+                                                                     completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
+        -> Self {
+        appendResponseSerializer {
+            // Start work that should be on the serialization queue.
+            let start = CFAbsoluteTimeGetCurrent()
+            let result: AFResult<Serializer.SerializedObject> = Result {
+                try responseSerializer.serialize(request: self.request,
+                                                 response: self.response,
+                                                 data: self.data,
+                                                 error: self.error)
+            }.mapError { error in
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
+            }
+
+            let end = CFAbsoluteTimeGetCurrent()
+            // End work that should be on the serialization queue.
+
+            self.underlyingQueue.async {
+                let response = DataResponse(request: self.request,
+                                            response: self.response,
+                                            data: self.data,
+                                            metrics: self.metrics,
+                                            serializationDuration: end - start,
+                                            result: result)
+
+                self.eventMonitor?.request(self, didParseResponse: response)
+
+                guard let serializerError = result.failure, let delegate = self.delegate else {
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+                    return
+                }
+
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
+                    var didComplete: (() -> Void)?
+
+                    defer {
+                        if let didComplete = didComplete {
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
+                        }
+                    }
+
+                    switch retryResult {
+                    case .doNotRetry:
+                        didComplete = { completionHandler(response) }
+
+                    case let .doNotRetryWithError(retryError):
+                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+
+                        let response = DataResponse(request: self.request,
+                                                    response: self.response,
+                                                    data: self.data,
+                                                    metrics: self.metrics,
+                                                    serializationDuration: end - start,
+                                                    result: result)
+
+                        didComplete = { completionHandler(response) }
+
+                    case .retry, .retryWithDelay:
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
+                    }
+                }
+            }
+        }
+
+        return self
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func response(queue: DispatchQueue = .main,
+                         completionHandler: @escaping (AFDownloadResponse<URL?>) -> Void)
+        -> Self {
+        appendResponseSerializer {
+            // Start work that should be on the serialization queue.
+            let result = AFResult<URL?>(value: self.fileURL, error: self.error)
+            // End work that should be on the serialization queue.
+
+            self.underlyingQueue.async {
+                let response = DownloadResponse(request: self.request,
+                                                response: self.response,
+                                                fileURL: self.fileURL,
+                                                resumeData: self.resumeData,
+                                                metrics: self.metrics,
+                                                serializationDuration: 0,
+                                                result: result)
+
+                self.eventMonitor?.request(self, didParseResponse: response)
+
+                self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+            }
+        }
+
+        return self
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:              The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - responseSerializer: The response serializer responsible for serializing the request, response, and data
+    ///                         contained in the destination `URL`.
+    ///   - completionHandler:  The code to be executed once the request has finished.
+    ///
+    /// - Returns:              The request.
+    @discardableResult
+    public func response<Serializer: DownloadResponseSerializerProtocol>(queue: DispatchQueue = .main,
+                                                                         responseSerializer: Serializer,
+                                                                         completionHandler: @escaping (AFDownloadResponse<Serializer.SerializedObject>) -> Void)
+        -> Self {
+        appendResponseSerializer {
+            // Start work that should be on the serialization queue.
+            let start = CFAbsoluteTimeGetCurrent()
+            let result: AFResult<Serializer.SerializedObject> = Result {
+                try responseSerializer.serializeDownload(request: self.request,
+                                                         response: self.response,
+                                                         fileURL: self.fileURL,
+                                                         error: self.error)
+            }.mapError { error in
+                error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
+            }
+            let end = CFAbsoluteTimeGetCurrent()
+            // End work that should be on the serialization queue.
+
+            self.underlyingQueue.async {
+                let response = DownloadResponse(request: self.request,
+                                                response: self.response,
+                                                fileURL: self.fileURL,
+                                                resumeData: self.resumeData,
+                                                metrics: self.metrics,
+                                                serializationDuration: end - start,
+                                                result: result)
+
+                self.eventMonitor?.request(self, didParseResponse: response)
+
+                guard let serializerError = result.failure, let delegate = self.delegate else {
+                    self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+                    return
+                }
+
+                delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
+                    var didComplete: (() -> Void)?
+
+                    defer {
+                        if let didComplete = didComplete {
+                            self.responseSerializerDidComplete { queue.async { didComplete() } }
+                        }
+                    }
+
+                    switch retryResult {
+                    case .doNotRetry:
+                        didComplete = { completionHandler(response) }
+
+                    case let .doNotRetryWithError(retryError):
+                        let result: AFResult<Serializer.SerializedObject> = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+
+                        let response = DownloadResponse(request: self.request,
+                                                        response: self.response,
+                                                        fileURL: self.fileURL,
+                                                        resumeData: self.resumeData,
+                                                        metrics: self.metrics,
+                                                        serializationDuration: end - start,
+                                                        result: result)
+
+                        didComplete = { completionHandler(response) }
+
+                    case .retry, .retryWithDelay:
+                        delegate.retryRequest(self, withDelay: retryResult.delay)
+                    }
+                }
+            }
+        }
+
+        return self
+    }
+}
+
+// MARK: - Data
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseData(queue: DispatchQueue = .main,
+                             completionHandler: @escaping (AFDataResponse<Data>) -> Void)
+        -> Self {
+        return response(queue: queue,
+                        responseSerializer: DataResponseSerializer(),
+                        completionHandler: completionHandler)
+    }
+}
+
+/// A `ResponseSerializer` that performs minimal response checking and returns any response data as-is. By default, a
+/// request returning `nil` or no data is considered an error. However, if the response is has a status code valid for
+/// empty responses (`204`, `205`), then an empty `Data` value is returned.
+public final class DataResponseSerializer: ResponseSerializer {
+    public let dataPreprocessor: DataPreprocessor
+    public let emptyResponseCodes: Set<Int>
+    public let emptyRequestMethods: Set<HTTPMethod>
+
+    /// Creates an instance using the provided values.
+    ///
+    /// - Parameters:
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
+    public init(dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
+                emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
+                emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) {
+        self.dataPreprocessor = dataPreprocessor
+        self.emptyResponseCodes = emptyResponseCodes
+        self.emptyRequestMethods = emptyRequestMethods
+    }
+
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data {
+        guard error == nil else { throw error! }
+
+        guard var data = data, !data.isEmpty else {
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
+            }
+
+            return Data()
+        }
+
+        data = try dataPreprocessor.preprocess(data)
+
+        return data
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseData(queue: DispatchQueue = .main,
+                             completionHandler: @escaping (AFDownloadResponse<Data>) -> Void)
+        -> Self {
+        return response(queue: queue,
+                        responseSerializer: DataResponseSerializer(),
+                        completionHandler: completionHandler)
+    }
+}
+
+// MARK: - String
+
+/// A `ResponseSerializer` that decodes the response data as a `String`. By default, a request returning `nil` or no
+/// data is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`),
+/// then an empty `String` is returned.
+public final class StringResponseSerializer: ResponseSerializer {
+    public let dataPreprocessor: DataPreprocessor
+    /// Optional string encoding used to validate the response.
+    public let encoding: String.Encoding?
+    public let emptyResponseCodes: Set<Int>
+    public let emptyRequestMethods: Set<HTTPMethod>
+
+    /// Creates an instance with the provided values.
+    ///
+    /// - Parameters:
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
+    ///   - encoding:            A string encoding. Defaults to `nil`, in which case the encoding will be determined
+    ///                          from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
+    public init(dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
+                encoding: String.Encoding? = nil,
+                emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
+                emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods) {
+        self.dataPreprocessor = dataPreprocessor
+        self.encoding = encoding
+        self.emptyResponseCodes = emptyResponseCodes
+        self.emptyRequestMethods = emptyRequestMethods
+    }
+
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> String {
+        guard error == nil else { throw error! }
+
+        guard var data = data, !data.isEmpty else {
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
+            }
+
+            return ""
+        }
+
+        data = try dataPreprocessor.preprocess(data)
+
+        var convertedEncoding = encoding
+
+        if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil {
+            let ianaCharSet = CFStringConvertIANACharSetNameToEncoding(encodingName)
+            let nsStringEncoding = CFStringConvertEncodingToNSStringEncoding(ianaCharSet)
+            convertedEncoding = String.Encoding(rawValue: nsStringEncoding)
+        }
+
+        let actualEncoding = convertedEncoding ?? .isoLatin1
+
+        guard let string = String(data: data, encoding: actualEncoding) else {
+            throw AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))
+        }
+
+        return string
+    }
+}
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseString(queue: DispatchQueue = .main,
+                               encoding: String.Encoding? = nil,
+                               completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self {
+        return response(queue: queue,
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
+                        completionHandler: completionHandler)
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - encoding:          The string encoding. Defaults to `nil`, in which case the encoding will be determined from
+    ///                        the server response, falling back to the default HTTP character set, `ISO-8859-1`.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseString(queue: DispatchQueue = .main,
+                               encoding: String.Encoding? = nil,
+                               completionHandler: @escaping (AFDownloadResponse<String>) -> Void)
+        -> Self {
+        return response(queue: queue,
+                        responseSerializer: StringResponseSerializer(encoding: encoding),
+                        completionHandler: completionHandler)
+    }
+}
+
+// MARK: - JSON
+
+/// A `ResponseSerializer` that decodes the response data using `JSONSerialization`. By default, a request returning
+/// `nil` or no data is considered an error. However, if the response is has a status code valid for empty responses
+/// (`204`, `205`), then an `NSNull`  value is returned.
+public final class JSONResponseSerializer: ResponseSerializer {
+    public let dataPreprocessor: DataPreprocessor
+    public let emptyResponseCodes: Set<Int>
+    public let emptyRequestMethods: Set<HTTPMethod>
+    /// `JSONSerialization.ReadingOptions` used when serializing a response.
+    public let options: JSONSerialization.ReadingOptions
+
+    /// Creates an instance with the provided values.
+    ///
+    /// - Parameters:
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
+    ///   - options:             The options to use. `.allowFragments` by default.
+    public init(dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
+                emptyResponseCodes: Set<Int> = JSONResponseSerializer.defaultEmptyResponseCodes,
+                emptyRequestMethods: Set<HTTPMethod> = JSONResponseSerializer.defaultEmptyRequestMethods,
+                options: JSONSerialization.ReadingOptions = .allowFragments) {
+        self.dataPreprocessor = dataPreprocessor
+        self.emptyResponseCodes = emptyResponseCodes
+        self.emptyRequestMethods = emptyRequestMethods
+        self.options = options
+    }
+
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Any {
+        guard error == nil else { throw error! }
+
+        guard var data = data, !data.isEmpty else {
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
+            }
+
+            return NSNull()
+        }
+
+        data = try dataPreprocessor.preprocess(data)
+
+        do {
+            return try JSONSerialization.jsonObject(with: data, options: options)
+        } catch {
+            throw AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))
+        }
+    }
+}
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseJSON(queue: DispatchQueue = .main,
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
+                             completionHandler: @escaping (AFDataResponse<Any>) -> Void) -> Self {
+        return response(queue: queue,
+                        responseSerializer: JSONResponseSerializer(options: options),
+                        completionHandler: completionHandler)
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - options:           The JSON serialization reading options. `.allowFragments` by default.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseJSON(queue: DispatchQueue = .main,
+                             options: JSONSerialization.ReadingOptions = .allowFragments,
+                             completionHandler: @escaping (AFDownloadResponse<Any>) -> Void)
+        -> Self {
+        return response(queue: queue,
+                        responseSerializer: JSONResponseSerializer(options: options),
+                        completionHandler: completionHandler)
+    }
+}
+
+// MARK: - Empty
+
+/// Protocol representing an empty response. Use `T.emptyValue()` to get an instance.
+public protocol EmptyResponse {
+    /// Empty value for the conforming type.
+    ///
+    /// - Returns: Value of `Self` to use for empty values.
+    static func emptyValue() -> Self
+}
+
+/// Type representing an empty response. Use `Empty.value` to get the static instance.
+public struct Empty: Decodable {
+    /// Static `Empty` instance used for all `Empty` responses.
+    public static let value = Empty()
+}
+
+extension Empty: EmptyResponse {
+    public static func emptyValue() -> Empty {
+        return value
+    }
+}
+
+// MARK: - DataDecoder Protocol
+
+/// Any type which can decode `Data` into a `Decodable` type.
+public protocol DataDecoder {
+    /// Decode `Data` into the provided type.
+    ///
+    /// - Parameters:
+    ///   - type:  The `Type` to be decoded.
+    ///   - data:  The `Data` to be decoded.
+    ///
+    /// - Returns: The decoded value of type `D`.
+    /// - Throws:  Any error that occurs during decode.
+    func decode<D: Decodable>(_ type: D.Type, from data: Data) throws -> D
+}
+
+/// `JSONDecoder` automatically conforms to `DataDecoder`.
+extension JSONDecoder: DataDecoder {}
+
+// MARK: - Decodable
+
+/// A `ResponseSerializer` that decodes the response data as a generic value using any type that conforms to
+/// `DataDecoder`. By default, this is an instance of `JSONDecoder`. Additionally, a request returning `nil` or no data
+/// is considered an error. However, if the response is has a status code valid for empty responses (`204`, `205`), then
+/// the `Empty.value` value is returned.
+public final class DecodableResponseSerializer<T: Decodable>: ResponseSerializer {
+    public let dataPreprocessor: DataPreprocessor
+    /// The `DataDecoder` instance used to decode responses.
+    public let decoder: DataDecoder
+    public let emptyResponseCodes: Set<Int>
+    public let emptyRequestMethods: Set<HTTPMethod>
+
+    /// Creates an instance using the values provided.
+    ///
+    /// - Parameters:
+    ///   - dataPreprocessor:    `DataPreprocessor` used to prepare the received `Data` for serialization.
+    ///   - decoder:             The `DataDecoder`. `JSONDecoder()` by default.
+    ///   - emptyResponseCodes:  The HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
+    ///   - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. `[.head]` by default.
+    public init(dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
+                decoder: DataDecoder = JSONDecoder(),
+                emptyResponseCodes: Set<Int> = DecodableResponseSerializer.defaultEmptyResponseCodes,
+                emptyRequestMethods: Set<HTTPMethod> = DecodableResponseSerializer.defaultEmptyRequestMethods) {
+        self.dataPreprocessor = dataPreprocessor
+        self.decoder = decoder
+        self.emptyResponseCodes = emptyResponseCodes
+        self.emptyRequestMethods = emptyRequestMethods
+    }
+
+    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
+        guard error == nil else { throw error! }
+
+        guard var data = data, !data.isEmpty else {
+            guard emptyResponseAllowed(forRequest: request, response: response) else {
+                throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
+            }
+
+            guard let emptyResponseType = T.self as? EmptyResponse.Type, let emptyValue = emptyResponseType.emptyValue() as? T else {
+                throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
+            }
+
+            return emptyValue
+        }
+
+        data = try dataPreprocessor.preprocess(data)
+
+        do {
+            return try decoder.decode(T.self, from: data)
+        } catch {
+            throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
+        }
+    }
+}
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - type:              `Decodable` type to decode from response data.
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - decoder:           `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
+                                                queue: DispatchQueue = .main,
+                                                decoder: DataDecoder = JSONDecoder(),
+                                                completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
+        return response(queue: queue,
+                        responseSerializer: DecodableResponseSerializer(decoder: decoder),
+                        completionHandler: completionHandler)
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - Parameters:
+    ///   - type:              `Decodable` type to decode from response data.
+    ///   - queue:             The queue on which the completion handler is dispatched. `.main` by default.
+    ///   - decoder:           `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
+    ///   - completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - Returns:             The request.
+    @discardableResult
+    public func responseDecodable<T: Decodable>(of type: T.Type = T.self,
+                                                queue: DispatchQueue = .main,
+                                                decoder: DataDecoder = JSONDecoder(),
+                                                completionHandler: @escaping (AFDownloadResponse<T>) -> Void) -> Self {
+        return response(queue: queue,
+                        responseSerializer: DecodableResponseSerializer(decoder: decoder),
+                        completionHandler: completionHandler)
+    }
+}

+ 109 - 0
Pods/Alamofire/Source/Result+Alamofire.swift

@@ -0,0 +1,109 @@
+//
+//  Result+Alamofire.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Default type of `Result` returned by Alamofire, with an `AFError` `Failure` type.
+public typealias AFResult<Success> = Result<Success, AFError>
+
+// MARK: - Internal APIs
+
+extension Result {
+    /// Returns the associated value if the result is a success, `nil` otherwise.
+    var success: Success? {
+        guard case let .success(value) = self else { return nil }
+        return value
+    }
+
+    /// Returns the associated error value if the result is a failure, `nil` otherwise.
+    var failure: Failure? {
+        guard case let .failure(error) = self else { return nil }
+        return error
+    }
+
+    /// Initializes a `Result` from value or error. Returns `.failure` if the error is non-nil, `.success` otherwise.
+    ///
+    /// - Parameters:
+    ///   - value: A value.
+    ///   - error: An `Error`.
+    init(value: Success, error: Failure?) {
+        if let error = error {
+            self = .failure(error)
+        } else {
+            self = .success(value)
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
+    ///
+    /// Use the `tryMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
+    ///     let possibleObject = possibleData.tryMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance.
+    ///
+    /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
+    ///            same failure.
+    func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
+        switch self {
+        case let .success(value):
+            do {
+                return try .success(transform(value))
+            } catch {
+                return .failure(error)
+            }
+        case let .failure(error):
+            return .failure(error)
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `tryMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: Result<Data, Error> = .success(Data(...))
+    ///     let possibleObject = possibleData.tryMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
+    ///            the same success.
+    func tryMapError<NewFailure: Error>(_ transform: (Failure) throws -> NewFailure) -> Result<Success, Error> {
+        switch self {
+        case let .failure(error):
+            do {
+                return try .failure(transform(error))
+            } catch {
+                return .failure(error)
+            }
+        case let .success(value):
+            return .success(value)
+        }
+    }
+}

+ 367 - 0
Pods/Alamofire/Source/RetryPolicy.swift

@@ -0,0 +1,367 @@
+//
+//  RetryPolicy.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A retry policy that retries requests using an exponential backoff for allowed HTTP methods and HTTP status codes
+/// as well as certain types of networking errors.
+open class RetryPolicy: RequestInterceptor {
+    /// The default retry limit for retry policies.
+    public static let defaultRetryLimit: UInt = 2
+
+    /// The default exponential backoff base for retry policies (must be a minimum of 2).
+    public static let defaultExponentialBackoffBase: UInt = 2
+
+    /// The default exponential backoff scale for retry policies.
+    public static let defaultExponentialBackoffScale: Double = 0.5
+
+    /// The default HTTP methods to retry.
+    /// See [RFC 2616 - Section 9.1.2](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) for more information.
+    public static let defaultRetryableHTTPMethods: Set<HTTPMethod> = [.delete, // [Delete](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7) - not always idempotent
+                                                                      .get, // [GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3) - generally idempotent
+                                                                      .head, // [HEAD](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4) - generally idempotent
+                                                                      .options, // [OPTIONS](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2) - inherently idempotent
+                                                                      .put, // [PUT](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) - not always idempotent
+                                                                      .trace // [TRACE](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.8) - inherently idempotent
+    ]
+
+    /// The default HTTP status codes to retry.
+    /// See [RFC 2616 - Section 10](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10) for more information.
+    public static let defaultRetryableHTTPStatusCodes: Set<Int> = [408, // [Request Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9)
+                                                                   500, // [Internal Server Error](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1)
+                                                                   502, // [Bad Gateway](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3)
+                                                                   503, // [Service Unavailable](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4)
+                                                                   504 // [Gateway Timeout](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.5)
+    ]
+
+    /// The default URL error codes to retry.
+    public static let defaultRetryableURLErrorCodes: Set<URLError.Code> = [// [Security] App Transport Security disallowed a connection because there is no secure network connection.
+        //   - [Disabled] ATS settings do not change at runtime.
+        // .appTransportSecurityRequiresSecureConnection,
+
+        // [System] An app or app extension attempted to connect to a background session that is already connected to a
+        // process.
+        //   - [Enabled] The other process could release the background session.
+        .backgroundSessionInUseByAnotherProcess,
+                                                                           
+        // [System] The shared container identifier of the URL session configuration is needed but has not been set.
+        //   - [Disabled] Cannot change at runtime.
+        // .backgroundSessionRequiresSharedContainer,
+
+        // [System] The app is suspended or exits while a background data task is processing.
+        //   - [Enabled] App can be foregrounded or launched to recover.
+        .backgroundSessionWasDisconnected,
+                                                                           
+        // [Network] The URL Loading system received bad data from the server.
+        //   - [Enabled] Server could return valid data when retrying.
+        .badServerResponse,
+                                                                           
+        // [Resource] A malformed URL prevented a URL request from being initiated.
+        //   - [Disabled] URL was most likely constructed incorrectly.
+        // .badURL,
+
+        // [System] A connection was attempted while a phone call is active on a network that does not support
+        // simultaneous phone and data communication (EDGE or GPRS).
+        //   - [Enabled] Phone call could be ended to allow request to recover.
+        .callIsActive,
+                                                                           
+        // [Client] An asynchronous load has been canceled.
+        //   - [Disabled] Request was cancelled by the client.
+        // .cancelled,
+
+        // [File System] A download task couldn’t close the downloaded file on disk.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotCloseFile,
+
+        // [Network] An attempt to connect to a host failed.
+        //   - [Enabled] Server or DNS lookup could recover during retry.
+        .cannotConnectToHost,
+                                                                           
+        // [File System] A download task couldn’t create the downloaded file on disk because of an I/O failure.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotCreateFile,
+
+        // [Data] Content data received during a connection request had an unknown content encoding.
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
+        // .cannotDecodeContentData,
+
+        // [Data] Content data received during a connection request could not be decoded for a known content encoding.
+        //   - [Disabled] Server is unlikely to modify the content encoding during a retry.
+        // .cannotDecodeRawData,
+
+        // [Network] The host name for a URL could not be resolved.
+        //   - [Enabled] Server or DNS lookup could recover during retry.
+        .cannotFindHost,
+                                                                           
+        // [Network] A request to load an item only from the cache could not be satisfied.
+        //   - [Enabled] Cache could be populated during a retry.
+        .cannotLoadFromNetwork,
+                                                                           
+        // [File System] A download task was unable to move a downloaded file on disk.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotMoveFile,
+
+        // [File System] A download task was unable to open the downloaded file on disk.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotOpenFile,
+
+        // [Data] A task could not parse a response.
+        //   - [Disabled] Invalid response is unlikely to recover with retry.
+        // .cannotParseResponse,
+
+        // [File System] A download task was unable to remove a downloaded file from disk.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotRemoveFile,
+
+        // [File System] A download task was unable to write to the downloaded file on disk.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .cannotWriteToFile,
+
+        // [Security] A client certificate was rejected.
+        //   - [Disabled] Client certificate is unlikely to change with retry.
+        // .clientCertificateRejected,
+
+        // [Security] A client certificate was required to authenticate an SSL connection during a request.
+        //   - [Disabled] Client certificate is unlikely to be provided with retry.
+        // .clientCertificateRequired,
+
+        // [Data] The length of the resource data exceeds the maximum allowed.
+        //   - [Disabled] Resource will likely still exceed the length maximum on retry.
+        // .dataLengthExceedsMaximum,
+
+        // [System] The cellular network disallowed a connection.
+        //   - [Enabled] WiFi connection could be established during retry.
+        .dataNotAllowed,
+                                                                           
+        // [Network] The host address could not be found via DNS lookup.
+        //   - [Enabled] DNS lookup could succeed during retry.
+        .dnsLookupFailed,
+                                                                           
+        // [Data] A download task failed to decode an encoded file during the download.
+        //   - [Enabled] Server could correct the decoding issue with retry.
+        .downloadDecodingFailedMidStream,
+                                                                           
+        // [Data] A download task failed to decode an encoded file after downloading.
+        //   - [Enabled] Server could correct the decoding issue with retry.
+        .downloadDecodingFailedToComplete,
+                                                                           
+        // [File System] A file does not exist.
+        //   - [Disabled] File system error is unlikely to recover with retry.
+        // .fileDoesNotExist,
+
+        // [File System] A request for an FTP file resulted in the server responding that the file is not a plain file,
+        // but a directory.
+        //   - [Disabled] FTP directory is not likely to change to a file during a retry.
+        // .fileIsDirectory,
+
+        // [Network] A redirect loop has been detected or the threshold for number of allowable redirects has been
+        // exceeded (currently 16).
+        //   - [Disabled] The redirect loop is unlikely to be resolved within the retry window.
+        // .httpTooManyRedirects,
+
+        // [System] The attempted connection required activating a data context while roaming, but international roaming
+        // is disabled.
+        //   - [Enabled] WiFi connection could be established during retry.
+        .internationalRoamingOff,
+                                                                           
+        // [Connectivity] A client or server connection was severed in the middle of an in-progress load.
+        //   - [Enabled] A network connection could be established during retry.
+        .networkConnectionLost,
+                                                                           
+        // [File System] A resource couldn’t be read because of insufficient permissions.
+        //   - [Disabled] Permissions are unlikely to be granted during retry.
+        // .noPermissionsToReadFile,
+
+        // [Connectivity] A network resource was requested, but an internet connection has not been established and
+        // cannot be established automatically.
+        //   - [Enabled] A network connection could be established during retry.
+        .notConnectedToInternet,
+                                                                           
+        // [Resource] A redirect was specified by way of server response code, but the server did not accompany this
+        // code with a redirect URL.
+        //   - [Disabled] The redirect URL is unlikely to be supplied during a retry.
+        // .redirectToNonExistentLocation,
+
+        // [Client] A body stream is needed but the client did not provide one.
+        //   - [Disabled] The client will be unlikely to supply a body stream during retry.
+        // .requestBodyStreamExhausted,
+
+        // [Resource] A requested resource couldn’t be retrieved.
+        //   - [Disabled] The resource is unlikely to become available during the retry window.
+        // .resourceUnavailable,
+
+        // [Security] An attempt to establish a secure connection failed for reasons that can’t be expressed more
+        // specifically.
+        //   - [Enabled] The secure connection could be established during a retry given the lack of specificity
+        //     provided by the error.
+        .secureConnectionFailed,
+                                                                           
+        // [Security] A server certificate had a date which indicates it has expired, or is not yet valid.
+        //   - [Enabled] The server certificate could become valid within the retry window.
+        .serverCertificateHasBadDate,
+                                                                           
+        // [Security] A server certificate was not signed by any root server.
+        //   - [Disabled] The server certificate is unlikely to change during the retry window.
+        // .serverCertificateHasUnknownRoot,
+
+        // [Security] A server certificate is not yet valid.
+        //   - [Enabled] The server certificate could become valid within the retry window.
+        .serverCertificateNotYetValid,
+                                                                           
+        // [Security] A server certificate was signed by a root server that isn’t trusted.
+        //   - [Disabled] The server certificate is unlikely to become trusted within the retry window.
+        // .serverCertificateUntrusted,
+
+        // [Network] An asynchronous operation timed out.
+        //   - [Enabled] The request timed out for an unknown reason and should be retried.
+        .timedOut
+
+        // [System] The URL Loading System encountered an error that it can’t interpret.
+        //   - [Disabled] The error could not be interpreted and is unlikely to be recovered from during a retry.
+        // .unknown,
+
+        // [Resource] A properly formed URL couldn’t be handled by the framework.
+        //   - [Disabled] The URL is unlikely to change during a retry.
+        // .unsupportedURL,
+
+        // [Client] Authentication is required to access a resource.
+        //   - [Disabled] The user authentication is unlikely to be provided by retrying.
+        // .userAuthenticationRequired,
+
+        // [Client] An asynchronous request for authentication has been canceled by the user.
+        //   - [Disabled] The user cancelled authentication and explicitly took action to not retry.
+        // .userCancelledAuthentication,
+
+        // [Resource] A server reported that a URL has a non-zero content length, but terminated the network connection
+        // gracefully without sending any data.
+        //   - [Disabled] The server is unlikely to provide data during the retry window.
+        // .zeroByteResource,
+    ]
+
+    /// The total number of times the request is allowed to be retried.
+    public let retryLimit: UInt
+
+    /// The base of the exponential backoff policy (should always be greater than or equal to 2).
+    public let exponentialBackoffBase: UInt
+
+    /// The scale of the exponential backoff.
+    public let exponentialBackoffScale: Double
+
+    /// The HTTP methods that are allowed to be retried.
+    public let retryableHTTPMethods: Set<HTTPMethod>
+
+    /// The HTTP status codes that are automatically retried by the policy.
+    public let retryableHTTPStatusCodes: Set<Int>
+
+    /// The URL error codes that are automatically retried by the policy.
+    public let retryableURLErrorCodes: Set<URLError.Code>
+
+    /// Creates an `ExponentialBackoffRetryPolicy` from the specified parameters.
+    ///
+    /// - Parameters:
+    ///   - retryLimit:               The total number of times the request is allowed to be retried. `2` by default.
+    ///   - exponentialBackoffBase:   The base of the exponential backoff policy. `2` by default.
+    ///   - exponentialBackoffScale:  The scale of the exponential backoff. `0.5` by default.
+    ///   - retryableHTTPMethods:     The HTTP methods that are allowed to be retried.
+    ///                               `RetryPolicy.defaultRetryableHTTPMethods` by default.
+    ///   - retryableHTTPStatusCodes: The HTTP status codes that are automatically retried by the policy.
+    ///                               `RetryPolicy.defaultRetryableHTTPStatusCodes` by default.
+    ///   - retryableURLErrorCodes:   The URL error codes that are automatically retried by the policy.
+    ///                               `RetryPolicy.defaultRetryableURLErrorCodes` by default.
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods,
+                retryableHTTPStatusCodes: Set<Int> = RetryPolicy.defaultRetryableHTTPStatusCodes,
+                retryableURLErrorCodes: Set<URLError.Code> = RetryPolicy.defaultRetryableURLErrorCodes) {
+        precondition(exponentialBackoffBase >= 2, "The `exponentialBackoffBase` must be a minimum of 2.")
+
+        self.retryLimit = retryLimit
+        self.exponentialBackoffBase = exponentialBackoffBase
+        self.exponentialBackoffScale = exponentialBackoffScale
+        self.retryableHTTPMethods = retryableHTTPMethods
+        self.retryableHTTPStatusCodes = retryableHTTPStatusCodes
+        self.retryableURLErrorCodes = retryableURLErrorCodes
+    }
+
+    open func retry(_ request: Request,
+                    for session: Session,
+                    dueTo error: Error,
+                    completion: @escaping (RetryResult) -> Void) {
+        if
+            request.retryCount < retryLimit,
+            let httpMethod = request.request?.method,
+            retryableHTTPMethods.contains(httpMethod),
+            shouldRetry(response: request.response, error: error) {
+            let timeDelay = pow(Double(exponentialBackoffBase), Double(request.retryCount)) * exponentialBackoffScale
+            completion(.retryWithDelay(timeDelay))
+        } else {
+            completion(.doNotRetry)
+        }
+    }
+
+    private func shouldRetry(response: HTTPURLResponse?, error: Error) -> Bool {
+        if let statusCode = response?.statusCode, retryableHTTPStatusCodes.contains(statusCode) {
+            return true
+        } else {
+            let errorCode = (error as? URLError)?.code
+            let afErrorCode = (error.asAFError?.underlyingError as? URLError)?.code
+            if let code = errorCode ?? afErrorCode, retryableURLErrorCodes.contains(code) {
+                return true
+            } else {
+                return false
+            }
+        }
+    }
+}
+
+// MARK: -
+
+/// A retry policy that automatically retries idempotent requests for network connection lost errors. For more
+/// information about retrying network connection lost errors, please refer to Apple's
+/// [technical document](https://developer.apple.com/library/content/qa/qa1941/_index.html).
+open class ConnectionLostRetryPolicy: RetryPolicy {
+    /// Creates a `ConnectionLostRetryPolicy` instance from the specified parameters.
+    ///
+    /// - Parameters:
+    ///   - retryLimit:              The total number of times the request is allowed to be retried.
+    ///                              `RetryPolicy.defaultRetryLimit` by default.
+    ///   - exponentialBackoffBase:  The base of the exponential backoff policy.
+    ///                              `RetryPolicy.defaultExponentialBackoffBase` by default.
+    ///   - exponentialBackoffScale: The scale of the exponential backoff.
+    ///                              `RetryPolicy.defaultExponentialBackoffScale` by default.
+    ///   - retryableHTTPMethods:    The idempotent http methods to retry.
+    ///                              `RetryPolicy.defaultRetryableHTTPMethods` by default.
+    public init(retryLimit: UInt = RetryPolicy.defaultRetryLimit,
+                exponentialBackoffBase: UInt = RetryPolicy.defaultExponentialBackoffBase,
+                exponentialBackoffScale: Double = RetryPolicy.defaultExponentialBackoffScale,
+                retryableHTTPMethods: Set<HTTPMethod> = RetryPolicy.defaultRetryableHTTPMethods) {
+        super.init(retryLimit: retryLimit,
+                   exponentialBackoffBase: exponentialBackoffBase,
+                   exponentialBackoffScale: exponentialBackoffScale,
+                   retryableHTTPMethods: retryableHTTPMethods,
+                   retryableHTTPStatusCodes: [],
+                   retryableURLErrorCodes: [.networkConnectionLost])
+    }
+}

+ 606 - 0
Pods/Alamofire/Source/ServerTrustEvaluation.swift

@@ -0,0 +1,606 @@
+//
+//  ServerTrustPolicy.swift
+//
+//  Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Responsible for managing the mapping of `ServerTrustEvaluating` values to given hosts.
+open class ServerTrustManager {
+    /// Determines whether all hosts for this `ServerTrustManager` must be evaluated. `true` by default.
+    public let allHostsMustBeEvaluated: Bool
+
+    /// The dictionary of policies mapped to a particular host.
+    public let evaluators: [String: ServerTrustEvaluating]
+
+    /// Initializes the `ServerTrustManager` instance with the given evaluators.
+    ///
+    /// Since different servers and web services can have different leaf certificates, intermediate and even root
+    /// certificates, it is important to have the flexibility to specify evaluation policies on a per host basis. This
+    /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key
+    /// pinning for host3 and disabling evaluation for host4.
+    ///
+    /// - Parameters:
+    ///   - allHostsMustBeEvaluated: The value determining whether all hosts for this instance must be evaluated. `true`
+    ///                              by default.
+    ///   - evaluators:              A dictionary of evaluators mapped to hosts.
+    public init(allHostsMustBeEvaluated: Bool = true, evaluators: [String: ServerTrustEvaluating]) {
+        self.allHostsMustBeEvaluated = allHostsMustBeEvaluated
+        self.evaluators = evaluators
+    }
+
+    /// Returns the `ServerTrustEvaluating` value for the given host, if one is set.
+    ///
+    /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
+    /// this method and implement more complex mapping implementations such as wildcards.
+    ///
+    /// - Parameter host: The host to use when searching for a matching policy.
+    ///
+    /// - Returns:        The `ServerTrustEvaluating` value for the given host if found, `nil` otherwise.
+    /// - Throws:         `AFError.serverTrustEvaluationFailed` if `allHostsMustBeEvaluated` is `true` and no matching
+    ///                   evaluators are found.
+    open func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
+        guard let evaluator = evaluators[host] else {
+            if allHostsMustBeEvaluated {
+                throw AFError.serverTrustEvaluationFailed(reason: .noRequiredEvaluator(host: host))
+            }
+
+            return nil
+        }
+
+        return evaluator
+    }
+}
+
+/// A protocol describing the API used to evaluate server trusts.
+public protocol ServerTrustEvaluating {
+    #if os(Linux)
+    // Implement this once Linux has API for evaluating server trusts.
+    #else
+    /// Evaluates the given `SecTrust` value for the given `host`.
+    ///
+    /// - Parameters:
+    ///   - trust: The `SecTrust` value to evaluate.
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
+    ///
+    /// - Returns: A `Bool` indicating whether the evaluator considers the `SecTrust` value valid for `host`.
+    func evaluate(_ trust: SecTrust, forHost host: String) throws
+    #endif
+}
+
+// MARK: - Server Trust Evaluators
+
+/// An evaluator which uses the default server trust evaluation while allowing you to control whether to validate the
+/// host provided by the challenge. Applications are encouraged to always validate the host in production environments
+/// to guarantee the validity of the server's certificate chain.
+public final class DefaultTrustEvaluator: ServerTrustEvaluating {
+    private let validateHost: Bool
+
+    /// Creates a `DefaultTrustEvaluator`.
+    ///
+    /// - Parameter validateHost: Determines whether or not the evaluator should validate the host. `true` by default.
+    public init(validateHost: Bool = true) {
+        self.validateHost = validateHost
+    }
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        if validateHost {
+            try trust.af.performValidation(forHost: host)
+        }
+
+        try trust.af.performDefaultValidation(forHost: host)
+    }
+}
+
+/// An evaluator which Uses the default and revoked server trust evaluations allowing you to control whether to validate
+/// the host provided by the challenge as well as specify the revocation flags for testing for revoked certificates.
+/// Apple platforms did not start testing for revoked certificates automatically until iOS 10.1, macOS 10.12 and tvOS
+/// 10.1 which is demonstrated in our TLS tests. Applications are encouraged to always validate the host in production
+/// environments to guarantee the validity of the server's certificate chain.
+public final class RevocationTrustEvaluator: ServerTrustEvaluating {
+    /// Represents the options to be use when evaluating the status of a certificate.
+    /// Only Revocation Policy Constants are valid, and can be found in [Apple's documentation](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/policies/1563600-revocation_policy_constants).
+    public struct Options: OptionSet {
+        /// Perform revocation checking using the CRL (Certification Revocation List) method.
+        public static let crl = Options(rawValue: kSecRevocationCRLMethod)
+        /// Consult only locally cached replies; do not use network access.
+        public static let networkAccessDisabled = Options(rawValue: kSecRevocationNetworkAccessDisabled)
+        /// Perform revocation checking using OCSP (Online Certificate Status Protocol).
+        public static let ocsp = Options(rawValue: kSecRevocationOCSPMethod)
+        /// Prefer CRL revocation checking over OCSP; by default, OCSP is preferred.
+        public static let preferCRL = Options(rawValue: kSecRevocationPreferCRL)
+        /// Require a positive response to pass the policy. If the flag is not set, revocation checking is done on a
+        /// "best attempt" basis, where failure to reach the server is not considered fatal.
+        public static let requirePositiveResponse = Options(rawValue: kSecRevocationRequirePositiveResponse)
+        /// Perform either OCSP or CRL checking. The checking is performed according to the method(s) specified in the
+        /// certificate and the value of `preferCRL`.
+        public static let any = Options(rawValue: kSecRevocationUseAnyAvailableMethod)
+
+        /// The raw value of the option.
+        public let rawValue: CFOptionFlags
+
+        /// Creates an `Options` value with the given `CFOptionFlags`.
+        ///
+        /// - Parameter rawValue: The `CFOptionFlags` value to initialize with.
+        public init(rawValue: CFOptionFlags) {
+            self.rawValue = rawValue
+        }
+    }
+
+    private let performDefaultValidation: Bool
+    private let validateHost: Bool
+    private let options: Options
+
+    /// Creates a `RevocationTrustEvaluator`.
+    ///
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
+    ///
+    /// - Parameters:
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
+    ///                                   evaluating the pinned certificates. `true` by default.
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
+    ///                                   `false`. `true` by default.
+    ///   - options:                      The `Options` to use to check the revocation status of the certificate. `.any`
+    ///                                   by default.
+    public init(performDefaultValidation: Bool = true, validateHost: Bool = true, options: Options = .any) {
+        self.performDefaultValidation = performDefaultValidation
+        self.validateHost = validateHost
+        self.options = options
+    }
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        if performDefaultValidation {
+            try trust.af.performDefaultValidation(forHost: host)
+        }
+
+        if validateHost {
+            try trust.af.performValidation(forHost: host)
+        }
+
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
+            try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
+        } else {
+            try trust.af.validate(policy: SecPolicy.af.revocation(options: options)) { status, result in
+                AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
+            }
+        }
+    }
+}
+
+/// Uses the pinned certificates to validate the server trust. The server trust is considered valid if one of the pinned
+/// certificates match one of the server certificates. By validating both the certificate chain and host, certificate
+/// pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
+/// environments.
+public final class PinnedCertificatesTrustEvaluator: ServerTrustEvaluating {
+    private let certificates: [SecCertificate]
+    private let acceptSelfSignedCertificates: Bool
+    private let performDefaultValidation: Bool
+    private let validateHost: Bool
+
+    /// Creates a `PinnedCertificatesTrustEvaluator`.
+    ///
+    /// - Parameters:
+    ///   - certificates:                 The certificates to use to evaluate the trust. All `cer`, `crt`, and `der`
+    ///                                   certificates in `Bundle.main` by default.
+    ///   - acceptSelfSignedCertificates: Adds the provided certificates as anchors for the trust evaluation, allowing
+    ///                                   self-signed certificates to pass. `false` by default. THIS SETTING SHOULD BE
+    ///                                   FALSE IN PRODUCTION!
+    ///   - performDefaultValidation:     Determines whether default validation should be performed in addition to
+    ///                                   evaluating the pinned certificates. `true` by default.
+    ///   - validateHost:                 Determines whether or not the evaluator should validate the host, in addition
+    ///                                   to performing the default evaluation, even if `performDefaultValidation` is
+    ///                                   `false`. `true` by default.
+    public init(certificates: [SecCertificate] = Bundle.main.af.certificates,
+                acceptSelfSignedCertificates: Bool = false,
+                performDefaultValidation: Bool = true,
+                validateHost: Bool = true) {
+        self.certificates = certificates
+        self.acceptSelfSignedCertificates = acceptSelfSignedCertificates
+        self.performDefaultValidation = performDefaultValidation
+        self.validateHost = validateHost
+    }
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        guard !certificates.isEmpty else {
+            throw AFError.serverTrustEvaluationFailed(reason: .noCertificatesFound)
+        }
+
+        if acceptSelfSignedCertificates {
+            try trust.af.setAnchorCertificates(certificates)
+        }
+
+        if performDefaultValidation {
+            try trust.af.performDefaultValidation(forHost: host)
+        }
+
+        if validateHost {
+            try trust.af.performValidation(forHost: host)
+        }
+
+        let serverCertificatesData = Set(trust.af.certificateData)
+        let pinnedCertificatesData = Set(certificates.af.data)
+        let pinnedCertificatesInServerData = !serverCertificatesData.isDisjoint(with: pinnedCertificatesData)
+        if !pinnedCertificatesInServerData {
+            throw AFError.serverTrustEvaluationFailed(reason: .certificatePinningFailed(host: host,
+                                                                                        trust: trust,
+                                                                                        pinnedCertificates: certificates,
+                                                                                        serverCertificates: trust.af.certificates))
+        }
+    }
+}
+
+/// Uses the pinned public keys to validate the server trust. The server trust is considered valid if one of the pinned
+/// public keys match one of the server certificate public keys. By validating both the certificate chain and host,
+/// public key pinning provides a very secure form of server trust validation mitigating most, if not all, MITM attacks.
+/// Applications are encouraged to always validate the host and require a valid certificate chain in production
+/// environments.
+public final class PublicKeysTrustEvaluator: ServerTrustEvaluating {
+    private let keys: [SecKey]
+    private let performDefaultValidation: Bool
+    private let validateHost: Bool
+
+    /// Creates a `PublicKeysTrustEvaluator`.
+    ///
+    /// - Note: Default and host validation will fail when using this evaluator with self-signed certificates. Use
+    ///         `PinnedCertificatesTrustEvaluator` if you need to use self-signed certificates.
+    ///
+    /// - Parameters:
+    ///   - keys:                     The `SecKey`s to use to validate public keys. Defaults to the public keys of all
+    ///                               certificates included in the main bundle.
+    ///   - performDefaultValidation: Determines whether default validation should be performed in addition to
+    ///                               evaluating the pinned certificates. `true` by default.
+    ///   - validateHost:             Determines whether or not the evaluator should validate the host, in addition to
+    ///                               performing the default evaluation, even if `performDefaultValidation` is `false`.
+    ///                               `true` by default.
+    public init(keys: [SecKey] = Bundle.main.af.publicKeys,
+                performDefaultValidation: Bool = true,
+                validateHost: Bool = true) {
+        self.keys = keys
+        self.performDefaultValidation = performDefaultValidation
+        self.validateHost = validateHost
+    }
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        guard !keys.isEmpty else {
+            throw AFError.serverTrustEvaluationFailed(reason: .noPublicKeysFound)
+        }
+
+        if performDefaultValidation {
+            try trust.af.performDefaultValidation(forHost: host)
+        }
+
+        if validateHost {
+            try trust.af.performValidation(forHost: host)
+        }
+
+        let pinnedKeysInServerKeys: Bool = {
+            for serverPublicKey in trust.af.publicKeys {
+                for pinnedPublicKey in keys {
+                    if serverPublicKey == pinnedPublicKey {
+                        return true
+                    }
+                }
+            }
+            return false
+        }()
+
+        if !pinnedKeysInServerKeys {
+            throw AFError.serverTrustEvaluationFailed(reason: .publicKeyPinningFailed(host: host,
+                                                                                      trust: trust,
+                                                                                      pinnedKeys: keys,
+                                                                                      serverKeys: trust.af.publicKeys))
+        }
+    }
+}
+
+/// Uses the provided evaluators to validate the server trust. The trust is only considered valid if all of the
+/// evaluators consider it valid.
+public final class CompositeTrustEvaluator: ServerTrustEvaluating {
+    private let evaluators: [ServerTrustEvaluating]
+
+    /// Creates a `CompositeTrustEvaluator`.
+    ///
+    /// - Parameter evaluators: The `ServerTrustEvaluating` values used to evaluate the server trust.
+    public init(evaluators: [ServerTrustEvaluating]) {
+        self.evaluators = evaluators
+    }
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        try evaluators.evaluate(trust, forHost: host)
+    }
+}
+
+/// Disables all evaluation which in turn will always consider any server trust as valid.
+///
+/// **THIS EVALUATOR SHOULD NEVER BE USED IN PRODUCTION!**
+public final class DisabledEvaluator: ServerTrustEvaluating {
+    /// Creates an instance.
+    public init() {}
+
+    public func evaluate(_ trust: SecTrust, forHost host: String) throws {}
+}
+
+// MARK: - Extensions
+
+public extension Array where Element == ServerTrustEvaluating {
+    #if os(Linux)
+    // Add this same convenience method for Linux.
+    #else
+    /// Evaluates the given `SecTrust` value for the given `host`.
+    ///
+    /// - Parameters:
+    ///   - trust: The `SecTrust` value to evaluate.
+    ///   - host:  The host for which to evaluate the `SecTrust` value.
+    ///
+    /// - Returns: Whether or not the evaluator considers the `SecTrust` value valid for `host`.
+    func evaluate(_ trust: SecTrust, forHost host: String) throws {
+        for evaluator in self {
+            try evaluator.evaluate(trust, forHost: host)
+        }
+    }
+    #endif
+}
+
+extension Bundle: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType: Bundle {
+    /// Returns all valid `cer`, `crt`, and `der` certificates in the bundle.
+    var certificates: [SecCertificate] {
+        return paths(forResourcesOfTypes: [".cer", ".CER", ".crt", ".CRT", ".der", ".DER"]).compactMap { path in
+            guard
+                let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
+                let certificate = SecCertificateCreateWithData(nil, certificateData) else { return nil }
+
+            return certificate
+        }
+    }
+
+    /// Returns all public keys for the valid certificates in the bundle.
+    var publicKeys: [SecKey] {
+        return certificates.af.publicKeys
+    }
+
+    /// Returns all pathnames for the resources identified by the provided file extensions.
+    ///
+    /// - Parameter types: The filename extensions locate.
+    ///
+    /// - Returns:         All pathnames for the given filename extensions.
+    func paths(forResourcesOfTypes types: [String]) -> [String] {
+        return Array(Set(types.flatMap { type.paths(forResourcesOfType: $0, inDirectory: nil) }))
+    }
+}
+
+extension SecTrust: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == SecTrust {
+    /// Evaluates `self` after applying the `SecPolicy` value provided.
+    ///
+    /// - Parameter policy: The `SecPolicy` to apply to `self` before evaluation.
+    ///
+    /// - Throws:           Any `Error` from applying the `SecPolicy` or from evaluation.
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
+    func evaluate(afterApplying policy: SecPolicy) throws {
+        try apply(policy: policy).af.evaluate()
+    }
+
+    /// Attempts to validate `self` using the `SecPolicy` provided and transforming any error produced using the closure passed.
+    ///
+    /// - Parameters:
+    ///   - policy:        The `SecPolicy` used to evaluate `self`.
+    ///   - errorProducer: The closure used transform the failed `OSStatus` and `SecTrustResultType`.
+    /// - Throws:          Any `Error` from applying the `policy`, or the result of `errorProducer` if validation fails.
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate(afterApplying:)")
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate(afterApplying:)")
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate(afterApplying:)")
+    func validate(policy: SecPolicy, errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
+        try apply(policy: policy).af.validate(errorProducer: errorProducer)
+    }
+
+    /// Applies a `SecPolicy` to `self`, throwing if it fails.
+    ///
+    /// - Parameter policy: The `SecPolicy`.
+    ///
+    /// - Returns: `self`, with the policy applied.
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.policyApplicationFailed` reason.
+    func apply(policy: SecPolicy) throws -> SecTrust {
+        let status = SecTrustSetPolicies(type, policy)
+
+        guard status.af.isSuccess else {
+            throw AFError.serverTrustEvaluationFailed(reason: .policyApplicationFailed(trust: type,
+                                                                                       policy: policy,
+                                                                                       status: status))
+        }
+
+        return type
+    }
+
+    /// Evaluate `self`, throwing an `Error` if evaluation fails.
+    ///
+    /// - Throws: `AFError.serverTrustEvaluationFailed` with reason `.trustValidationFailed` and associated error from
+    ///           the underlying evaluation.
+    @available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *)
+    func evaluate() throws {
+        var error: CFError?
+        let evaluationSucceeded = SecTrustEvaluateWithError(type, &error)
+
+        if !evaluationSucceeded {
+            throw AFError.serverTrustEvaluationFailed(reason: .trustEvaluationFailed(error: error))
+        }
+    }
+
+    /// Validate `self`, passing any failure values through `errorProducer`.
+    ///
+    /// - Parameter errorProducer: The closure used to transform the failed `OSStatus` and `SecTrustResultType` into an
+    ///                            `Error`.
+    /// - Throws:                  The `Error` produced by the `errorProducer` closure.
+    @available(iOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
+    @available(macOS, introduced: 10.12, deprecated: 10.14, renamed: "evaluate()")
+    @available(tvOS, introduced: 10, deprecated: 12, renamed: "evaluate()")
+    @available(watchOS, introduced: 3, deprecated: 5, renamed: "evaluate()")
+    func validate(errorProducer: (_ status: OSStatus, _ result: SecTrustResultType) -> Error) throws {
+        var result = SecTrustResultType.invalid
+        let status = SecTrustEvaluate(type, &result)
+
+        guard status.af.isSuccess && result.af.isSuccess else {
+            throw errorProducer(status, result)
+        }
+    }
+
+    /// Sets a custom certificate chain on `self`, allowing full validation of a self-signed certificate and its chain.
+    ///
+    /// - Parameter certificates: The `SecCertificate`s to add to the chain.
+    /// - Throws:                 Any error produced when applying the new certificate chain.
+    func setAnchorCertificates(_ certificates: [SecCertificate]) throws {
+        // Add additional anchor certificates.
+        let status = SecTrustSetAnchorCertificates(type, certificates as CFArray)
+        guard status.af.isSuccess else {
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: status,
+                                                                                               certificates: certificates))
+        }
+
+        // Reenable system anchor certificates.
+        let systemStatus = SecTrustSetAnchorCertificatesOnly(type, true)
+        guard systemStatus.af.isSuccess else {
+            throw AFError.serverTrustEvaluationFailed(reason: .settingAnchorCertificatesFailed(status: systemStatus,
+                                                                                               certificates: certificates))
+        }
+    }
+
+    /// The public keys contained in `self`.
+    var publicKeys: [SecKey] {
+        return certificates.af.publicKeys
+    }
+
+    /// The `SecCertificate`s contained i `self`.
+    var certificates: [SecCertificate] {
+        return (0..<SecTrustGetCertificateCount(type)).compactMap { index in
+            SecTrustGetCertificateAtIndex(type, index)
+        }
+    }
+
+    /// The `Data` values for all certificates contained in `self`.
+    var certificateData: [Data] {
+        return certificates.af.data
+    }
+
+    /// Validates `self` after applying `SecPolicy.af.default`. This evaluation does not validate the hostname.
+    ///
+    /// - Parameter host: The hostname, used only in the error output if validation fails.
+    /// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
+    func performDefaultValidation(forHost host: String) throws {
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
+            try evaluate(afterApplying: SecPolicy.af.default)
+        } else {
+            try validate(policy: SecPolicy.af.default) { status, result in
+                AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
+            }
+        }
+    }
+
+    /// Validates `self` after applying `SecPolicy.af.hostname(host)`, which performs the default validation as well as
+    /// hostname validation.
+    ///
+    /// - Parameter host: The hostname to use in the validation.
+    /// - Throws:         An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
+    func performValidation(forHost host: String) throws {
+        if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
+            try evaluate(afterApplying: SecPolicy.af.hostname(host))
+        } else {
+            try validate(policy: SecPolicy.af.hostname(host)) { status, result in
+                AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
+            }
+        }
+    }
+}
+
+extension SecPolicy: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == SecPolicy {
+    /// Creates a `SecPolicy` instance which will validate server certificates but not require a host name match.
+    static let `default` = SecPolicyCreateSSL(true, nil)
+
+    /// Creates a `SecPolicy` instance which will validate server certificates and much match the provided hostname.
+    ///
+    /// - Parameter hostname: The hostname to validate against.
+    ///
+    /// - Returns:            The `SecPolicy`.
+    static func hostname(_ hostname: String) -> SecPolicy {
+        return SecPolicyCreateSSL(true, hostname as CFString)
+    }
+
+    /// Creates a `SecPolicy` which checks the revocation of certificates.
+    ///
+    /// - Parameter options: The `RevocationTrustEvaluator.Options` for evaluation.
+    ///
+    /// - Returns:           The `SecPolicy`.
+    /// - Throws:            An `AFError.serverTrustEvaluationFailed` error with reason `.revocationPolicyCreationFailed`
+    ///                      if the policy cannot be created.
+    static func revocation(options: RevocationTrustEvaluator.Options) throws -> SecPolicy {
+        guard let policy = SecPolicyCreateRevocation(options.rawValue) else {
+            throw AFError.serverTrustEvaluationFailed(reason: .revocationPolicyCreationFailed)
+        }
+
+        return policy
+    }
+}
+
+extension Array: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == [SecCertificate] {
+    /// All `Data` values for the contained `SecCertificate`s.
+    var data: [Data] {
+        return type.map { SecCertificateCopyData($0) as Data }
+    }
+
+    /// All public `SecKey` values for the contained `SecCertificate`s.
+    var publicKeys: [SecKey] {
+        return type.compactMap { $0.af.publicKey }
+    }
+}
+
+extension SecCertificate: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == SecCertificate {
+    /// The public key for `self`, if it can be extracted.
+    var publicKey: SecKey? {
+        let policy = SecPolicyCreateBasicX509()
+        var trust: SecTrust?
+        let trustCreationStatus = SecTrustCreateWithCertificates(type, policy, &trust)
+
+        guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
+
+        return SecTrustCopyPublicKey(createdTrust)
+    }
+}
+
+extension OSStatus: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == OSStatus {
+    /// Returns whether `self` is `errSecSuccess`.
+    var isSuccess: Bool { return type == errSecSuccess }
+}
+
+extension SecTrustResultType: AlamofireExtended {}
+public extension AlamofireExtension where ExtendedType == SecTrustResultType {
+    /// Returns whether `self is `.unspecified` or `.proceed`.
+    var isSuccess: Bool {
+        return (type == .unspecified || type == .proceed)
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1067 - 0
Pods/Alamofire/Source/Session.swift


+ 328 - 0
Pods/Alamofire/Source/SessionDelegate.swift

@@ -0,0 +1,328 @@
+//
+//  SessionDelegate.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Class which implements the various `URLSessionDelegate` methods to connect various Alamofire features.
+open class SessionDelegate: NSObject {
+    private let fileManager: FileManager
+
+    weak var stateProvider: SessionStateProvider?
+    var eventMonitor: EventMonitor?
+
+    /// Creates an instance from the given `FileManager`.
+    ///
+    /// - Parameter fileManager: `FileManager` to use for underlying file management, such as moving downloaded files.
+    ///                          `.default` by default.
+    public init(fileManager: FileManager = .default) {
+        self.fileManager = fileManager
+    }
+
+    /// Internal method to find and cast requests while maintaining some integrity checking.
+    ///
+    /// - Parameters:
+    ///   - task: The `URLSessionTask` for which to find the associated `Request`.
+    ///   - type: The `Request` subclass type to cast any `Request` associate with `task`.
+    func request<R: Request>(for task: URLSessionTask, as type: R.Type) -> R? {
+        guard let provider = stateProvider else {
+            assertionFailure("StateProvider is nil.")
+            return nil
+        }
+
+        guard let request = provider.request(for: task) as? R else {
+            fatalError("Returned Request is not of expected type: \(R.self).")
+        }
+
+        return request
+    }
+}
+
+/// Type which provides various `Session` state values.
+protocol SessionStateProvider: AnyObject {
+    var serverTrustManager: ServerTrustManager? { get }
+    var redirectHandler: RedirectHandler? { get }
+    var cachedResponseHandler: CachedResponseHandler? { get }
+
+    func request(for task: URLSessionTask) -> Request?
+    func didGatherMetricsForTask(_ task: URLSessionTask)
+    func didCompleteTask(_ task: URLSessionTask, completion: @escaping () -> Void)
+    func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential?
+    func cancelRequestsForSessionInvalidation(with error: Error?)
+}
+
+// MARK: URLSessionDelegate
+
+extension SessionDelegate: URLSessionDelegate {
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
+        eventMonitor?.urlSession(session, didBecomeInvalidWithError: error)
+
+        stateProvider?.cancelRequestsForSessionInvalidation(with: error)
+    }
+}
+
+// MARK: URLSessionTaskDelegate
+
+extension SessionDelegate: URLSessionTaskDelegate {
+    /// Result of a `URLAuthenticationChallenge` evaluation.
+    typealias ChallengeEvaluation = (disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?, error: AFError?)
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         didReceive challenge: URLAuthenticationChallenge,
+                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
+        eventMonitor?.urlSession(session, task: task, didReceive: challenge)
+
+        let evaluation: ChallengeEvaluation
+        switch challenge.protectionSpace.authenticationMethod {
+        case NSURLAuthenticationMethodServerTrust:
+            evaluation = attemptServerTrustAuthentication(with: challenge)
+        case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM,
+             NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate:
+            evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
+        default:
+            evaluation = (.performDefaultHandling, nil, nil)
+        }
+
+        if let error = evaluation.error {
+            stateProvider?.request(for: task)?.didFailTask(task, earlyWithError: error)
+        }
+
+        completionHandler(evaluation.disposition, evaluation.credential)
+    }
+
+    /// Evaluates the server trust `URLAuthenticationChallenge` received.
+    ///
+    /// - Parameter challenge: The `URLAuthenticationChallenge`.
+    ///
+    /// - Returns:             The `ChallengeEvaluation`.
+    func attemptServerTrustAuthentication(with challenge: URLAuthenticationChallenge) -> ChallengeEvaluation {
+        let host = challenge.protectionSpace.host
+
+        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
+            let trust = challenge.protectionSpace.serverTrust
+        else {
+            return (.performDefaultHandling, nil, nil)
+        }
+
+        do {
+            guard let evaluator = try stateProvider?.serverTrustManager?.serverTrustEvaluator(forHost: host) else {
+                return (.performDefaultHandling, nil, nil)
+            }
+
+            try evaluator.evaluate(trust, forHost: host)
+
+            return (.useCredential, URLCredential(trust: trust), nil)
+        } catch {
+            return (.cancelAuthenticationChallenge, nil, error.asAFError(or: .serverTrustEvaluationFailed(reason: .customEvaluationFailed(error: error))))
+        }
+    }
+
+    /// Evaluates the credential-based authentication `URLAuthenticationChallenge` received for `task`.
+    ///
+    /// - Parameters:
+    ///   - challenge: The `URLAuthenticationChallenge`.
+    ///   - task:      The `URLSessionTask` which received the challenge.
+    ///
+    /// - Returns:     The `ChallengeEvaluation`.
+    func attemptCredentialAuthentication(for challenge: URLAuthenticationChallenge,
+                                         belongingTo task: URLSessionTask) -> ChallengeEvaluation {
+        guard challenge.previousFailureCount == 0 else {
+            return (.rejectProtectionSpace, nil, nil)
+        }
+
+        guard let credential = stateProvider?.credential(for: task, in: challenge.protectionSpace) else {
+            return (.performDefaultHandling, nil, nil)
+        }
+
+        return (.useCredential, credential, nil)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         didSendBodyData bytesSent: Int64,
+                         totalBytesSent: Int64,
+                         totalBytesExpectedToSend: Int64) {
+        eventMonitor?.urlSession(session,
+                                 task: task,
+                                 didSendBodyData: bytesSent,
+                                 totalBytesSent: totalBytesSent,
+                                 totalBytesExpectedToSend: totalBytesExpectedToSend)
+
+        stateProvider?.request(for: task)?.updateUploadProgress(totalBytesSent: totalBytesSent,
+                                                                totalBytesExpectedToSend: totalBytesExpectedToSend)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
+        eventMonitor?.urlSession(session, taskNeedsNewBodyStream: task)
+
+        guard let request = request(for: task, as: UploadRequest.self) else {
+            assertionFailure("needNewBodyStream did not find UploadRequest.")
+            completionHandler(nil)
+            return
+        }
+
+        completionHandler(request.inputStream())
+    }
+
+    open func urlSession(_ session: URLSession,
+                         task: URLSessionTask,
+                         willPerformHTTPRedirection response: HTTPURLResponse,
+                         newRequest request: URLRequest,
+                         completionHandler: @escaping (URLRequest?) -> Void) {
+        eventMonitor?.urlSession(session, task: task, willPerformHTTPRedirection: response, newRequest: request)
+
+        if let redirectHandler = stateProvider?.request(for: task)?.redirectHandler ?? stateProvider?.redirectHandler {
+            redirectHandler.task(task, willBeRedirectedTo: request, for: response, completion: completionHandler)
+        } else {
+            completionHandler(request)
+        }
+    }
+
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
+        eventMonitor?.urlSession(session, task: task, didFinishCollecting: metrics)
+
+        stateProvider?.request(for: task)?.didGatherMetrics(metrics)
+
+        stateProvider?.didGatherMetricsForTask(task)
+    }
+
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        eventMonitor?.urlSession(session, task: task, didCompleteWithError: error)
+
+        let request = stateProvider?.request(for: task)
+
+        stateProvider?.didCompleteTask(task) {
+            request?.didCompleteTask(task, with: error.map { $0.asAFError(or: .sessionTaskFailed(error: $0)) })
+        }
+    }
+
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    open func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
+        eventMonitor?.urlSession(session, taskIsWaitingForConnectivity: task)
+    }
+}
+
+// MARK: URLSessionDataDelegate
+
+extension SessionDelegate: URLSessionDataDelegate {
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
+
+        guard let request = request(for: dataTask, as: DataRequest.self) else {
+            assertionFailure("dataTask did not find DataRequest.")
+            return
+        }
+
+        request.didReceive(data: data)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         dataTask: URLSessionDataTask,
+                         willCacheResponse proposedResponse: CachedURLResponse,
+                         completionHandler: @escaping (CachedURLResponse?) -> Void) {
+        eventMonitor?.urlSession(session, dataTask: dataTask, willCacheResponse: proposedResponse)
+
+        if let handler = stateProvider?.request(for: dataTask)?.cachedResponseHandler ?? stateProvider?.cachedResponseHandler {
+            handler.dataTask(dataTask, willCacheResponse: proposedResponse, completion: completionHandler)
+        } else {
+            completionHandler(proposedResponse)
+        }
+    }
+}
+
+// MARK: URLSessionDownloadDelegate
+
+extension SessionDelegate: URLSessionDownloadDelegate {
+    open func urlSession(_ session: URLSession,
+                         downloadTask: URLSessionDownloadTask,
+                         didResumeAtOffset fileOffset: Int64,
+                         expectedTotalBytes: Int64) {
+        eventMonitor?.urlSession(session,
+                                 downloadTask: downloadTask,
+                                 didResumeAtOffset: fileOffset,
+                                 expectedTotalBytes: expectedTotalBytes)
+        guard let downloadRequest = request(for: downloadTask, as: DownloadRequest.self) else {
+            assertionFailure("downloadTask did not find DownloadRequest.")
+            return
+        }
+
+        downloadRequest.updateDownloadProgress(bytesWritten: fileOffset,
+                                               totalBytesExpectedToWrite: expectedTotalBytes)
+    }
+
+    open func urlSession(_ session: URLSession,
+                         downloadTask: URLSessionDownloadTask,
+                         didWriteData bytesWritten: Int64,
+                         totalBytesWritten: Int64,
+                         totalBytesExpectedToWrite: Int64) {
+        eventMonitor?.urlSession(session,
+                                 downloadTask: downloadTask,
+                                 didWriteData: bytesWritten,
+                                 totalBytesWritten: totalBytesWritten,
+                                 totalBytesExpectedToWrite: totalBytesExpectedToWrite)
+        guard let downloadRequest = request(for: downloadTask, as: DownloadRequest.self) else {
+            assertionFailure("downloadTask did not find DownloadRequest.")
+            return
+        }
+
+        downloadRequest.updateDownloadProgress(bytesWritten: bytesWritten,
+                                               totalBytesExpectedToWrite: totalBytesExpectedToWrite)
+    }
+
+    open func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
+        eventMonitor?.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
+
+        guard let request = request(for: downloadTask, as: DownloadRequest.self) else {
+            assertionFailure("downloadTask did not find DownloadRequest.")
+            return
+        }
+
+        guard let response = request.response else {
+            fatalError("URLSessionDownloadTask finished downloading with no response.")
+        }
+
+        let (destination, options) = (request.destination)(location, response)
+
+        eventMonitor?.request(request, didCreateDestinationURL: destination)
+
+        do {
+            if options.contains(.removePreviousFile), fileManager.fileExists(atPath: destination.path) {
+                try fileManager.removeItem(at: destination)
+            }
+
+            if options.contains(.createIntermediateDirectories) {
+                let directory = destination.deletingLastPathComponent()
+                try fileManager.createDirectory(at: directory, withIntermediateDirectories: true)
+            }
+
+            try fileManager.moveItem(at: location, to: destination)
+
+            request.didFinishDownloading(using: downloadTask, with: .success(destination))
+        } catch {
+            request.didFinishDownloading(using: downloadTask, with: .failure(.downloadedFileMoveFailed(error: error, source: location, destination: destination)))
+        }
+    }
+}

+ 105 - 0
Pods/Alamofire/Source/URLConvertible+URLRequestConvertible.swift

@@ -0,0 +1,105 @@
+//
+//  URLConvertible+URLRequestConvertible.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Types adopting the `URLConvertible` protocol can be used to construct `URL`s, which can then be used to construct
+/// `URLRequests`.
+public protocol URLConvertible {
+    /// Returns a `URL` from the conforming instance or throws.
+    ///
+    /// - Returns: The `URL` created from the instance.
+    /// - Throws:  Any error thrown while creating the `URL`.
+    func asURL() throws -> URL
+}
+
+extension String: URLConvertible {
+    /// Returns a `URL` if `self` can be used to initialize a `URL` instance, otherwise throws.
+    ///
+    /// - Returns: The `URL` initialized with `self`.
+    /// - Throws:  An `AFError.invalidURL` instance.
+    public func asURL() throws -> URL {
+        guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
+
+        return url
+    }
+}
+
+extension URL: URLConvertible {
+    /// Returns `self`.
+    public func asURL() throws -> URL { return self }
+}
+
+extension URLComponents: URLConvertible {
+    /// Returns a `URL` if the `self`'s `url` is not nil, otherwise throws.
+    ///
+    /// - Returns: The `URL` from the `url` property.
+    /// - Throws:  An `AFError.invalidURL` instance.
+    public func asURL() throws -> URL {
+        guard let url = url else { throw AFError.invalidURL(url: self) }
+
+        return url
+    }
+}
+
+// MARK: -
+
+/// Types adopting the `URLRequestConvertible` protocol can be used to safely construct `URLRequest`s.
+public protocol URLRequestConvertible {
+    /// Returns a `URLRequest` or throws if an `Error` was encountered.
+    ///
+    /// - Returns: A `URLRequest`.
+    /// - Throws:  Any error thrown while constructing the `URLRequest`.
+    func asURLRequest() throws -> URLRequest
+}
+
+extension URLRequestConvertible {
+    /// The `URLRequest` returned by discarding any `Error` encountered.
+    public var urlRequest: URLRequest? { return try? asURLRequest() }
+}
+
+extension URLRequest: URLRequestConvertible {
+    /// Returns `self`.
+    public func asURLRequest() throws -> URLRequest { return self }
+}
+
+// MARK: -
+
+extension URLRequest {
+    /// Creates an instance with the specified `url`, `method`, and `headers`.
+    ///
+    /// - Parameters:
+    ///   - url:     The `URLConvertible` value.
+    ///   - method:  The `HTTPMethod`.
+    ///   - headers: The `HTTPHeaders`, `nil` by default.
+    /// - Throws:    Any error thrown while converting the `URLConvertible` to a `URL`.
+    public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
+        let url = try url.asURL()
+
+        self.init(url: url)
+
+        httpMethod = method.rawValue
+        allHTTPHeaderFields = headers?.dictionary
+    }
+}

+ 973 - 0
Pods/Alamofire/Source/URLEncodedFormEncoder.swift

@@ -0,0 +1,973 @@
+//
+//  URLEncodedFormEncoder.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// An object that encodes instances into URL-encoded query strings.
+///
+/// There is no published specification for how to encode collection types. By default, the convention of appending
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
+/// square brackets appended to array keys.
+///
+/// `BoolEncoding` can be used to configure how `Bool` values are encoded. The default behavior is to encode
+/// `true` as 1 and `false` as 0.
+///
+/// `DateEncoding` can be used to configure how `Date` values are encoded. By default, the `.deferredToDate`
+/// strategy is used, which formats dates from their structure.
+///
+/// `SpaceEncoding` can be used to configure how spaces are encoded. Modern encodings use percent replacement (`%20`),
+/// while older encodings may expect spaces to be replaced with `+`.
+///
+/// This type is largely based on Vapor's [`url-encoded-form`](https://github.com/vapor/url-encoded-form) project.
+public final class URLEncodedFormEncoder {
+    /// Encoding to use for `Array` values.
+    public enum ArrayEncoding {
+        /// An empty set of square brackets ("[]") are appended to the key for every value. This is the default encoding.
+        case brackets
+        /// No brackets are appended to the key and the key is encoded as is.
+        case noBrackets
+
+        /// Encodes the key according to the encoding.
+        ///
+        /// - Parameter key: The `key` to encode.
+        /// - Returns:       The encoded key.
+        func encode(_ key: String) -> String {
+            switch self {
+            case .brackets: return "\(key)[]"
+            case .noBrackets: return key
+            }
+        }
+    }
+
+    /// Encoding to use for `Bool` values.
+    public enum BoolEncoding {
+        /// Encodes `true` as `1`, `false` as `0`.
+        case numeric
+        /// Encodes `true` as "true", `false` as "false". This is the default encoding.
+        case literal
+
+        /// Encodes the given `Bool` as a `String`.
+        ///
+        /// - Parameter value: The `Bool` to encode.
+        ///
+        /// - Returns:         The encoded `String`.
+        func encode(_ value: Bool) -> String {
+            switch self {
+            case .numeric: return value ? "1" : "0"
+            case .literal: return value ? "true" : "false"
+            }
+        }
+    }
+
+    /// Encoding to use for `Data` values.
+    public enum DataEncoding {
+        /// Defers encoding to the `Data` type.
+        case deferredToData
+        /// Encodes `Data` as a Base64-encoded string. This is the default encoding.
+        case base64
+        /// Encode the `Data` as a custom value encoded by the given closure.
+        case custom((Data) throws -> String)
+
+        /// Encodes `Data` according to the encoding.
+        ///
+        /// - Parameter data: The `Data` to encode.
+        ///
+        /// - Returns:        The encoded `String`, or `nil` if the `Data` should be encoded according to its
+        ///                   `Encodable` implementation.
+        func encode(_ data: Data) throws -> String? {
+            switch self {
+            case .deferredToData: return nil
+            case .base64: return data.base64EncodedString()
+            case let .custom(encoding): return try encoding(data)
+            }
+        }
+    }
+
+    /// Encoding to use for `Date` values.
+    public enum DateEncoding {
+        /// ISO8601 and RFC3339 formatter.
+        private static let iso8601Formatter: ISO8601DateFormatter = {
+            let formatter = ISO8601DateFormatter()
+            formatter.formatOptions = .withInternetDateTime
+            return formatter
+        }()
+
+        /// Defers encoding to the `Date` type. This is the default encoding.
+        case deferredToDate
+        /// Encodes `Date`s as seconds since midnight UTC on January 1, 1970.
+        case secondsSince1970
+        /// Encodes `Date`s as milliseconds since midnight UTC on January 1, 1970.
+        case millisecondsSince1970
+        /// Encodes `Date`s according to the ISO8601 and RFC3339 standards.
+        case iso8601
+        /// Encodes `Date`s using the given `DateFormatter`.
+        case formatted(DateFormatter)
+        /// Encodes `Date`s using the given closure.
+        case custom((Date) throws -> String)
+
+        /// Encodes the date according to the encoding.
+        ///
+        /// - Parameter date: The `Date` to encode.
+        ///
+        /// - Returns:        The encoded `String`, or `nil` if the `Date` should be encoded according to its
+        ///                   `Encodable` implementation.
+        func encode(_ date: Date) throws -> String? {
+            switch self {
+            case .deferredToDate:
+                return nil
+            case .secondsSince1970:
+                return String(date.timeIntervalSince1970)
+            case .millisecondsSince1970:
+                return String(date.timeIntervalSince1970 * 1000.0)
+            case .iso8601:
+                return DateEncoding.iso8601Formatter.string(from: date)
+            case let .formatted(formatter):
+                return formatter.string(from: date)
+            case let .custom(closure):
+                return try closure(date)
+            }
+        }
+    }
+
+    /// Encoding to use for keys.
+    ///
+    /// This type is derived from [`JSONEncoder`'s `KeyEncodingStrategy`](https://github.com/apple/swift/blob/6aa313b8dd5f05135f7f878eccc1db6f9fbe34ff/stdlib/public/Darwin/Foundation/JSONEncoder.swift#L128)
+    /// and [`XMLEncoder`s `KeyEncodingStrategy`](https://github.com/MaxDesiatov/XMLCoder/blob/master/Sources/XMLCoder/Encoder/XMLEncoder.swift#L102).
+    public enum KeyEncoding {
+        /// Use the keys specified by each type. This is the default encoding.
+        case useDefaultKeys
+        /// Convert from "camelCaseKeys" to "snake_case_keys" before writing a key.
+        ///
+        /// Capital characters are determined by testing membership in
+        /// `CharacterSet.uppercaseLetters` and `CharacterSet.lowercaseLetters`
+        /// (Unicode General Categories Lu and Lt).
+        /// The conversion to lower case uses `Locale.system`, also known as
+        /// the ICU "root" locale. This means the result is consistent
+        /// regardless of the current user's locale and language preferences.
+        ///
+        /// Converting from camel case to snake case:
+        /// 1. Splits words at the boundary of lower-case to upper-case
+        /// 2. Inserts `_` between words
+        /// 3. Lowercases the entire string
+        /// 4. Preserves starting and ending `_`.
+        ///
+        /// For example, `oneTwoThree` becomes `one_two_three`. `_oneTwoThree_` becomes `_one_two_three_`.
+        ///
+        /// - Note: Using a key encoding strategy has a nominal performance cost, as each string key has to be converted.
+        case convertToSnakeCase
+        /// Same as convertToSnakeCase, but using `-` instead of `_`.
+        /// For example `oneTwoThree` becomes `one-two-three`.
+        case convertToKebabCase
+        /// Capitalize the first letter only.
+        /// For example `oneTwoThree` becomes  `OneTwoThree`.
+        case capitalized
+        /// Uppercase all letters.
+        /// For example `oneTwoThree` becomes  `ONETWOTHREE`.
+        case uppercased
+        /// Lowercase all letters.
+        /// For example `oneTwoThree` becomes  `onetwothree`.
+        case lowercased
+        /// A custom encoding using the provided closure.
+        case custom((String) -> String)
+
+        func encode(_ key: String) -> String {
+            switch self {
+            case .useDefaultKeys: return key
+            case .convertToSnakeCase: return convertToSnakeCase(key)
+            case .convertToKebabCase: return convertToKebabCase(key)
+            case .capitalized: return String(key.prefix(1).uppercased() + key.dropFirst())
+            case .uppercased: return key.uppercased()
+            case .lowercased: return key.lowercased()
+            case let .custom(encoding): return encoding(key)
+            }
+        }
+
+        private func convertToSnakeCase(_ key: String) -> String {
+            return convert(key, usingSeparator: "_")
+        }
+
+        private func convertToKebabCase(_ key: String) -> String {
+            return convert(key, usingSeparator: "-")
+        }
+
+        private func convert(_ key: String, usingSeparator separator: String) -> String {
+            guard !key.isEmpty else { return key }
+
+            var words: [Range<String.Index>] = []
+            // The general idea of this algorithm is to split words on
+            // transition from lower to upper case, then on transition of >1
+            // upper case characters to lowercase
+            //
+            // myProperty -> my_property
+            // myURLProperty -> my_url_property
+            //
+            // It is assumed, per Swift naming conventions, that the first character of the key is lowercase.
+            var wordStart = key.startIndex
+            var searchRange = key.index(after: wordStart)..<key.endIndex
+
+            // Find next uppercase character
+            while let upperCaseRange = key.rangeOfCharacter(from: CharacterSet.uppercaseLetters, options: [], range: searchRange) {
+                let untilUpperCase = wordStart..<upperCaseRange.lowerBound
+                words.append(untilUpperCase)
+
+                // Find next lowercase character
+                searchRange = upperCaseRange.lowerBound..<searchRange.upperBound
+                guard let lowerCaseRange = key.rangeOfCharacter(from: CharacterSet.lowercaseLetters, options: [], range: searchRange) else {
+                    // There are no more lower case letters. Just end here.
+                    wordStart = searchRange.lowerBound
+                    break
+                }
+
+                // Is the next lowercase letter more than 1 after the uppercase?
+                // If so, we encountered a group of uppercase letters that we
+                // should treat as its own word
+                let nextCharacterAfterCapital = key.index(after: upperCaseRange.lowerBound)
+                if lowerCaseRange.lowerBound == nextCharacterAfterCapital {
+                    // The next character after capital is a lower case character and therefore not a word boundary.
+                    // Continue searching for the next upper case for the boundary.
+                    wordStart = upperCaseRange.lowerBound
+                } else {
+                    // There was a range of >1 capital letters. Turn those into a word, stopping at the capital before the lower case character.
+                    let beforeLowerIndex = key.index(before: lowerCaseRange.lowerBound)
+                    words.append(upperCaseRange.lowerBound..<beforeLowerIndex)
+
+                    // Next word starts at the capital before the lowercase we just found
+                    wordStart = beforeLowerIndex
+                }
+                searchRange = lowerCaseRange.upperBound..<searchRange.upperBound
+            }
+            words.append(wordStart..<searchRange.upperBound)
+            let result = words.map { range in
+                key[range].lowercased()
+            }.joined(separator: separator)
+
+            return result
+        }
+    }
+
+    /// Encoding to use for spaces.
+    public enum SpaceEncoding {
+        /// Encodes spaces according to normal percent escaping rules (%20).
+        case percentEscaped
+        /// Encodes spaces as `+`,
+        case plusReplaced
+
+        /// Encodes the string according to the encoding.
+        ///
+        /// - Parameter string: The `String` to encode.
+        ///
+        /// - Returns:          The encoded `String`.
+        func encode(_ string: String) -> String {
+            switch self {
+            case .percentEscaped: return string.replacingOccurrences(of: " ", with: "%20")
+            case .plusReplaced: return string.replacingOccurrences(of: " ", with: "+")
+            }
+        }
+    }
+
+    /// `URLEncodedFormEncoder` error.
+    public enum Error: Swift.Error {
+        /// An invalid root object was created by the encoder. Only keyed values are valid.
+        case invalidRootObject(String)
+
+        var localizedDescription: String {
+            switch self {
+            case let .invalidRootObject(object):
+                return "URLEncodedFormEncoder requires keyed root object. Received \(object) instead."
+            }
+        }
+    }
+
+    /// Whether or not to sort the encoded key value pairs.
+    ///
+    /// - Note: This setting ensures a consistent ordering for all encodings of the same parameters. When set to `false`,
+    ///         encoded `Dictionary` values may have a different encoded order each time they're encoded due to
+    ///       ` Dictionary`'s random storage order, but `Encodable` types will maintain their encoded order.
+    public let alphabetizeKeyValuePairs: Bool
+    /// The `ArrayEncoding` to use.
+    public let arrayEncoding: ArrayEncoding
+    /// The `BoolEncoding` to use.
+    public let boolEncoding: BoolEncoding
+    /// THe `DataEncoding` to use.
+    public let dataEncoding: DataEncoding
+    /// The `DateEncoding` to use.
+    public let dateEncoding: DateEncoding
+    /// The `KeyEncoding` to use.
+    public let keyEncoding: KeyEncoding
+    /// The `SpaceEncoding` to use.
+    public let spaceEncoding: SpaceEncoding
+    /// The `CharacterSet` of allowed (non-escaped) characters.
+    public var allowedCharacters: CharacterSet
+
+    /// Creates an instance from the supplied parameters.
+    ///
+    /// - Parameters:
+    ///   - alphabetizeKeyValuePairs: Whether or not to sort the encoded key value pairs. `true` by default.
+    ///   - arrayEncoding:            The `ArrayEncoding` to use. `.brackets` by default.
+    ///   - boolEncoding:             The `BoolEncoding` to use. `.numeric` by default.
+    ///   - dataEncoding:             The `DataEncoding` to use. `.base64` by default.
+    ///   - dateEncoding:             The `DateEncoding` to use. `.deferredToDate` by default.
+    ///   - keyEncoding:              The `KeyEncoding` to use. `.useDefaultKeys` by default.
+    ///   - spaceEncoding:            The `SpaceEncoding` to use. `.percentEscaped` by default.
+    ///   - allowedCharacters:        The `CharacterSet` of allowed (non-escaped) characters. `.afURLQueryAllowed` by
+    ///                               default.
+    public init(alphabetizeKeyValuePairs: Bool = true,
+                arrayEncoding: ArrayEncoding = .brackets,
+                boolEncoding: BoolEncoding = .numeric,
+                dataEncoding: DataEncoding = .base64,
+                dateEncoding: DateEncoding = .deferredToDate,
+                keyEncoding: KeyEncoding = .useDefaultKeys,
+                spaceEncoding: SpaceEncoding = .percentEscaped,
+                allowedCharacters: CharacterSet = .afURLQueryAllowed) {
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
+        self.arrayEncoding = arrayEncoding
+        self.boolEncoding = boolEncoding
+        self.dataEncoding = dataEncoding
+        self.dateEncoding = dateEncoding
+        self.keyEncoding = keyEncoding
+        self.spaceEncoding = spaceEncoding
+        self.allowedCharacters = allowedCharacters
+    }
+
+    func encode(_ value: Encodable) throws -> URLEncodedFormComponent {
+        let context = URLEncodedFormContext(.object([]))
+        let encoder = _URLEncodedFormEncoder(context: context,
+                                             boolEncoding: boolEncoding,
+                                             dataEncoding: dataEncoding,
+                                             dateEncoding: dateEncoding)
+        try value.encode(to: encoder)
+
+        return context.component
+    }
+
+    /// Encodes the `value` as a URL form encoded `String`.
+    ///
+    /// - Parameter value: The `Encodable` value.`
+    ///
+    /// - Returns:         The encoded `String`.
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
+    public func encode(_ value: Encodable) throws -> String {
+        let component: URLEncodedFormComponent = try encode(value)
+
+        guard case let .object(object) = component else {
+            throw Error.invalidRootObject("\(component)")
+        }
+
+        let serializer = URLEncodedFormSerializer(alphabetizeKeyValuePairs: alphabetizeKeyValuePairs,
+                                                  arrayEncoding: arrayEncoding,
+                                                  keyEncoding: keyEncoding,
+                                                  spaceEncoding: spaceEncoding,
+                                                  allowedCharacters: allowedCharacters)
+        let query = serializer.serialize(object)
+
+        return query
+    }
+
+    /// Encodes the value as `Data`. This is performed by first creating an encoded `String` and then returning the
+    /// `.utf8` data.
+    ///
+    /// - Parameter value: The `Encodable` value.
+    ///
+    /// - Returns:         The encoded `Data`.
+    ///
+    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.
+    public func encode(_ value: Encodable) throws -> Data {
+        let string: String = try encode(value)
+
+        return Data(string.utf8)
+    }
+}
+
+final class _URLEncodedFormEncoder {
+    var codingPath: [CodingKey]
+    // Returns an empty dictionary, as this encoder doesn't support userInfo.
+    var userInfo: [CodingUserInfoKey: Any] { return [:] }
+
+    let context: URLEncodedFormContext
+
+    private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
+    private let dataEncoding: URLEncodedFormEncoder.DataEncoding
+    private let dateEncoding: URLEncodedFormEncoder.DateEncoding
+
+    init(context: URLEncodedFormContext,
+         codingPath: [CodingKey] = [],
+         boolEncoding: URLEncodedFormEncoder.BoolEncoding,
+         dataEncoding: URLEncodedFormEncoder.DataEncoding,
+         dateEncoding: URLEncodedFormEncoder.DateEncoding) {
+        self.context = context
+        self.codingPath = codingPath
+        self.boolEncoding = boolEncoding
+        self.dataEncoding = dataEncoding
+        self.dateEncoding = dateEncoding
+    }
+}
+
+extension _URLEncodedFormEncoder: Encoder {
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
+        let container = _URLEncodedFormEncoder.KeyedContainer<Key>(context: context,
+                                                                   codingPath: codingPath,
+                                                                   boolEncoding: boolEncoding,
+                                                                   dataEncoding: dataEncoding,
+                                                                   dateEncoding: dateEncoding)
+        return KeyedEncodingContainer(container)
+    }
+
+    func unkeyedContainer() -> UnkeyedEncodingContainer {
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
+                                                       codingPath: codingPath,
+                                                       boolEncoding: boolEncoding,
+                                                       dataEncoding: dataEncoding,
+                                                       dateEncoding: dateEncoding)
+    }
+
+    func singleValueContainer() -> SingleValueEncodingContainer {
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
+                                                           codingPath: codingPath,
+                                                           boolEncoding: boolEncoding,
+                                                           dataEncoding: dataEncoding,
+                                                           dateEncoding: dateEncoding)
+    }
+}
+
+final class URLEncodedFormContext {
+    var component: URLEncodedFormComponent
+
+    init(_ component: URLEncodedFormComponent) {
+        self.component = component
+    }
+}
+
+enum URLEncodedFormComponent {
+    typealias Object = [(key: String, value: URLEncodedFormComponent)]
+
+    case string(String)
+    case array([URLEncodedFormComponent])
+    case object(Object)
+
+    /// Converts self to an `[URLEncodedFormData]` or returns `nil` if not convertible.
+    var array: [URLEncodedFormComponent]? {
+        switch self {
+        case let .array(array): return array
+        default: return nil
+        }
+    }
+
+    /// Converts self to an `Object` or returns `nil` if not convertible.
+    var object: Object? {
+        switch self {
+        case let .object(object): return object
+        default: return nil
+        }
+    }
+
+    /// Sets self to the supplied value at a given path.
+    ///
+    ///     data.set(to: "hello", at: ["path", "to", "value"])
+    ///
+    /// - parameters:
+    ///     - value: Value of `Self` to set at the supplied path.
+    ///     - path: `CodingKey` path to update with the supplied value.
+    public mutating func set(to value: URLEncodedFormComponent, at path: [CodingKey]) {
+        set(&self, to: value, at: path)
+    }
+
+    /// Recursive backing method to `set(to:at:)`.
+    private func set(_ context: inout URLEncodedFormComponent, to value: URLEncodedFormComponent, at path: [CodingKey]) {
+        guard path.count >= 1 else {
+            context = value
+            return
+        }
+
+        let end = path[0]
+        var child: URLEncodedFormComponent
+        switch path.count {
+        case 1:
+            child = value
+        case 2...:
+            if let index = end.intValue {
+                let array = context.array ?? []
+                if array.count > index {
+                    child = array[index]
+                } else {
+                    child = .array([])
+                }
+                set(&child, to: value, at: Array(path[1...]))
+            } else {
+                child = context.object?.first { $0.key == end.stringValue }?.value ?? .object(.init())
+                set(&child, to: value, at: Array(path[1...]))
+            }
+        default: fatalError("Unreachable")
+        }
+
+        if let index = end.intValue {
+            if var array = context.array {
+                if array.count > index {
+                    array[index] = child
+                } else {
+                    array.append(child)
+                }
+                context = .array(array)
+            } else {
+                context = .array([child])
+            }
+        } else {
+            if var object = context.object {
+                if let index = object.firstIndex(where: { $0.key == end.stringValue }) {
+                    object[index] = (key: end.stringValue, value: child)
+                } else {
+                    object.append((key: end.stringValue, value: child))
+                }
+                context = .object(object)
+            } else {
+                context = .object([(key: end.stringValue, value: child)])
+            }
+        }
+    }
+}
+
+struct AnyCodingKey: CodingKey, Hashable {
+    let stringValue: String
+    let intValue: Int?
+
+    init?(stringValue: String) {
+        self.stringValue = stringValue
+        intValue = nil
+    }
+
+    init?(intValue: Int) {
+        stringValue = "\(intValue)"
+        self.intValue = intValue
+    }
+
+    init<Key>(_ base: Key) where Key: CodingKey {
+        if let intValue = base.intValue {
+            self.init(intValue: intValue)!
+        } else {
+            self.init(stringValue: base.stringValue)!
+        }
+    }
+}
+
+extension _URLEncodedFormEncoder {
+    final class KeyedContainer<Key> where Key: CodingKey {
+        var codingPath: [CodingKey]
+
+        private let context: URLEncodedFormContext
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
+
+        init(context: URLEncodedFormContext,
+             codingPath: [CodingKey],
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
+            self.context = context
+            self.codingPath = codingPath
+            self.boolEncoding = boolEncoding
+            self.dataEncoding = dataEncoding
+            self.dateEncoding = dateEncoding
+        }
+
+        private func nestedCodingPath(for key: CodingKey) -> [CodingKey] {
+            return codingPath + [key]
+        }
+    }
+}
+
+extension _URLEncodedFormEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
+    func encodeNil(forKey key: Key) throws {
+        let context = EncodingError.Context(codingPath: codingPath,
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
+        throw EncodingError.invalidValue("\(key): nil", context)
+    }
+
+    func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
+        var container = nestedSingleValueEncoder(for: key)
+        try container.encode(value)
+    }
+
+    func nestedSingleValueEncoder(for key: Key) -> SingleValueEncodingContainer {
+        let container = _URLEncodedFormEncoder.SingleValueContainer(context: context,
+                                                                    codingPath: nestedCodingPath(for: key),
+                                                                    boolEncoding: boolEncoding,
+                                                                    dataEncoding: dataEncoding,
+                                                                    dateEncoding: dateEncoding)
+
+        return container
+    }
+
+    func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+        let container = _URLEncodedFormEncoder.UnkeyedContainer(context: context,
+                                                                codingPath: nestedCodingPath(for: key),
+                                                                boolEncoding: boolEncoding,
+                                                                dataEncoding: dataEncoding,
+                                                                dateEncoding: dateEncoding)
+
+        return container
+    }
+
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
+                                                                         codingPath: nestedCodingPath(for: key),
+                                                                         boolEncoding: boolEncoding,
+                                                                         dataEncoding: dataEncoding,
+                                                                         dateEncoding: dateEncoding)
+
+        return KeyedEncodingContainer(container)
+    }
+
+    func superEncoder() -> Encoder {
+        return _URLEncodedFormEncoder(context: context,
+                                      codingPath: codingPath,
+                                      boolEncoding: boolEncoding,
+                                      dataEncoding: dataEncoding,
+                                      dateEncoding: dateEncoding)
+    }
+
+    func superEncoder(forKey key: Key) -> Encoder {
+        return _URLEncodedFormEncoder(context: context,
+                                      codingPath: nestedCodingPath(for: key),
+                                      boolEncoding: boolEncoding,
+                                      dataEncoding: dataEncoding,
+                                      dateEncoding: dateEncoding)
+    }
+}
+
+extension _URLEncodedFormEncoder {
+    final class SingleValueContainer {
+        var codingPath: [CodingKey]
+
+        private var canEncodeNewValue = true
+
+        private let context: URLEncodedFormContext
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
+
+        init(context: URLEncodedFormContext,
+             codingPath: [CodingKey],
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
+            self.context = context
+            self.codingPath = codingPath
+            self.boolEncoding = boolEncoding
+            self.dataEncoding = dataEncoding
+            self.dateEncoding = dateEncoding
+        }
+
+        private func checkCanEncode(value: Any?) throws {
+            guard canEncodeNewValue else {
+                let context = EncodingError.Context(codingPath: codingPath,
+                                                    debugDescription: "Attempt to encode value through single value container when previously value already encoded.")
+                throw EncodingError.invalidValue(value as Any, context)
+            }
+        }
+    }
+}
+
+extension _URLEncodedFormEncoder.SingleValueContainer: SingleValueEncodingContainer {
+    func encodeNil() throws {
+        try checkCanEncode(value: nil)
+        defer { canEncodeNewValue = false }
+
+        let context = EncodingError.Context(codingPath: codingPath,
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
+        throw EncodingError.invalidValue("nil", context)
+    }
+
+    func encode(_ value: Bool) throws {
+        try encode(value, as: String(boolEncoding.encode(value)))
+    }
+
+    func encode(_ value: String) throws {
+        try encode(value, as: value)
+    }
+
+    func encode(_ value: Double) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Float) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Int) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Int8) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Int16) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Int32) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: Int64) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: UInt) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: UInt8) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: UInt16) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: UInt32) throws {
+        try encode(value, as: String(value))
+    }
+
+    func encode(_ value: UInt64) throws {
+        try encode(value, as: String(value))
+    }
+
+    private func encode<T>(_ value: T, as string: String) throws where T: Encodable {
+        try checkCanEncode(value: value)
+        defer { canEncodeNewValue = false }
+
+        context.component.set(to: .string(string), at: codingPath)
+    }
+
+    func encode<T>(_ value: T) throws where T: Encodable {
+        switch value {
+        case let date as Date:
+            guard let string = try dateEncoding.encode(date) else {
+                try attemptToEncode(value)
+                return
+            }
+
+            try encode(value, as: string)
+        case let data as Data:
+            guard let string = try dataEncoding.encode(data) else {
+                try attemptToEncode(value)
+                return
+            }
+
+            try encode(value, as: string)
+        default:
+            try attemptToEncode(value)
+        }
+    }
+
+    private func attemptToEncode<T>(_ value: T) throws where T: Encodable {
+        try checkCanEncode(value: value)
+        defer { canEncodeNewValue = false }
+
+        let encoder = _URLEncodedFormEncoder(context: context,
+                                             codingPath: codingPath,
+                                             boolEncoding: boolEncoding,
+                                             dataEncoding: dataEncoding,
+                                             dateEncoding: dateEncoding)
+        try value.encode(to: encoder)
+    }
+}
+
+extension _URLEncodedFormEncoder {
+    final class UnkeyedContainer {
+        var codingPath: [CodingKey]
+
+        var count = 0
+        var nestedCodingPath: [CodingKey] {
+            return codingPath + [AnyCodingKey(intValue: count)!]
+        }
+
+        private let context: URLEncodedFormContext
+        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding
+        private let dataEncoding: URLEncodedFormEncoder.DataEncoding
+        private let dateEncoding: URLEncodedFormEncoder.DateEncoding
+
+        init(context: URLEncodedFormContext,
+             codingPath: [CodingKey],
+             boolEncoding: URLEncodedFormEncoder.BoolEncoding,
+             dataEncoding: URLEncodedFormEncoder.DataEncoding,
+             dateEncoding: URLEncodedFormEncoder.DateEncoding) {
+            self.context = context
+            self.codingPath = codingPath
+            self.boolEncoding = boolEncoding
+            self.dataEncoding = dataEncoding
+            self.dateEncoding = dateEncoding
+        }
+    }
+}
+
+extension _URLEncodedFormEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
+    func encodeNil() throws {
+        let context = EncodingError.Context(codingPath: codingPath,
+                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")
+        throw EncodingError.invalidValue("nil", context)
+    }
+
+    func encode<T>(_ value: T) throws where T: Encodable {
+        var container = nestedSingleValueContainer()
+        try container.encode(value)
+    }
+
+    func nestedSingleValueContainer() -> SingleValueEncodingContainer {
+        defer { count += 1 }
+
+        return _URLEncodedFormEncoder.SingleValueContainer(context: context,
+                                                           codingPath: nestedCodingPath,
+                                                           boolEncoding: boolEncoding,
+                                                           dataEncoding: dataEncoding,
+                                                           dateEncoding: dateEncoding)
+    }
+
+    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
+        defer { count += 1 }
+        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,
+                                                                         codingPath: nestedCodingPath,
+                                                                         boolEncoding: boolEncoding,
+                                                                         dataEncoding: dataEncoding,
+                                                                         dateEncoding: dateEncoding)
+
+        return KeyedEncodingContainer(container)
+    }
+
+    func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
+        defer { count += 1 }
+
+        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,
+                                                       codingPath: nestedCodingPath,
+                                                       boolEncoding: boolEncoding,
+                                                       dataEncoding: dataEncoding,
+                                                       dateEncoding: dateEncoding)
+    }
+
+    func superEncoder() -> Encoder {
+        defer { count += 1 }
+
+        return _URLEncodedFormEncoder(context: context,
+                                      codingPath: codingPath,
+                                      boolEncoding: boolEncoding,
+                                      dataEncoding: dataEncoding,
+                                      dateEncoding: dateEncoding)
+    }
+}
+
+final class URLEncodedFormSerializer {
+    private let alphabetizeKeyValuePairs: Bool
+    private let arrayEncoding: URLEncodedFormEncoder.ArrayEncoding
+    private let keyEncoding: URLEncodedFormEncoder.KeyEncoding
+    private let spaceEncoding: URLEncodedFormEncoder.SpaceEncoding
+    private let allowedCharacters: CharacterSet
+
+    init(alphabetizeKeyValuePairs: Bool,
+         arrayEncoding: URLEncodedFormEncoder.ArrayEncoding,
+         keyEncoding: URLEncodedFormEncoder.KeyEncoding,
+         spaceEncoding: URLEncodedFormEncoder.SpaceEncoding,
+         allowedCharacters: CharacterSet) {
+        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs
+        self.arrayEncoding = arrayEncoding
+        self.keyEncoding = keyEncoding
+        self.spaceEncoding = spaceEncoding
+        self.allowedCharacters = allowedCharacters
+    }
+
+    func serialize(_ object: URLEncodedFormComponent.Object) -> String {
+        var output: [String] = []
+        for (key, component) in object {
+            let value = serialize(component, forKey: key)
+            output.append(value)
+        }
+        output = alphabetizeKeyValuePairs ? output.sorted() : output
+
+        return output.joinedWithAmpersands()
+    }
+
+    func serialize(_ component: URLEncodedFormComponent, forKey key: String) -> String {
+        switch component {
+        case let .string(string): return "\(escape(keyEncoding.encode(key)))=\(escape(string))"
+        case let .array(array): return serialize(array, forKey: key)
+        case let .object(object): return serialize(object, forKey: key)
+        }
+    }
+
+    func serialize(_ object: URLEncodedFormComponent.Object, forKey key: String) -> String {
+        var segments: [String] = object.map { subKey, value in
+            let keyPath = "[\(subKey)]"
+            return serialize(value, forKey: key + keyPath)
+        }
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
+
+        return segments.joinedWithAmpersands()
+    }
+
+    func serialize(_ array: [URLEncodedFormComponent], forKey key: String) -> String {
+        var segments: [String] = array.map { component in
+            let keyPath = arrayEncoding.encode(key)
+            return serialize(component, forKey: keyPath)
+        }
+        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments
+
+        return segments.joinedWithAmpersands()
+    }
+
+    func escape(_ query: String) -> String {
+        var allowedCharactersWithSpace = allowedCharacters
+        allowedCharactersWithSpace.insert(charactersIn: " ")
+        let escapedQuery = query.addingPercentEncoding(withAllowedCharacters: allowedCharactersWithSpace) ?? query
+        let spaceEncodedQuery = spaceEncoding.encode(escapedQuery)
+
+        return spaceEncodedQuery
+    }
+}
+
+extension Array where Element == String {
+    func joinedWithAmpersands() -> String {
+        return joined(separator: "&")
+    }
+}
+
+public extension CharacterSet {
+    /// Creates a CharacterSet from RFC 3986 allowed characters.
+    ///
+    /// RFC 3986 states that the following characters are "reserved" characters.
+    ///
+    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
+    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
+    ///
+    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
+    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
+    /// should be percent-escaped in the query string.
+    static let afURLQueryAllowed: CharacterSet = {
+        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
+        let subDelimitersToEncode = "!$&'()*+,;="
+        let encodableDelimiters = CharacterSet(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
+
+        return CharacterSet.urlQueryAllowed.subtracting(encodableDelimiters)
+    }()
+}

+ 39 - 0
Pods/Alamofire/Source/URLRequest+Alamofire.swift

@@ -0,0 +1,39 @@
+//
+//  URLRequest+Alamofire.swift
+//
+//  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+public extension URLRequest {
+    /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type.
+    var method: HTTPMethod? {
+        get { return httpMethod.flatMap(HTTPMethod.init) }
+        set { httpMethod = newValue?.rawValue }
+    }
+
+    func validate() throws {
+        if method == .get, let bodyData = httpBody {
+            throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData))
+        }
+    }
+}

+ 37 - 0
Pods/Alamofire/Source/URLSessionConfiguration+Alamofire.swift

@@ -0,0 +1,37 @@
+//
+//  URLSessionConfiguration+Alamofire.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+extension URLSessionConfiguration: AlamofireExtended {}
+extension AlamofireExtension where ExtendedType: URLSessionConfiguration {
+    /// Alamofire's default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default
+    /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers.
+    public static var `default`: URLSessionConfiguration {
+        let configuration = URLSessionConfiguration.default
+        configuration.headers = .default
+
+        return configuration
+    }
+}

+ 247 - 0
Pods/Alamofire/Source/Validation.swift

@@ -0,0 +1,247 @@
+//
+//  Validation.swift
+//
+//  Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+extension Request {
+    // MARK: Helper Types
+
+    fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
+
+    /// Used to represent whether a validation succeeded or failed.
+    public typealias ValidationResult = Result<Void, Error>
+
+    fileprivate struct MIMEType {
+        let type: String
+        let subtype: String
+
+        var isWildcard: Bool { return type == "*" && subtype == "*" }
+
+        init?(_ string: String) {
+            let components: [String] = {
+                let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
+                let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)]
+
+                return split.components(separatedBy: "/")
+            }()
+
+            if let type = components.first, let subtype = components.last {
+                self.type = type
+                self.subtype = subtype
+            } else {
+                return nil
+            }
+        }
+
+        func matches(_ mime: MIMEType) -> Bool {
+            switch (type, subtype) {
+            case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
+                return true
+            default:
+                return false
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    fileprivate var acceptableStatusCodes: Range<Int> { return 200..<300 }
+
+    fileprivate var acceptableContentTypes: [String] {
+        if let accept = request?.value(forHTTPHeaderField: "Accept") {
+            return accept.components(separatedBy: ",")
+        }
+
+        return ["*/*"]
+    }
+
+    // MARK: Status Code
+
+    fileprivate func validate<S: Sequence>(statusCode acceptableStatusCodes: S,
+                                           response: HTTPURLResponse)
+        -> ValidationResult
+        where S.Iterator.Element == Int {
+        if acceptableStatusCodes.contains(response.statusCode) {
+            return .success(Void())
+        } else {
+            let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode)
+            return .failure(AFError.responseValidationFailed(reason: reason))
+        }
+    }
+
+    // MARK: Content Type
+
+    fileprivate func validate<S: Sequence>(contentType acceptableContentTypes: S,
+                                           response: HTTPURLResponse,
+                                           data: Data?)
+        -> ValidationResult
+        where S.Iterator.Element == String {
+        guard let data = data, !data.isEmpty else { return .success(Void()) }
+
+        guard
+            let responseContentType = response.mimeType,
+            let responseMIMEType = MIMEType(responseContentType)
+        else {
+            for contentType in acceptableContentTypes {
+                if let mimeType = MIMEType(contentType), mimeType.isWildcard {
+                    return .success(Void())
+                }
+            }
+
+            let error: AFError = {
+                let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes))
+                return AFError.responseValidationFailed(reason: reason)
+            }()
+
+            return .failure(error)
+        }
+
+        for contentType in acceptableContentTypes {
+            if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) {
+                return .success(Void())
+            }
+        }
+
+        let error: AFError = {
+            let reason: ErrorReason = .unacceptableContentType(acceptableContentTypes: Array(acceptableContentTypes),
+                                                               responseContentType: responseContentType)
+
+            return AFError.responseValidationFailed(reason: reason)
+        }()
+
+        return .failure(error)
+    }
+}
+
+// MARK: -
+
+extension DataRequest {
+    /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
+    /// request was valid.
+    public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
+
+    /// Validates that the response has a status code in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter range: The range of acceptable status codes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
+        return validate { [unowned self] _, response, _ in
+            self.validate(statusCode: acceptableStatusCodes, response: response)
+        }
+    }
+
+    /// Validates that the response has a content type in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
+        return validate { [unowned self] _, response, data in
+            self.validate(contentType: acceptableContentTypes(), response: response, data: data)
+        }
+    }
+
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
+    /// type matches any specified in the Accept HTTP header field.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate() -> Self {
+        let contentTypes: () -> [String] = { [unowned self] in
+            self.acceptableContentTypes
+        }
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
+    }
+}
+
+// MARK: -
+
+extension DownloadRequest {
+    /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
+    /// destination URL, and returns whether the request was valid.
+    public typealias Validation = (_ request: URLRequest?,
+                                   _ response: HTTPURLResponse,
+                                   _ fileURL: URL?)
+        -> ValidationResult
+
+    /// Validates that the response has a status code in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter range: The range of acceptable status codes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
+        return validate { [unowned self] _, response, _ in
+            self.validate(statusCode: acceptableStatusCodes, response: response)
+        }
+    }
+
+    /// Validates that the response has a content type in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
+        return validate { [unowned self] _, response, fileURL in
+            guard let validFileURL = fileURL else {
+                return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: validFileURL)
+                return self.validate(contentType: acceptableContentTypes(), response: response, data: data)
+            } catch {
+                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
+            }
+        }
+    }
+
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
+    /// type matches any specified in the Accept HTTP header field.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate() -> Self {
+        let contentTypes = { [unowned self] in
+            self.acceptableContentTypes
+        }
+        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
+    }
+}

+ 136 - 0
Pods/Firebase/CoreOnly/Sources/Firebase.h

@@ -0,0 +1,136 @@
+// Copyright 2019 Google
+//
+// 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 <FirebaseCore/FirebaseCore.h>
+
+#if !defined(__has_include)
+  #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \
+          import the headers individually."
+#else
+  #if __has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+    #import <FirebaseAnalytics/FirebaseAnalytics.h>
+  #endif
+
+  #if __has_include(<FirebaseAppDistribution/FirebaseAppDistribution.h>)
+    #import <FirebaseAppDistribution/FirebaseAppDistribution.h>
+  #endif
+
+  #if __has_include(<FirebaseAuth/FirebaseAuth.h>)
+    #import <FirebaseAuth/FirebaseAuth.h>
+  #endif
+
+  #if __has_include(<FirebaseCrashlytics/FirebaseCrashlytics.h>)
+    #import <FirebaseCrashlytics/FirebaseCrashlytics.h>
+  #endif
+
+  #if __has_include(<FirebaseDatabase/FirebaseDatabase.h>)
+    #import <FirebaseDatabase/FirebaseDatabase.h>
+  #endif
+
+  #if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
+    #import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
+    #if TARGET_OS_IOS && !__has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+      #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+        #warning "FirebaseAnalytics.framework is not included in your target. Please add the \
+FirebaseAnalytics dependency to your project to ensure Firebase Dynamic Links works as intended."
+      #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+    #endif
+  #endif
+
+  #if __has_include(<FirebaseFirestore/FirebaseFirestore.h>)
+    #import <FirebaseFirestore/FirebaseFirestore.h>
+  #endif
+
+  #if __has_include(<FirebaseFunctions/FirebaseFunctions.h>)
+    #import <FirebaseFunctions/FirebaseFunctions.h>
+  #endif
+
+  #if __has_include(<FirebaseInAppMessaging/FirebaseInAppMessaging.h>)
+    #import <FirebaseInAppMessaging/FirebaseInAppMessaging.h>
+    #if TARGET_OS_IOS && !__has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+      #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+        #warning "FirebaseAnalytics.framework is not included in your target. Please add the \
+FirebaseAnalytics dependency to your project to ensure Firebase In App Messaging works as intended."
+      #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+    #endif
+  #endif
+
+  #if __has_include(<FirebaseInstallations/FirebaseInstallations.h>)
+    #import <FirebaseInstallations/FirebaseInstallations.h>
+  #endif
+
+  #if __has_include(<FirebaseInstanceID/FirebaseInstanceID.h>)
+    #import <FirebaseInstanceID/FirebaseInstanceID.h>
+  #endif
+
+  #if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
+    #import <FirebaseMessaging/FirebaseMessaging.h>
+      #if TARGET_OS_IOS && !__has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+      #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+        #warning "FirebaseAnalytics.framework is not included in your target. Please add the \
+FirebaseAnalytics dependency to your project to ensure Messaging works as intended."
+
+      #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+    #endif
+  #endif
+
+  #if __has_include(<FirebaseMLCommon/FirebaseMLCommon.h>)
+    #import <FirebaseMLCommon/FirebaseMLCommon.h>
+  #endif
+
+  #if __has_include(<FirebaseMLModelInterpreter/FirebaseMLModelInterpreter.h>)
+    #import <FirebaseMLModelInterpreter/FirebaseMLModelInterpreter.h>
+  #endif
+
+  #if __has_include(<FirebaseMLVision/FirebaseMLVision.h>)
+    #import <FirebaseMLVision/FirebaseMLVision.h>
+  #endif
+
+  #if __has_include(<FirebasePerformance/FirebasePerformance.h>)
+    #import <FirebasePerformance/FirebasePerformance.h>
+    #if TARGET_OS_IOS && !__has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+      #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+        #warning "FirebaseAnalytics.framework is not included in your target. Please add the \
+FirebaseAnalytics dependency to your project to ensure Firebase Performance works as intended."
+      #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+    #endif
+  #endif
+
+  #if __has_include(<FirebaseRemoteConfig/FirebaseRemoteConfig.h>)
+    #import <FirebaseRemoteConfig/FirebaseRemoteConfig.h>
+    #if TARGET_OS_IOS && !__has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
+      #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+        #warning "FirebaseAnalytics.framework is not included in your target. Please add the \
+FirebaseAnalytics dependency to your project to ensure Firebase Remote Config works as intended."
+      #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
+    #endif
+  #endif
+
+  #if __has_include(<FirebaseStorage/FirebaseStorage.h>)
+    #import <FirebaseStorage/FirebaseStorage.h>
+  #endif
+
+  #if __has_include(<GoogleMobileAds/GoogleMobileAds.h>)
+    #import <GoogleMobileAds/GoogleMobileAds.h>
+  #endif
+
+  #if __has_include(<Fabric/Fabric.h>)
+    #import <Fabric/Fabric.h>
+  #endif
+
+  #if __has_include(<Crashlytics/Crashlytics.h>)
+    #import <Crashlytics/Crashlytics.h>
+  #endif
+
+#endif  // defined(__has_include)

+ 4 - 0
Pods/Firebase/CoreOnly/Sources/module.modulemap

@@ -0,0 +1,4 @@
+module Firebase {
+  export *
+  header "Firebase.h"
+}

+ 202 - 0
Pods/Firebase/LICENSE

@@ -0,0 +1,202 @@
+
+                                 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 2020 Firebase, Inc.
+
+   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.

+ 300 - 0
Pods/Firebase/README.md

@@ -0,0 +1,300 @@
+[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+
+[![Actions Status][gh-abtesting-badge]][gh-actions]
+[![Actions Status][gh-appdistribution-badge]][gh-actions]
+[![Actions Status][gh-auth-badge]][gh-actions]
+[![Actions Status][gh-core-badge]][gh-actions]
+[![Actions Status][gh-crashlytics-badge]][gh-actions]
+[![Actions Status][gh-database-badge]][gh-actions]
+[![Actions Status][gh-datatransport-badge]][gh-actions]
+[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
+[![Actions Status][gh-firebasepod-badge]][gh-actions]
+[![Actions Status][gh-firestore-badge]][gh-actions]
+[![Actions Status][gh-functions-badge]][gh-actions]
+[![Actions Status][gh-inappmessaging-badge]][gh-actions]
+[![Actions Status][gh-interop-badge]][gh-actions]
+[![Actions Status][gh-messaging-badge]][gh-actions]
+[![Actions Status][gh-remoteconfig-badge]][gh-actions]
+[![Actions Status][gh-storage-badge]][gh-actions]
+[![Actions Status][gh-symbolcollision-badge]][gh-actions]
+[![Actions Status][gh-zip-badge]][gh-actions]
+[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
+
+# Firebase Apple Open Source Development
+
+This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics,
+FirebasePerformance, and FirebaseML.
+
+Firebase is an app development platform with tools to help you build, grow and
+monetize your app. More information about Firebase can be found at
+[https://firebase.google.com](https://firebase.google.com).
+
+The repository also includes GoogleUtilities and GoogleDataTransport source
+which are utilities used by Firebase and other Google products.
+
+## Installation
+
+See the subsections below for details about the different installation methods.
+1. [Standard pod install](README.md#standard-pod-install)
+1. [Swift Package Manager (Beta)](SwiftPackageManager.md)
+1. [Installing from the GitHub repo](README.md#installing-from-github)
+1. [Experimental Carthage](README.md#carthage-ios-only)
+
+### Standard pod install
+
+Go to
+[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
+
+### Swift Package Manager (Beta)
+
+Instructions for the Beta of [Swift Package Manager](https://swift.org/package-manager/)
+support can be found at [SwiftPackageManager.md](SwiftPackageManager.md).
+
+### Installing from GitHub
+
+For releases starting with 5.0.0, the source for each release is also deployed
+to CocoaPods master and available via standard
+[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
+
+These instructions can be used to access the Firebase repo at other branches,
+tags, or commits.
+
+#### Background
+
+See
+[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
+for instructions and options about overriding pod source locations.
+
+#### Accessing Firebase Source Snapshots
+
+All of the official releases are tagged in this repo and available via CocoaPods. To access a local
+source snapshot or unreleased branch, use Podfile directives like the following:
+
+To access FirebaseFirestore via a branch:
+```
+pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
+pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
+```
+
+To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
+
+```
+pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
+pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
+```
+
+### Carthage (iOS only)
+
+Instructions for the experimental Carthage distribution are at
+[Carthage](Carthage.md).
+
+### Using Firebase from a Framework or a library
+
+[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md)
+
+## Development
+
+To develop Firebase software in this repository, ensure that you have at least
+the following software:
+
+  * Xcode 11.0 (or later)
+  * CocoaPods 1.9.0 (or later)
+  * [CocoaPods generate](https://github.com/square/cocoapods-generate)
+
+For the pod that you want to develop:
+
+`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios`
+
+Note: If the CocoaPods cache is out of date, you may need to run
+`pod repo update` before the `pod gen` command.
+
+Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for
+those platforms. Since 10.2, Xcode does not properly handle multi-platform
+CocoaPods workspaces.
+
+Firestore has a self contained Xcode project. See
+[Firestore/README.md](Firestore/README.md).
+
+### Development for Catalyst
+* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios`
+* Check the Mac box in the App-iOS Build Settings
+* Sign the App in the Settings Signing & Capabilities tab
+* Click Pods in the Project Manager
+* Add Signing to the iOS host app and unit test targets
+* Select the Unit-unit scheme
+* Run it to build and test
+
+### Adding a New Firebase Pod
+
+See [AddNewPod.md](AddNewPod.md).
+
+### Managing Headers and Imports
+
+See [HeadersImports.md](HeadersImports.md).
+
+### Code Formatting
+
+To ensure that the code is formatted consistently, run the script
+[./scripts/check.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/check.sh)
+before creating a PR.
+
+GitHub Actions will verify that any code changes are done in a style compliant
+way. Install `clang-format` and `mint`:
+
+```
+brew install clang-format@11
+brew install mint
+```
+
+### Running Unit Tests
+
+Select a scheme and press Command-u to build a component and run its unit tests.
+
+#### Viewing Code Coverage (Deprecated)
+
+First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
+
+After running the `AllUnitTests_iOS` scheme in Xcode, execute
+`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
+at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
+
+### Running Sample Apps
+In order to run the sample apps and integration tests, you'll need a valid
+`GoogleService-Info.plist` file. The Firebase Xcode project contains dummy plist
+files without real values, but can be replaced with real plist files. To get your own
+`GoogleService-Info.plist` files:
+
+1. Go to the [Firebase Console](https://console.firebase.google.com/)
+2. Create a new Firebase project, if you don't already have one
+3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
+identifier (e.g. `com.google.Database-Example`)
+4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project.
+
+## Specific Component Instructions
+See the sections below for any special instructions for those components.
+
+### Firebase Auth
+
+If you're doing specific Firebase Auth development, see
+[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about
+building and running the FirebaseAuth pod along with various samples and tests.
+
+### Firebase Database
+
+The Firebase Database Integration tests can be run against a locally running Database Emulator
+or against a production instance.
+
+To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
+running the integration test.
+
+To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
+`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to
+[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
+running.
+
+### Firebase Storage
+
+To run the Storage Integration tests, follow the instructions in
+[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m).
+
+#### Push Notifications
+
+Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
+In order to actually test receiving push notifications, you will need to:
+
+1. Change the bundle identifier of the sample app to something you own in your Apple Developer
+account, and enable that App ID for push notifications.
+2. You'll also need to
+[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
+at **Project Settings > Cloud Messaging > [Your Firebase App]**.
+3. Ensure your iOS device is added to your Apple Developer portal as a test device.
+
+#### iOS Simulator
+
+The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
+In order to receive push notifications, you'll have to follow the steps above and run the app on a
+physical device.
+
+## Community Supported Efforts
+
+We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
+very grateful!  We'd like to empower as many developers as we can to be able to use Firebase and
+participate in the Firebase community.
+
+### tvOS, macOS, watchOS and Catalyst
+Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on
+tvOS, macOS, watchOS and Catalyst.
+
+For tvOS, checkout the [Sample](Example/tvOSSample).
+For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the
+[Independent Watch App Sample](Example/watchOSSample).
+
+Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this
+repository is actively developed primarily for iOS. While we can catch basic unit test issues with
+Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you
+encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
+
+During app setup in the console, you may get to a step that mentions something like "Checking if the app
+has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst.
+**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected.
+
+To install, add a subset of the following to the Podfile:
+
+```
+pod 'Firebase/ABTesting'     # No watchOS support yet
+pod 'Firebase/Auth'          # Limited watchOS support
+pod 'Firebase/Crashlytics'
+pod 'Firebase/Database'      # No watchOS support yet
+pod 'Firebase/Firestore'     # No watchOS support yet
+pod 'Firebase/Functions'     # No watchOS support yet
+pod 'Firebase/Messaging'
+pod 'Firebase/RemoteConfig'  # No watchOS support yet
+pod 'Firebase/Storage'
+```
+
+#### Additional Catalyst Notes
+
+* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability`
+to Build Settings.
+* FirebaseFirestore requires signing the
+[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681).
+
+## Roadmap
+
+See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
+plans and directions.
+
+## Contributing
+
+See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
+iOS SDK.
+
+## License
+
+The contents of this repository is licensed under the
+[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
+
+Your use of Firebase is governed by the
+[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
+
+[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
+[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
+[gh-appdistribution-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/appdistribution/badge.svg
+[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
+[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
+[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
+[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
+[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
+[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
+[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
+[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
+[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
+[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
+[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
+[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
+[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
+[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
+[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
+[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg

BIN
Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector


+ 11 - 0
Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap

@@ -0,0 +1,11 @@
+framework module FIRAnalyticsConnector {
+  export *
+  module * { export * }
+  link "sqlite3"
+  link "z"
+  link framework "CoreData"
+  link framework "Security"
+  link framework "StoreKit"
+  link framework "SystemConfiguration"
+  link framework "UIKit"
+}

BIN
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics


+ 62 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h

@@ -0,0 +1,62 @@
+#import <Foundation/Foundation.h>
+
+#import "FIRAnalytics.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Provides App Delegate handlers to be used in your App Delegate.
+ *
+ * To save time integrating Firebase Analytics in an application, Firebase Analytics does not
+ * require delegation implementation from the AppDelegate. Instead this is automatically done by
+ * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App
+ * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting
+ * it to NO, and adding the methods in this category to corresponding delegation handlers.
+ *
+ * To handle Universal Links, you must return YES in
+ * [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
+ */
+@interface FIRAnalytics (AppDelegate)
+
+/**
+ * Handles events related to a URL session that are waiting to be processed.
+ *
+ * For optimal use of Firebase Analytics, call this method from the
+ * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler]
+ * method of the app delegate in your app.
+ *
+ * @param identifier The identifier of the URL session requiring attention.
+ * @param completionHandler The completion handler to call when you finish processing the events.
+ *     Calling this completion handler lets the system know that your app's user interface is
+ *     updated and a new snapshot can be taken.
+ */
++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier
+                          completionHandler:(nullable void (^)(void))completionHandler;
+
+/**
+ * Handles the event when the app is launched by a URL.
+ *
+ * Call this method from [UIApplicationDelegate application:openURL:options:] &#40;on iOS 9.0 and
+ * above&#41;, or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] &#40;on
+ * iOS 8.x and below&#41; in your app.
+ *
+ * @param url The URL resource to open. This resource can be a network resource or a file.
+ */
++ (void)handleOpenURL:(NSURL *)url;
+
+/**
+ * Handles the event when the app receives data associated with user activity that includes a
+ * Universal Link (on iOS 9.0 and above).
+ *
+ * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app
+ * delegate (on iOS 9.0 and above).
+ *
+ * @param userActivity The activity object containing the data associated with the task the user
+ *     was performing.
+ */
++ (void)handleUserActivity:(id)userActivity;
+
+@end
+
+NS_ASSUME_NONNULL_END
+

+ 33 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+Consent.h

@@ -0,0 +1,33 @@
+#import <Foundation/Foundation.h>
+
+#import "FIRAnalytics.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// The type of consent to set. Supported consent types are `ConsentType.adStorage` and
+/// `ConsentType.analyticsStorage`. Omitting a type retains its previous status.
+typedef NSString *FIRConsentType NS_TYPED_ENUM NS_SWIFT_NAME(ConsentType);
+extern FIRConsentType const FIRConsentTypeAdStorage;
+extern FIRConsentType const FIRConsentTypeAnalyticsStorage;
+
+/// The status value of the consent type. Supported statuses are `ConsentStatus.granted` and
+/// `ConsentStatus.denied`.
+typedef NSString *FIRConsentStatus NS_TYPED_ENUM NS_SWIFT_NAME(ConsentStatus);
+extern FIRConsentStatus const FIRConsentStatusDenied;
+extern FIRConsentStatus const FIRConsentStatusGranted;
+
+/// Sets the applicable end user consent state.
+@interface FIRAnalytics (Consent)
+
+/// Sets the applicable end user consent state (e.g. for device identifiers) for this app on this
+/// device. Use the consent settings to specify individual consent type values. Settings are
+/// persisted across app sessions. By default consent types are set to `ConsentStatus.granted`.
+///
+/// @param consentSettings An NSDictionary of consent types. Supported consent type keys are
+///   `ConsentType.adStorage` and `ConsentType.analyticsStorage`. Valid values are
+///   `ConsentStatus.granted` and `ConsentStatus.denied`.
++ (void)setConsent:(NSDictionary<FIRConsentType, FIRConsentStatus> *)consentSettings;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 173 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h

@@ -0,0 +1,173 @@
+#import <Foundation/Foundation.h>
+
+#import "FIREventNames.h"
+#import "FIRParameterNames.h"
+#import "FIRUserPropertyNames.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// The top level Firebase Analytics singleton that provides methods for logging events and setting
+/// user properties. See <a href="http://goo.gl/gz8SLz">the developer guides</a> for general
+/// information on using Firebase Analytics in your apps.
+///
+/// @note The Analytics SDK uses SQLite to persist events and other app-specific data. Calling
+///     certain thread-unsafe global SQLite methods like `sqlite3_shutdown()` can result in
+///     unexpected crashes at runtime.
+NS_SWIFT_NAME(Analytics)
+@interface FIRAnalytics : NSObject
+
+/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have
+/// the same parameters. Up to 500 event names are supported. Using predefined events and/or
+/// parameters is recommended for optimal reporting.
+///
+/// The following event names are reserved and cannot be used:
+/// <ul>
+///     <li>ad_activeview</li>
+///     <li>ad_click</li>
+///     <li>ad_exposure</li>
+///     <li>ad_query</li>
+///     <li>ad_reward</li>
+///     <li>adunit_exposure</li>
+///     <li>app_background</li>
+///     <li>app_clear_data</li>
+///     <li>app_exception</li>
+///     <li>app_remove</li>
+///     <li>app_store_refund</li>
+///     <li>app_store_subscription_cancel</li>
+///     <li>app_store_subscription_convert</li>
+///     <li>app_store_subscription_renew</li>
+///     <li>app_update</li>
+///     <li>app_upgrade</li>
+///     <li>dynamic_link_app_open</li>
+///     <li>dynamic_link_app_update</li>
+///     <li>dynamic_link_first_open</li>
+///     <li>error</li>
+///     <li>firebase_campaign</li>
+///     <li>first_open</li>
+///     <li>first_visit</li>
+///     <li>in_app_purchase</li>
+///     <li>notification_dismiss</li>
+///     <li>notification_foreground</li>
+///     <li>notification_open</li>
+///     <li>notification_receive</li>
+///     <li>os_update</li>
+///     <li>session_start</li>
+///     <li>session_start_with_rollout</li>
+///     <li>user_engagement</li>
+/// </ul>
+///
+/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or
+///     underscores. The name must start with an alphabetic character. Some event names are
+///     reserved. See FIREventNames.h for the list of reserved event names. The "firebase_",
+///     "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are
+///     case-sensitive and that logging two events whose names differ only in case will result in
+///     two distinct events. To manually log screen view events, use the `screen_view` event name.
+/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has
+///     no parameters. Parameter names can be up to 40 characters long and must start with an
+///     alphabetic character and contain only alphanumeric characters and underscores. Only NSString
+///     and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are
+///     supported. NSString parameter values can be up to 100 characters long. The "firebase_",
+///     "google_", and "ga_" prefixes are reserved and should not be used for parameter names.
++ (void)logEventWithName:(NSString *)name
+              parameters:(nullable NSDictionary<NSString *, id> *)parameters
+    NS_SWIFT_NAME(logEvent(_:parameters:));
+
+/// Sets a user property to a given value. Up to 25 user property names are supported. Once set,
+/// user property values persist throughout the app lifecycle and across sessions.
+///
+/// The following user property names are reserved and cannot be used:
+/// <ul>
+///     <li>first_open_time</li>
+///     <li>last_deep_link_referrer</li>
+///     <li>user_id</li>
+/// </ul>
+///
+/// @param value The value of the user property. Values can be up to 36 characters long. Setting the
+///     value to nil removes the user property.
+/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters
+///     or underscores and must start with an alphabetic character. The "firebase_", "google_", and
+///     "ga_" prefixes are reserved and should not be used for user property names.
++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name
+    NS_SWIFT_NAME(setUserProperty(_:forName:));
+
+/// Sets the user ID property. This feature must be used in accordance with
+/// <a href="https://www.google.com/policies/privacy">Google's Privacy Policy</a>
+///
+/// @param userID The user ID to ascribe to the user of this app on this device, which must be
+///     non-empty and no more than 256 characters long. Setting userID to nil removes the user ID.
++ (void)setUserID:(nullable NSString *)userID;
+
+/// This method was deprecated in Firebase 6.29.0.
+///
+/// Sets the current screen name, which specifies the current visual context in your app. This helps
+/// identify the areas in your app where users spend their time and how they interact with your app.
+/// Must be called on the main thread.
+///
+/// Note that screen reporting is enabled automatically and records the class name of the current
+/// UIViewController for you without requiring you to call this method. The class name can
+/// optionally be overridden by calling this method in the viewDidAppear callback of your
+/// UIViewController and specifying the screenClassOverride parameter.
+/// `setScreenName:screenClass:` must be called after `[super viewDidAppear:]`.
+///
+/// If your app does not use a distinct UIViewController for each screen, you should call this
+/// method and specify a distinct screenName each time a new screen is presented to the user.
+///
+/// The screen name and screen class remain in effect until the current UIViewController changes or
+/// a new call to setScreenName:screenClass: is made.
+///
+/// @warning If you override `viewDidAppear:` in your UIViewController but do not call
+///     `[super viewDidAppear:]`, that screen class will not be tracked.
+///
+/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil
+///     to clear the current screen name.
+/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By
+///     default this is the class name of the current UIViewController. Set to nil to revert to the
+///     default class name.
++ (void)setScreenName:(nullable NSString *)screenName
+          screenClass:(nullable NSString *)screenClassOverride
+    DEPRECATED_MSG_ATTRIBUTE(
+        "Use +[FIRAnalytics logEventWithName:kFIREventScreenView parameters:] instead.");
+
+/// Sets whether analytics collection is enabled for this app on this device. This setting is
+/// persisted across app sessions. By default it is enabled.
+///
+/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection.
++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled;
+
+/// Sets the interval of inactivity in seconds that terminates the current session. The default
+/// value is 1800 seconds (30 minutes).
+///
+/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current
+///     session terminates.
++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval;
+
+/// Returns the unique ID for this instance of the application or nil if
+/// `ConsentType.analyticsStorage` has been set to `ConsentStatus.denied`.
+///
+/// @see `FIRAnalytics+Consent.h`
++ (nullable NSString *)appInstanceID;
+
+/// Clears all analytics data for this instance from the device and resets the app instance ID.
+/// FIRAnalyticsConfiguration values will be reset to the default values.
++ (void)resetAnalyticsData;
+
+/// Adds parameters that will be set on every event logged from the SDK, including automatic ones.
+/// The values passed in the parameters dictionary will be added to the dictionary of default event
+/// parameters. These parameters persist across app runs. They are of lower precedence than event
+/// parameters, so if an event parameter and a parameter set using this API have the same name, the
+/// value of the event parameter will be used. The same limitations on event parameters apply to
+/// default event parameters.
+///
+/// @param parameters Parameters to be added to the dictionary of parameters added to every event.
+///     They will be added to the dictionary of default event parameters, replacing any existing
+///     parameter with the same name. Valid parameters are NSString and NSNumber (signed 64-bit
+///     integer and 64-bit floating-point number). Setting a key's value to [NSNull null] will clear
+///     that parameter. Passing in a nil dictionary will clear all parameters.
++ (void)setDefaultEventParameters:(nullable NSDictionary<NSString *, id> *)parameters;
+
+/// Unavailable.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 495 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h

@@ -0,0 +1,495 @@
+/// @file FIREventNames.h
+///
+/// Predefined event names.
+///
+/// An Event is an important occurrence in your app that you want to measure. You can report up to
+/// 500 different types of Events per app and you can associate up to 25 unique parameters with each
+/// Event type. Some common events are suggested below, but you may also choose to specify custom
+/// Event types that are associated with your specific app. Each event type is identified by a
+/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric
+/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_",
+/// "google_", and "ga_" prefixes are reserved and should not be used.
+
+#import <Foundation/Foundation.h>
+
+/// Add Payment Info event. This event signifies that a user has submitted their payment
+/// information. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterPaymentType (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) =
+    @"add_payment_info";
+
+/// E-Commerce Add To Cart event. This event signifies that an item(s) was added to a cart for
+/// purchase. Add this event to a funnel with @c kFIREventPurchase to gauge the effectiveness of
+/// your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must also
+/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart";
+
+/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. Use
+/// this event to identify popular gift items. Note: If you supply the @c kFIRParameterValue
+/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue metrics
+/// can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) =
+    @"add_to_wishlist";
+
+/// Ad Impression event. This event signifies when a user sees an ad impression. Note: If you supply
+/// the @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency parameter
+/// so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterAdPlatform (NSString) (optional)</li>
+///     <li>@c kFIRParameterAdFormat (NSString) (optional)</li>
+///     <li>@c kFIRParameterAdSource (NSString) (optional)</li>
+///     <li>@c kFIRParameterAdUnitName (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAdImpression NS_SWIFT_NAME(AnalyticsEventAdImpression) =
+    @"ad_impression";
+
+/// App Open event. By logging this event when an App becomes active, developers can understand how
+/// often users leave and return during the course of a Session. Although Sessions are automatically
+/// reported, this event can provide further clarification around the continuous engagement of
+/// app-users.
+static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open";
+
+/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of
+/// checking out. Add this event to a funnel with your @c kFIREventPurchase event to gauge the
+/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue parameter,
+/// you must also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be
+/// computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) =
+    @"begin_checkout";
+
+/// Campaign Detail event. Log this event to supply the referral details of a re-engagement
+/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource,
+/// kFIRParameterMedium or kFIRParameterCampaign. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSource (NSString)</li>
+///     <li>@c kFIRParameterMedium (NSString)</li>
+///     <li>@c kFIRParameterCampaign (NSString)</li>
+///     <li>@c kFIRParameterTerm (NSString) (optional)</li>
+///     <li>@c kFIRParameterContent (NSString) (optional)</li>
+///     <li>@c kFIRParameterAdNetworkClickID (NSString) (optional)</li>
+///     <li>@c kFIRParameterCP1 (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) =
+    @"campaign_details";
+
+/// Checkout progress. Params:
+///
+/// <ul>
+///    <li>@c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)</li>
+///    <li>@c kFIRParameterCheckoutOption (NSString) (optional)</li>
+/// </ul>
+/// <b>This constant has been deprecated.</b>
+static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) =
+    @"checkout_progress";
+
+/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log
+/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
+///     <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
+/// </ul>
+static NSString *const kFIREventEarnVirtualCurrency
+    NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency";
+
+/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note:
+/// This is different from the in-app purchase event, which is reported automatically for App
+/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also
+/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterTax (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterShipping (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterLocation (NSString) (optional)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+/// <b>This constant has been deprecated. Use @c kFIREventPurchase constant instead.</b>
+static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) =
+    @"ecommerce_purchase";
+
+/// Generate Lead event. Log this event when a lead has been generated in the app to understand the
+/// efficacy of your install and re-engagement campaigns. Note: If you supply the
+/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency
+/// parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) =
+    @"generate_lead";
+
+/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use
+/// this event to analyze how popular certain groups or social features are in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterGroupID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group";
+
+/// Level End event. Log this event when the user finishes a level. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterLevelName (NSString)</li>
+///     <li>@c kFIRParameterSuccess (NSString)</li>
+/// </ul>
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end";
+
+/// Level Start event. Log this event when the user starts a new level. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterLevelName (NSString)</li>
+/// </ul>
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = @"level_start";
+
+/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can
+/// help you gauge the level distribution of your userbase and help you identify certain levels that
+/// are difficult to pass. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterCharacter (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up";
+
+/// Login event. Apps with a login feature can report this event to signify that a user has logged
+/// in.
+static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login";
+
+/// Post Score event. Log this event when the user posts a score in your gaming app. This event can
+/// help you understand how users are actually performing in your game and it can help you correlate
+/// high scores with certain audiences or behaviors. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterScore (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCharacter (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score";
+
+/// Present Offer event. This event signifies that the app has presented a purchase offer to a user.
+/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge
+/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must
+/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+///     <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+/// <b>This constant has been deprecated. Use @c kFIREventViewPromotion constant instead.</b>
+static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) =
+    @"present_offer";
+
+/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded.
+/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+/// </ul>
+/// <b>This constant has been deprecated. Use @c kFIREventRefund constant instead.</b>
+static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) =
+    @"purchase_refund";
+
+/// E-Commerce Remove from Cart event. This event signifies that an item(s) was removed from a cart.
+/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the @c
+/// kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) =
+    @"remove_from_cart";
+
+/// Screen View event. This event signifies a screen view. Use this when a screen transition occurs.
+/// This event can be logged irrespective of whether automatic screen tracking is enabled. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterScreenClass (NSString) (optional)</li>
+///     <li>@c kFIRParameterScreenName (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventScreenView NS_SWIFT_NAME(AnalyticsEventScreenView) = @"screen_view";
+
+/// Search event. Apps that support search features can use this event to contextualize search
+/// operations by supplying the appropriate, corresponding parameters. This event can help you
+/// identify the most popular content in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSearchTerm (NSString)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search";
+
+/// Select Content event. This general purpose event signifies that a user has selected some content
+/// of a certain type in an app. The content can be any object in your app. This event can help you
+/// identify popular content and categories of content in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterContentType (NSString)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) =
+    @"select_content";
+
+/// Set checkout option. Params:
+///
+/// <ul>
+///    <li>@c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)</li>
+///    <li>@c kFIRParameterCheckoutOption (NSString)</li>
+/// </ul>
+/// <b>This constant has been deprecated.</b>
+static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) =
+    @"set_checkout_option";
+
+/// Share event. Apps with social features can log the Share event to identify the most viral
+/// content. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterContentType (NSString)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share";
+
+/// Sign Up event. This event indicates that a user has signed up for an account in your app. The
+/// parameter signifies the method by which the user signed up. Use this event to understand the
+/// different behaviors between logged in and logged out users. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSignUpMethod (NSString)</li>
+/// </ul>
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up";
+
+/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can
+/// help you identify which virtual goods are the most popular objects of purchase. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
+///     <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
+/// </ul>
+static NSString *const kFIREventSpendVirtualCurrency
+    NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency";
+
+/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use
+/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this
+/// process and move on to the full app experience.
+static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) =
+    @"tutorial_begin";
+
+/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding
+/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your
+/// on-boarding process.
+static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) =
+    @"tutorial_complete";
+
+/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your
+/// game. Since achievements generally represent the breadth of a gaming experience, this event can
+/// help you understand how many users are experiencing all that your game has to offer. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterAchievementID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) =
+    @"unlock_achievement";
+
+/// View Item event. This event signifies that a user has viewed an item. Use the appropriate
+/// parameters to contextualize the event. Use this event to discover the most popular items viewed
+/// in your app. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item";
+
+/// View Item List event. Log this event when a user sees a list of items or offerings. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterItemListID (NSString) (optional)</li>
+///     <li>@c kFIRParameterItemListName (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) =
+    @"view_item_list";
+
+/// View Search Results event. Log this event when the user has been presented with the results of a
+/// search. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSearchTerm (NSString)</li>
+/// </ul>
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) =
+    @"view_search_results";
+
+/// Add Shipping Info event. This event signifies that a user has submitted their shipping
+/// information. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterShippingTier (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddShippingInfo NS_SWIFT_NAME(AnalyticsEventAddShippingInfo) =
+    @"add_shipping_info";
+
+/// E-Commerce Purchase event. This event signifies that an item(s) was purchased by a user. Note:
+/// This is different from the in-app purchase event, which is reported automatically for App
+/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also supply
+/// the @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterAffiliation (NSString) (optional)</li>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterShipping (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTax (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventPurchase NS_SWIFT_NAME(AnalyticsEventPurchase) = @"purchase";
+
+/// E-Commerce Refund event. This event signifies that a refund was issued. Note: If you supply the
+/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency parameter so
+/// that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterAffiliation (NSString) (optional)</li>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterShipping (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTax (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventRefund NS_SWIFT_NAME(AnalyticsEventRefund) = @"refund";
+
+/// Select Item event. This event signifies that an item was selected by a user from a list. Use the
+/// appropriate parameters to contextualize the event. Use this event to discover the most popular
+/// items selected. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterItemListID (NSString) (optional)</li>
+///     <li>@c kFIRParameterItemListName (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventSelectItem NS_SWIFT_NAME(AnalyticsEventSelectItem) = @"select_item";
+
+/// Select promotion event. This event signifies that a user has selected a promotion offer. Use the
+/// appropriate parameters to contextualize the event, such as the item(s) for which the promotion
+/// applies. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCreativeName (NSString) (optional)</li>
+///     <li>@c kFIRParameterCreativeSlot (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPromotionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPromotionName (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventSelectPromotion NS_SWIFT_NAME(AnalyticsEventSelectPromotion) =
+    @"select_promotion";
+
+/// E-commerce View Cart event. This event signifies that a user has viewed their cart. Use this to
+/// analyze your purchase funnel. Note: If you supply the @c kFIRParameterValue parameter, you must
+/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventViewCart NS_SWIFT_NAME(AnalyticsEventViewCart) = @"view_cart";
+
+/// View Promotion event. This event signifies that a promotion was shown to a user. Add this event
+/// to a funnel with the @c kFIREventAddToCart and @c kFIREventPurchase to gauge your conversion
+/// process. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCreativeName (NSString) (optional)</li>
+///     <li>@c kFIRParameterCreativeSlot (NSString) (optional)</li>
+///     <li>@c kFIRParameterItems (NSArray) (optional)</li>
+///     <li>@c kFIRParameterLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPromotionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPromotionName (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventViewPromotion NS_SWIFT_NAME(AnalyticsEventViewPromotion) =
+    @"view_promotion";

+ 731 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h

@@ -0,0 +1,731 @@
+/// @file FIRParameterNames.h
+///
+/// Predefined event parameter names.
+///
+/// Params supply information that contextualize Events. You can associate up to 25 unique Params
+/// with each Event type. Some Params are suggested below for certain common Events, but you are
+/// not limited to these. You may supply extra Params for suggested Events or custom Params for
+/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric
+/// characters and underscores ("_"), and must start with an alphabetic character. Param values can
+/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and
+/// should not be used.
+
+#import <Foundation/Foundation.h>
+
+/// Game achievement ID (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) =
+    @"achievement_id";
+
+/// The ad format (e.g. Banner, Interstitial, Rewarded, Native, Rewarded Interstitial, Instream).
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdFormat : @"Banner",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdFormat NS_SWIFT_NAME(AnalyticsParameterAdFormat) =
+    @"ad_format";
+
+/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdNetworkClickID
+    NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid";
+
+/// The ad platform (e.g. MoPub, IronSource) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdPlatform : @"MoPub",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdPlatform NS_SWIFT_NAME(AnalyticsParameterAdPlatform) =
+    @"ad_platform";
+
+/// The ad source (e.g. AdColony) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdSource : @"AdColony",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdSource NS_SWIFT_NAME(AnalyticsParameterAdSource) =
+    @"ad_source";
+
+/// The ad unit name (e.g. Banner_03) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdUnitName : @"Banner_03",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdUnitName NS_SWIFT_NAME(AnalyticsParameterAdUnitName) =
+    @"ad_unit_name";
+
+/// A product affiliation to designate a supplying company or brick and mortar store location
+/// (NSString). <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) =
+    @"affiliation";
+
+/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to
+/// capture campaign information, otherwise can be populated by developer. Highly Recommended
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) =
+    @"campaign";
+
+/// Character used in game (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) =
+    @"character";
+
+/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// </pre>
+/// <b>This constant has been deprecated.</b>
+static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) =
+    @"checkout_step";
+
+/// Some option on a step in an ecommerce flow (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// </pre>
+/// <b>This constant has been deprecated.</b>
+static NSString *const kFIRParameterCheckoutOption
+    NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option";
+
+/// Campaign content (NSString).
+static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content";
+
+/// Type of content selected (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) =
+    @"content_type";
+
+/// Coupon code used for a purchase (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"SUMMER_FUN",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon";
+
+/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign.
+/// Use varies by network.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1";
+
+/// The name of a creative used in a promotional spot (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) =
+    @"creative_name";
+
+/// The name of a creative slot (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) =
+    @"creative_slot";
+
+/// Currency of the purchase or items associated with the event, in 3-letter
+/// <a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes"> ISO_4217</a> format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) =
+    @"currency";
+
+/// Flight or Travel destination (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) =
+    @"destination";
+
+/// The arrival date, check-out date or rental end date for the item. This should be in
+/// YYYY-MM-DD format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date";
+
+/// Flight number for travel events (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) =
+    @"flight_number";
+
+/// Group/clan/guild ID (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id";
+
+/// The index of the item in a list (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(5),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index";
+
+/// Item brand (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) =
+    @"item_brand";
+
+/// Item category (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"pants",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) =
+    @"item_category";
+
+/// Item ID (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"SKU_12345",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id";
+
+/// The Google <a href="https://developers.google.com/places/place-id">Place ID</a> (NSString) that
+/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// </pre>
+/// <b>This constant has been deprecated. Use @c kFIRParameterLocationID constant instead.</b>
+static NSString *const kFIRParameterItemLocationID
+    NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id";
+
+/// Item Name (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"jeggings",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) =
+    @"item_name";
+
+/// The list in which the item was presented to the user (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// </pre>
+/// <b>This constant has been deprecated. Use @c kFIRParameterItemListName constant instead.</b>
+static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) =
+    @"item_list";
+
+/// Item variant (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Black",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) =
+    @"item_variant";
+
+/// Level in game (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level";
+
+/// Location (NSString). The Google <a href="https://developers.google.com/places/place-id">Place ID
+/// </a> that corresponds to the associated event. Alternatively, you can supply your own custom
+/// Location ID.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) =
+    @"location";
+
+/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium";
+
+/// Number of nights staying at hotel (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfNights
+    NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights";
+
+/// Number of passengers traveling (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfPassengers
+    NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers";
+
+/// Number of rooms for travel events (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) =
+    @"number_of_rooms";
+
+/// Flight or Travel origin (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin";
+
+/// Purchase price (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price";
+
+/// Purchase quantity (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) =
+    @"quantity";
+
+/// Score in game (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score";
+
+/// Current screen class, such as the class name of the UIViewController, logged with screen_view
+/// event and added to every event (NSString). <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterScreenClass : @"LoginViewController",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterScreenClass NS_SWIFT_NAME(AnalyticsParameterScreenClass) =
+    @"screen_class";
+
+/// Current screen name, such as the name of the UIViewController, logged with screen_view event and
+/// added to every event (NSString). <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterScreenName : @"LoginView",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterScreenName NS_SWIFT_NAME(AnalyticsParameterScreenName) =
+    @"screen_name";
+
+/// The search string/keywords used (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) =
+    @"search_term";
+
+/// Shipping cost associated with a transaction (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(5.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $5.99 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) =
+    @"shipping";
+
+/// Sign up method (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// </pre>
+///
+/// <b>This constant has been deprecated. Use Method constant instead.</b>
+static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) =
+    @"sign_up_method";
+
+/// A particular approach used in an operation; for example, "facebook" or "email" in the context
+/// of a sign_up or login event.  (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method";
+
+/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban
+/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your
+/// property. Highly recommended (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source";
+
+/// The departure date, check-in date or rental start date for the item. This should be in
+/// YYYY-MM-DD format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) =
+    @"start_date";
+
+/// Tax cost associated with a transaction (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(2.43),
+///       kFIRParameterCurrency : @"USD",  // e.g. $2.43 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax";
+
+/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term";
+
+/// The unique identifier of a transaction (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"T12345",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) =
+    @"transaction_id";
+
+/// Travel class (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) =
+    @"travel_class";
+
+/// A context-specific numeric value which is accumulated automatically for each event type. This is
+/// a general purpose parameter that is useful for accumulating a key metric that pertains to an
+/// event. Examples include revenue, distance, time and points. Value should be specified as signed
+/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events
+/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be
+/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is
+/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the
+/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid
+/// <a href="https://goo.gl/qqX3J2">currency code</a> for conversion events will cause that
+/// conversion to be omitted from reporting.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value";
+
+/// Name of virtual currency type (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterVirtualCurrencyName
+    NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name";
+
+/// The name of a level in a game (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) =
+    @"level_name";
+
+/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned
+/// integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success";
+
+/// Indicates that the associated event should either extend the current session
+/// or start a new session if no session was active when the event was logged.
+/// Specify YES to extend the current session or to start a new session; any
+/// other value will not extend or start a session.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) =
+    @"extend_session";
+
+/// Monetary value of discount associated with a purchase (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterDiscount : @(2.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $2.00 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterDiscount NS_SWIFT_NAME(AnalyticsParameterDiscount) =
+    @"discount";
+
+/// Item Category (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory2 : @"pants",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory2 NS_SWIFT_NAME(AnalyticsParameterItemCategory2) =
+    @"item_category2";
+
+/// Item Category (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory3 : @"pants",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory3 NS_SWIFT_NAME(AnalyticsParameterItemCategory3) =
+    @"item_category3";
+
+/// Item Category (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory4 : @"pants",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory4 NS_SWIFT_NAME(AnalyticsParameterItemCategory4) =
+    @"item_category4";
+
+/// Item Category (context-specific) (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory5 : @"pants",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory5 NS_SWIFT_NAME(AnalyticsParameterItemCategory5) =
+    @"item_category5";
+
+/// The ID of the list in which the item was presented to the user (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemListID : @"ABC123",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemListID NS_SWIFT_NAME(AnalyticsParameterItemListID) =
+    @"item_list_id";
+
+/// The name of the list in which the item was presented to the user (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemListName : @"Related products",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemListName NS_SWIFT_NAME(AnalyticsParameterItemListName) =
+    @"item_list_name";
+
+/// The list of items involved in the transaction. (NSArray).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItems : @[
+///         @{kFIRParameterItemName : @"jeggings", kFIRParameterItemCategory : @"pants"},
+///         @{kFIRParameterItemName : @"boots", kFIRParameterItemCategory : @"shoes"},
+///       ],
+///     };
+/// </pre>
+static NSString *const kFIRParameterItems NS_SWIFT_NAME(AnalyticsParameterItems) = @"items";
+
+/// The location associated with the event. Preferred to be the Google
+/// <a href="https://developers.google.com/places/place-id">Place ID</a> that corresponds to the
+/// associated item but could be overridden to a custom location ID string.(NSString). <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLocationID NS_SWIFT_NAME(AnalyticsParameterLocationID) =
+    @"location_id";
+
+/// The chosen method of payment (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterPaymentType : @"Visa",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterPaymentType NS_SWIFT_NAME(AnalyticsParameterPaymentType) =
+    @"payment_type";
+
+/// The ID of a product promotion (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterPromotionID : @"ABC123",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterPromotionID NS_SWIFT_NAME(AnalyticsParameterPromotionID) =
+    @"promotion_id";
+
+/// The name of a product promotion (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterPromotionName : @"Summer Sale",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterPromotionName NS_SWIFT_NAME(AnalyticsParameterPromotionName) =
+    @"promotion_name";
+
+/// The shipping tier (e.g. Ground, Air, Next-day) selected for delivery of the purchased item
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterShippingTier : @"Ground",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterShippingTier NS_SWIFT_NAME(AnalyticsParameterShippingTier) =
+    @"shipping_tier";

+ 29 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h

@@ -0,0 +1,29 @@
+/// @file FIRUserPropertyNames.h
+///
+/// Predefined user property names.
+///
+/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can
+/// later analyze different behaviors of various segments of your userbase. You may supply up to 25
+/// unique UserProperties per app, and you can use the name and value of your choosing for each one.
+/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and
+/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to
+/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not
+/// be used.
+
+#import <Foundation/Foundation.h>
+
+/// The method used to sign in. For example, "google", "facebook" or "twitter".
+static NSString *const kFIRUserPropertySignUpMethod
+    NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method";
+
+/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user.
+/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the
+/// <a href="https://firebase.google.com/support/guides/disable-analytics">documentation</a> for
+/// more details and information about related settings.
+///
+/// <pre>
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// </pre>
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals
+    NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads";

+ 6 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h

@@ -0,0 +1,6 @@
+#import "FIRAnalytics+AppDelegate.h"
+#import "FIRAnalytics+Consent.h"
+#import "FIRAnalytics.h"
+#import "FIREventNames.h"
+#import "FIRParameterNames.h"
+#import "FIRUserPropertyNames.h"

+ 12 - 0
Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap

@@ -0,0 +1,12 @@
+framework module FirebaseAnalytics {
+  umbrella header "FirebaseAnalytics.h"
+  export *
+  module * { export * }
+  link "sqlite3"
+  link "z"
+  link framework "CoreData"
+  link framework "Security"
+  link framework "StoreKit"
+  link framework "SystemConfiguration"
+  link framework "UIKit"
+}

+ 56 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+/// Values stored in analyticsEnabledState. Never alter these constants since they must match with
+/// values persisted to disk.
+typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) {
+  // 0 is the default value for keys not found stored in persisted config, so it cannot represent
+  // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet.
+  kFIRAnalyticsEnabledStateNotSet = 0,
+  kFIRAnalyticsEnabledStateSetYes = 1,
+  kFIRAnalyticsEnabledStateSetNo = 2,
+};
+
+/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads
+/// measurementEnabledState using this same key.
+static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey =
+    @"/google/measurement/measurement_enabled_state";
+
+static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification =
+    @"FIRAnalyticsConfigurationSetEnabledNotification";
+static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification =
+    @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification";
+static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification =
+    @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification";
+
+@interface FIRAnalyticsConfiguration : NSObject
+
+/// Returns the shared instance of FIRAnalyticsConfiguration.
++ (FIRAnalyticsConfiguration *)sharedInstance;
+
+// Sets whether analytics collection is enabled for this app on this device. This setting is
+// persisted across app sessions. By default it is enabled.
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled;
+
+/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist
+/// the value or not. The setting should not be persisted if being set by the global data collection
+/// flag.
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled
+                       persistSetting:(BOOL)shouldPersist;
+
+@end

+ 62 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m

@@ -0,0 +1,62 @@
+// Copyright 2017 Google
+//
+// 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/Foundation.h>
+
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-implementations"
+@implementation FIRAnalyticsConfiguration
+#pragma clang diagnostic pop
+
++ (FIRAnalyticsConfiguration *)sharedInstance {
+  static FIRAnalyticsConfiguration *sharedInstance = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    sharedInstance = [[FIRAnalyticsConfiguration alloc] init];
+  });
+  return sharedInstance;
+}
+
+- (void)postNotificationName:(NSString *)name value:(id)value {
+  if (!name.length || !value) {
+    return;
+  }
+  [[NSNotificationCenter defaultCenter] postNotificationName:name
+                                                      object:self
+                                                    userInfo:@{name : value}];
+}
+
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled {
+  [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES];
+}
+
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled
+                       persistSetting:(BOOL)shouldPersist {
+  // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO.
+  FIRAnalyticsEnabledState analyticsEnabledState =
+      analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo;
+  if (shouldPersist) {
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    [userDefaults setObject:@(analyticsEnabledState)
+                     forKey:kFIRAPersistedConfigMeasurementEnabledStateKey];
+    [userDefaults synchronize];
+  }
+
+  [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification
+                       value:@(analyticsCollectionEnabled)];
+}
+
+@end

+ 860 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m

@@ -0,0 +1,860 @@
+// Copyright 2017 Google
+//
+// 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.
+
+#include <sys/utsname.h>
+
+#if __has_include(<UIKit/UIKit.h>)
+#import <UIKit/UIKit.h>
+#endif
+
+#if __has_include(<AppKit/AppKit.h>)
+#import <AppKit/AppKit.h>
+#endif
+
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRApp.h"
+
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
+#import "FirebaseCore/Sources/FIRBundleUtil.h"
+#import "FirebaseCore/Sources/FIRComponentContainerInternal.h"
+#import "FirebaseCore/Sources/FIRConfigurationInternal.h"
+#import "FirebaseCore/Sources/FIRFirebaseUserAgent.h"
+
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+#import "FirebaseCore/Sources/Private/FIRLogger.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h"
+
+#import <GoogleUtilities/GULAppEnvironmentUtil.h>
+
+#import <objc/runtime.h>
+
+// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics
+// pod to a Core dependency. These symbols are not used and should be deleted after the transition.
+NSString *const kFIRServiceAdMob;
+NSString *const kFIRServiceAuth;
+NSString *const kFIRServiceAuthUI;
+NSString *const kFIRServiceCrash;
+NSString *const kFIRServiceDatabase;
+NSString *const kFIRServiceDynamicLinks;
+NSString *const kFIRServiceFirestore;
+NSString *const kFIRServiceFunctions;
+NSString *const kFIRServiceInstanceID;
+NSString *const kFIRServiceInvites;
+NSString *const kFIRServiceMessaging;
+NSString *const kFIRServiceMeasurement;
+NSString *const kFIRServicePerformance;
+NSString *const kFIRServiceRemoteConfig;
+NSString *const kFIRServiceStorage;
+NSString *const kGGLServiceAnalytics;
+NSString *const kGGLServiceSignIn;
+
+NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT";
+NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification";
+NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification";
+NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey";
+NSString *const kFIRAppNameKey = @"FIRAppNameKey";
+NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey";
+
+NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat =
+    @"/google/firebase/global_data_collection_enabled:%@";
+NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey =
+    @"FirebaseDataCollectionDefaultEnabled";
+
+NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification";
+
+NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType";
+NSString *const kFIRAppDiagnosticsErrorKey = @"Error";
+NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp";
+NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName";
+NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion";
+NSString *const kFIRAppDiagnosticsApplePlatformPrefix = @"apple-platform";
+
+// Auth internal notification notification and key.
+NSString *const FIRAuthStateDidChangeInternalNotification =
+    @"FIRAuthStateDidChangeInternalNotification";
+NSString *const FIRAuthStateDidChangeInternalNotificationAppKey =
+    @"FIRAuthStateDidChangeInternalNotificationAppKey";
+NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey =
+    @"FIRAuthStateDidChangeInternalNotificationTokenKey";
+NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey =
+    @"FIRAuthStateDidChangeInternalNotificationUIDKey";
+
+/**
+ * Error domain for exceptions and NSError construction.
+ */
+NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core";
+
+/**
+ * The URL to download plist files.
+ */
+static NSString *const kPlistURL = @"https://console.firebase.google.com/";
+
+/**
+ * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle
+ * events from Core.
+ */
+static NSMutableArray<Class<FIRLibrary>> *sRegisteredAsConfigurable;
+
+@interface FIRApp ()
+
+#ifdef DEBUG
+@property(nonatomic) BOOL alreadyOutputDataCollectionFlag;
+#endif  // DEBUG
+
+@end
+
+@implementation FIRApp
+
+// This is necessary since our custom getter prevents `_options` from being created.
+@synthesize options = _options;
+
+static NSMutableDictionary *sAllApps;
+static FIRApp *sDefaultApp;
+
++ (void)configure {
+  FIROptions *options = [FIROptions defaultOptions];
+  if (!options) {
+    [NSException raise:kFirebaseCoreErrorDomain
+                format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find "
+                       @"a valid GoogleService-Info.plist in your project. Please download one "
+                       @"from %@.",
+                       kPlistURL];
+  }
+  [FIRApp configureWithOptions:options];
+#if TARGET_OS_OSX || TARGET_OS_TV
+  FIRLogNotice(kFIRLoggerCore, @"I-COR000028",
+               @"tvOS and macOS SDK support is not part of the official Firebase product. "
+               @"Instead they are community supported. Details at "
+               @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md.");
+#endif
+}
+
++ (void)configureWithOptions:(FIROptions *)options {
+  if (!options) {
+    [NSException raise:kFirebaseCoreErrorDomain
+                format:@"Options is nil. Please pass a valid options."];
+  }
+  [FIRApp configureWithName:kFIRDefaultAppName options:options];
+}
+
++ (NSCharacterSet *)applicationNameAllowedCharacters {
+  static NSCharacterSet *applicationNameAllowedCharacters;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    NSMutableCharacterSet *allowedNameCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
+    [allowedNameCharacters addCharactersInString:@"-_"];
+    applicationNameAllowedCharacters = [allowedNameCharacters copy];
+  });
+  return applicationNameAllowedCharacters;
+}
+
++ (void)configureWithName:(NSString *)name options:(FIROptions *)options {
+  if (!name || !options) {
+    [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."];
+  }
+  if (name.length == 0) {
+    [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."];
+  }
+
+  if ([name isEqualToString:kFIRDefaultAppName]) {
+    if (sDefaultApp) {
+      // The default app already exists. Handle duplicate `configure` calls and return.
+      [self appWasConfiguredTwice:sDefaultApp usingOptions:options];
+      return;
+    }
+
+    FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app.");
+  } else {
+    // Validate the app name and ensure it hasn't been configured already.
+    NSCharacterSet *nameCharacters = [NSCharacterSet characterSetWithCharactersInString:name];
+
+    if (![[self applicationNameAllowedCharacters] isSupersetOfSet:nameCharacters]) {
+      [NSException raise:kFirebaseCoreErrorDomain
+                  format:@"App name can only contain alphanumeric, "
+                         @"hyphen (-), and underscore (_) characters"];
+    }
+
+    @synchronized(self) {
+      if (sAllApps && sAllApps[name]) {
+        // The app already exists. Handle a duplicate `configure` call and return.
+        [self appWasConfiguredTwice:sAllApps[name] usingOptions:options];
+        return;
+      }
+    }
+
+    FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name);
+  }
+
+  @synchronized(self) {
+    FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options];
+    if (app.isDefaultApp) {
+      sDefaultApp = app;
+    }
+
+    [FIRApp addAppToAppDictionary:app];
+
+    // The FIRApp instance is ready to go, `sDefaultApp` is assigned, other SDKs are now ready to be
+    // instantiated.
+    [app.container instantiateEagerComponents];
+    [FIRApp sendNotificationsToSDKs:app];
+  }
+}
+
+/// Called when `configure` has been called multiple times for the same app. This can either throw
+/// an exception (most cases) or ignore the duplicate configuration in situations where it's allowed
+/// like an extension.
++ (void)appWasConfiguredTwice:(FIRApp *)app usingOptions:(FIROptions *)options {
+  // Only extensions should potentially be able to call `configure` more than once.
+  if (![GULAppEnvironmentUtil isAppExtension]) {
+    // Throw an exception since this is now an invalid state.
+    if (app.isDefaultApp) {
+      [NSException raise:kFirebaseCoreErrorDomain
+                  format:@"Default app has already been configured."];
+    } else {
+      [NSException raise:kFirebaseCoreErrorDomain
+                  format:@"App named %@ has already been configured.", app.name];
+    }
+  }
+
+  // In an extension, the entry point could be called multiple times. As long as the options are
+  // identical we should allow multiple `configure` calls.
+  if ([options isEqual:app.options]) {
+    // Everything is identical but the extension's lifecycle triggered `configure` twice.
+    // Ignore duplicate calls and return since everything should still be in a valid state.
+    FIRLogDebug(kFIRLoggerCore, @"I-COR000035",
+                @"Ignoring second `configure` call in an extension.");
+    return;
+  } else {
+    [NSException raise:kFirebaseCoreErrorDomain
+                format:@"App named %@ has already been configured.", app.name];
+  }
+}
+
++ (FIRApp *)defaultApp {
+  if (sDefaultApp) {
+    return sDefaultApp;
+  }
+  FIRLogError(kFIRLoggerCore, @"I-COR000003",
+              @"The default Firebase app has not yet been "
+              @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your "
+              @"application initialization. Read more: https://goo.gl/ctyzm8.");
+  return nil;
+}
+
++ (FIRApp *)appNamed:(NSString *)name {
+  @synchronized(self) {
+    if (sAllApps) {
+      FIRApp *app = sAllApps[name];
+      if (app) {
+        return app;
+      }
+    }
+    FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name);
+    return nil;
+  }
+}
+
++ (NSDictionary *)allApps {
+  @synchronized(self) {
+    if (!sAllApps) {
+      FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet.");
+    }
+    return [sAllApps copy];
+  }
+}
+
+// Public only for tests
++ (void)resetApps {
+  @synchronized(self) {
+    sDefaultApp = nil;
+    [sAllApps removeAllObjects];
+    sAllApps = nil;
+    [[self userAgent] reset];
+  }
+}
+
+- (void)deleteApp:(FIRAppVoidBoolCallback)completion {
+  @synchronized([self class]) {
+    if (sAllApps && sAllApps[self.name]) {
+      FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name);
+
+      // Remove all registered libraries from the container to avoid creating new instances.
+      [self.container removeAllComponents];
+      // Remove all cached instances from the container before deleting the app.
+      [self.container removeAllCachedInstances];
+
+      [sAllApps removeObjectForKey:self.name];
+      [self clearDataCollectionSwitchFromUserDefaults];
+      if ([self.name isEqualToString:kFIRDefaultAppName]) {
+        sDefaultApp = nil;
+      }
+      NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name};
+      [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification
+                                                          object:[self class]
+                                                        userInfo:appInfoDict];
+      completion(YES);
+    } else {
+      FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist.");
+      completion(NO);
+    }
+  }
+}
+
++ (void)addAppToAppDictionary:(FIRApp *)app {
+  if (!sAllApps) {
+    sAllApps = [NSMutableDictionary dictionary];
+  }
+  if ([app configureCore]) {
+    sAllApps[app.name] = app;
+  } else {
+    [NSException raise:kFirebaseCoreErrorDomain
+                format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in "
+                       @"GoogleService-Info.plist or set in the customized options."];
+  }
+}
+
+- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options {
+  self = [super init];
+  if (self) {
+    _name = [name copy];
+    _options = [options copy];
+    _options.editingLocked = YES;
+    _isDefaultApp = [name isEqualToString:kFIRDefaultAppName];
+    _container = [[FIRComponentContainer alloc] initWithApp:self];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (BOOL)configureCore {
+  [self checkExpectedBundleID];
+  if (![self isAppIDValid]) {
+    return NO;
+  }
+
+  [self logCoreTelemetryIfEnabled];
+
+#if TARGET_OS_IOS
+  // Initialize the Analytics once there is a valid options under default app. Analytics should
+  // always initialize first by itself before the other SDKs.
+  if ([self.name isEqualToString:kFIRDefaultAppName]) {
+    Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics");
+    if (firAnalyticsClass) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+      SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:);
+#pragma clang diagnostic pop
+      if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+        [firAnalyticsClass performSelector:startWithConfigurationSelector
+                                withObject:[FIRConfiguration sharedInstance].analyticsConfiguration
+                                withObject:_options];
+#pragma clang diagnostic pop
+      }
+    }
+  }
+#endif
+
+  [self subscribeForAppDidBecomeActiveNotifications];
+
+  return YES;
+}
+
+- (FIROptions *)options {
+  return [_options copy];
+}
+
+- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled {
+#ifdef DEBUG
+  FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.",
+              dataCollectionDefaultEnabled ? @"enabled" : @"disabled");
+  self.alreadyOutputDataCollectionFlag = YES;
+#endif  // DEBUG
+
+  NSString *key =
+      [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name];
+  [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key];
+
+  // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set
+  // within FIROptions and change the Analytics value if necessary. Analytics only works with the
+  // default app, so return if this isn't the default app.
+  if (!self.isDefaultApp) {
+    return;
+  }
+
+  // Check if the Analytics flag is explicitly set. If so, no further actions are necessary.
+  if ([self.options isAnalyticsCollectionExplicitlySet]) {
+    return;
+  }
+
+  // The Analytics flag has not been explicitly set, so update with the value being set.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  [[FIRAnalyticsConfiguration sharedInstance]
+      setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled
+                     persistSetting:NO];
+#pragma clang diagnostic pop
+}
+
+- (BOOL)isDataCollectionDefaultEnabled {
+  // Check if it's been manually set before in code, and use that as the higher priority value.
+  NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self];
+  if (defaultsObject != nil) {
+#ifdef DEBUG
+    if (!self.alreadyOutputDataCollectionFlag) {
+      FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.",
+                  [defaultsObject boolValue] ? @"enabled" : @"disabled");
+      self.alreadyOutputDataCollectionFlag = YES;
+    }
+#endif  // DEBUG
+    return [defaultsObject boolValue];
+  }
+
+  // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`.
+  // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has
+  // no performance impact calling multiple times.
+  NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist];
+  if (collectionEnabledPlistValue != nil) {
+#ifdef DEBUG
+    if (!self.alreadyOutputDataCollectionFlag) {
+      FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.",
+                  [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled");
+      self.alreadyOutputDataCollectionFlag = YES;
+    }
+#endif  // DEBUG
+    return [collectionEnabledPlistValue boolValue];
+  }
+
+#ifdef DEBUG
+  if (!self.alreadyOutputDataCollectionFlag) {
+    FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set.");
+    self.alreadyOutputDataCollectionFlag = YES;
+  }
+#endif  // DEBUG
+  return YES;
+}
+
+#pragma mark - private
+
++ (void)sendNotificationsToSDKs:(FIRApp *)app {
+  // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`.
+  NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp];
+  NSDictionary *appInfoDict = @{
+    kFIRAppNameKey : app.name,
+    kFIRAppIsDefaultAppKey : isDefaultApp,
+    kFIRGoogleAppIDKey : app.options.googleAppID
+  };
+  [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification
+                                                      object:self
+                                                    userInfo:appInfoDict];
+
+  // This is the new way of sending information to SDKs.
+  // TODO: Do we want this on a background thread, maybe?
+  @synchronized(self) {
+    for (Class<FIRLibrary> library in sRegisteredAsConfigurable) {
+      [library configureWithApp:app];
+    }
+  }
+}
+
++ (NSError *)errorForMissingOptions {
+  NSDictionary *errorDict = @{
+    NSLocalizedDescriptionKey :
+        @"Unable to parse GoogleService-Info.plist in order to configure services.",
+    NSLocalizedRecoverySuggestionErrorKey :
+        @"Check formatting and location of GoogleService-Info.plist."
+  };
+  return [NSError errorWithDomain:kFirebaseCoreErrorDomain code:-100 userInfo:errorDict];
+}
+
++ (NSError *)errorForInvalidAppID {
+  NSDictionary *errorDict = @{
+    NSLocalizedDescriptionKey : @"Unable to validate Google App ID",
+    NSLocalizedRecoverySuggestionErrorKey :
+        @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the "
+        @"customized options."
+  };
+  return [NSError errorWithDomain:kFirebaseCoreErrorDomain code:-101 userInfo:errorDict];
+}
+
++ (BOOL)isDefaultAppConfigured {
+  return (sDefaultApp != nil);
+}
+
++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version {
+  // Create the set of characters which aren't allowed, only if this feature is used.
+  NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet];
+  [allowedSet addCharactersInString:@"-_."];
+  NSCharacterSet *disallowedSet = [allowedSet invertedSet];
+  // Make sure the library name and version strings do not contain unexpected characters, and
+  // add the name/version pair to the dictionary.
+  if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound &&
+      [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) {
+    [[self userAgent] setValue:version forComponent:name];
+  } else {
+    FIRLogError(kFIRLoggerCore, @"I-COR000027",
+                @"The library name (%@) or version number (%@) contain invalid characters. "
+                @"Only alphanumeric, dash, underscore and period characters are allowed.",
+                name, version);
+  }
+}
+
++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
+                       withName:(nonnull NSString *)name {
+  [self registerInternalLibrary:library withName:name withVersion:FIRFirebaseVersion()];
+}
+
++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
+                       withName:(nonnull NSString *)name
+                    withVersion:(nonnull NSString *)version {
+  // This is called at +load time, keep the work to a minimum.
+
+  // Ensure the class given conforms to the proper protocol.
+  if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] ||
+      ![(Class)library respondsToSelector:@selector(componentsToRegister)]) {
+    [NSException raise:NSInvalidArgumentException
+                format:@"Class %@ attempted to register components, but it does not conform to "
+                       @"`FIRLibrary or provide a `componentsToRegister:` method.",
+                       library];
+  }
+
+  [FIRComponentContainer registerAsComponentRegistrant:library];
+  if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) {
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+      sRegisteredAsConfigurable = [[NSMutableArray alloc] init];
+    });
+    @synchronized(self) {
+      [sRegisteredAsConfigurable addObject:library];
+    }
+  }
+  [self registerLibrary:name withVersion:version];
+}
+
++ (FIRFirebaseUserAgent *)userAgent {
+  static dispatch_once_t onceToken;
+  static FIRFirebaseUserAgent *_userAgent;
+  dispatch_once(&onceToken, ^{
+    _userAgent = [[FIRFirebaseUserAgent alloc] init];
+    [_userAgent setValue:FIRFirebaseVersion() forComponent:@"fire-ios"];
+  });
+  return _userAgent;
+}
+
++ (NSString *)firebaseUserAgent {
+  return [[self userAgent] firebaseUserAgent];
+}
+
+- (void)checkExpectedBundleID {
+  NSArray *bundles = [FIRBundleUtil relevantBundles];
+  NSString *expectedBundleID = [self expectedBundleID];
+  // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for
+  // backward compatibility.
+  if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID
+                                                                 inBundles:bundles]) {
+    FIRLogError(kFIRLoggerCore, @"I-COR000008",
+                @"The project's Bundle ID is inconsistent with "
+                @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are "
+                @"using a customized options. To ensure that everything can be configured "
+                @"correctly, you may need to make the Bundle IDs consistent. To continue with this "
+                @"plist file, you may change your app's bundle identifier to '%@'. Or you can "
+                @"download a new configuration file that matches your bundle identifier from %@ "
+                @"and replace the current one.",
+                kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL);
+  }
+}
+
+#pragma mark - private - App ID Validation
+
+/**
+ * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file.
+ * This is the main method for validating app ID.
+ *
+ * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise.
+ */
+- (BOOL)isAppIDValid {
+  NSString *appID = _options.googleAppID;
+  BOOL isValid = [FIRApp validateAppID:appID];
+  if (!isValid) {
+    NSString *expectedBundleID = [self expectedBundleID];
+    FIRLogError(kFIRLoggerCore, @"I-COR000009",
+                @"The GOOGLE_APP_ID either in the plist file "
+                @"'%@.%@' or the one set in the customized options is invalid. If you are using "
+                @"the plist file, use the iOS version of bundle identifier to download the file, "
+                @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle "
+                @"identifier to '%@'. Or you can download a new configuration file that matches "
+                @"your bundle identifier from %@ and replace the current one.",
+                kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL);
+  };
+  return isValid;
+}
+
++ (BOOL)validateAppID:(NSString *)appID {
+  // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not
+  // have a valid fingerprint, otherwise we just warn about the potential issue.
+  if (!appID.length) {
+    return NO;
+  }
+
+  NSScanner *stringScanner = [NSScanner scannerWithString:appID];
+  stringScanner.charactersToBeSkipped = nil;
+
+  NSString *appIDVersion;
+  if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet]
+                                 intoString:&appIDVersion]) {
+    return NO;
+  }
+
+  if (![stringScanner scanString:@":" intoString:NULL]) {
+    // appIDVersion must be separated by ":"
+    return NO;
+  }
+
+  NSArray *knownVersions = @[ @"1" ];
+  if (![knownVersions containsObject:appIDVersion]) {
+    // Permit unknown yet properly formatted app ID versions.
+    FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion);
+    return YES;
+  }
+
+  if (![self validateAppIDFormat:appID withVersion:appIDVersion]) {
+    return NO;
+  }
+
+  if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) {
+    return NO;
+  }
+
+  return YES;
+}
+
++ (NSString *)actualBundleID {
+  return [[NSBundle mainBundle] bundleIdentifier];
+}
+
+/**
+ * Validates that the format of the app ID string is what is expected based on the supplied version.
+ * The version must end in ":".
+ *
+ * For v1 app ids the format is expected to be
+ * '<version #>:<project number>:ios:<fingerprint of bundle id>'.
+ *
+ * This method does not verify that the contents of the app id are correct, just that they fulfill
+ * the expected format.
+ *
+ * @param appID Contents of GOOGLE_APP_ID from the plist file.
+ * @param version Indicates what version of the app id format this string should be.
+ * @return YES if provided string fufills the expected format, NO otherwise.
+ */
++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version {
+  if (!appID.length || !version.length) {
+    return NO;
+  }
+
+  NSScanner *stringScanner = [NSScanner scannerWithString:appID];
+  stringScanner.charactersToBeSkipped = nil;
+
+  // Skip version part
+  // '*<version #>*:<project number>:ios:<fingerprint of bundle id>'
+  if (![stringScanner scanString:version intoString:NULL]) {
+    // The version part is missing or mismatched
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>*:*<project number>:ios:<fingerprint of bundle id>'
+  if (![stringScanner scanString:@":" intoString:NULL]) {
+    // appIDVersion must be separated by ":"
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>:*<project number>*:ios:<fingerprint of bundle id>'.
+  NSInteger projectNumber = NSNotFound;
+  if (![stringScanner scanInteger:&projectNumber]) {
+    // NO project number found.
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>:<project number>*:*ios:<fingerprint of bundle id>'.
+  if (![stringScanner scanString:@":" intoString:NULL]) {
+    // The project number must be separated by ":"
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>:<project number>:*ios*:<fingerprint of bundle id>'.
+  NSString *platform;
+  if (![stringScanner scanUpToString:@":" intoString:&platform]) {
+    return NO;
+  }
+
+  if (![platform isEqualToString:@"ios"]) {
+    // The platform must be @"ios"
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>:<project number>:ios*:*<fingerprint of bundle id>'.
+  if (![stringScanner scanString:@":" intoString:NULL]) {
+    // The platform must be separated by ":"
+    return NO;
+  }
+
+  // Validate version part (see part between '*' symbols below)
+  // '<version #>:<project number>:ios:*<fingerprint of bundle id>*'.
+  unsigned long long fingerprint = NSNotFound;
+  if (![stringScanner scanHexLongLong:&fingerprint]) {
+    // Fingerprint part is missing
+    return NO;
+  }
+
+  if (!stringScanner.isAtEnd) {
+    // There are not allowed characters in the fingerprint part
+    return NO;
+  }
+
+  return YES;
+}
+
+/**
+ * Validates that the fingerprint of the app ID string is what is expected based on the supplied
+ * version.
+ *
+ * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated.
+ *
+ * @param appID Contents of GOOGLE_APP_ID from the plist file.
+ * @param version Indicates what version of the app id format this string should be.
+ * @return YES if provided string fufills the expected fingerprint and the version is known, NO
+ *         otherwise.
+ */
++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version {
+  // Extract the supplied fingerprint from the supplied app ID.
+  // This assumes the app ID format is the same for all known versions below. If the app ID format
+  // changes in future versions, the tokenizing of the app ID format will need to take into account
+  // the version of the app ID.
+  NSArray *components = [appID componentsSeparatedByString:@":"];
+  if (components.count != 4) {
+    return NO;
+  }
+
+  NSString *suppliedFingerprintString = components[3];
+  if (!suppliedFingerprintString.length) {
+    return NO;
+  }
+
+  uint64_t suppliedFingerprint;
+  NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString];
+  if (![scanner scanHexLongLong:&suppliedFingerprint]) {
+    return NO;
+  }
+
+  if ([version isEqual:@"1"]) {
+    // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated.
+    return YES;
+  }
+
+  // Unknown version.
+  return NO;
+}
+
+- (NSString *)expectedBundleID {
+  return _options.bundleID;
+}
+
+// end App ID validation
+
+#pragma mark - Reading From Plist & User Defaults
+
+/**
+ * Clears the data collection switch from the standard NSUserDefaults for easier testing and
+ * readability.
+ */
+- (void)clearDataCollectionSwitchFromUserDefaults {
+  NSString *key =
+      [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name];
+  [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
+}
+
+/**
+ * Reads the data collection switch from the standard NSUserDefaults for easier testing and
+ * readability.
+ */
++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app {
+  // Read the object in user defaults, and only return if it's an NSNumber.
+  NSString *key =
+      [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name];
+  id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key];
+  if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) {
+    return collectionEnabledDefaultsObject;
+  }
+
+  return nil;
+}
+
+/**
+ * Reads the data collection switch from the Info.plist for easier testing and readability. Will
+ * only read once from the plist and return the cached value.
+ */
++ (nullable NSNumber *)readDataCollectionSwitchFromPlist {
+  static NSNumber *collectionEnabledPlistObject;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber.
+    id plistValue = [[NSBundle mainBundle]
+        objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey];
+    if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) {
+      collectionEnabledPlistObject = (NSNumber *)plistValue;
+    }
+  });
+
+  return collectionEnabledPlistObject;
+}
+
+#pragma mark - App Life Cycle
+
+- (void)subscribeForAppDidBecomeActiveNotifications {
+#if TARGET_OS_IOS || TARGET_OS_TV
+  NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification;
+#elif TARGET_OS_OSX
+  NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification;
+#endif
+
+#if !TARGET_OS_WATCH
+  [[NSNotificationCenter defaultCenter] addObserver:self
+                                           selector:@selector(appDidBecomeActive:)
+                                               name:notificationName
+                                             object:nil];
+#endif
+}
+
+- (void)appDidBecomeActive:(NSNotification *)notification {
+  [self logCoreTelemetryIfEnabled];
+}
+
+- (void)logCoreTelemetryIfEnabled {
+  if ([self isDataCollectionDefaultEnabled]) {
+    [FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options];
+  }
+}
+
+@end

+ 49 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+//  TODO: Remove this once Auth moves over to Core's instance registration system.
+/** @class FIRAppAssociationRegistration
+    @brief Manages object associations as a singleton-dependent: At most one object is
+        registered for any given host/key pair, and the object shall be created on-the-fly when
+        asked for.
+ */
+@interface FIRAppAssociationRegistration<ObjectType> : NSObject
+
+/** @fn registeredObjectWithHost:key:creationBlock:
+    @brief Retrieves the registered object with a particular host and key.
+    @param host The host object.
+    @param key The key to specify the registered object on the host.
+    @param creationBlock The block to return the object to be registered if not already.
+        The block is executed immediately before this method returns if it is executed at all.
+        It can also be executed multiple times across different method invocations if previous
+        execution of the block returns @c nil.
+    @return The registered object for the host/key pair, or @c nil if no object is registered
+        and @c creationBlock returns @c nil.
+    @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this
+        method again within the @c creationBlock with the same host/key pair raises an exception.
+        The registered object is retained by the host.
+ */
++ (nullable ObjectType)registeredObjectWithHost:(id)host
+                                            key:(NSString *)key
+                                  creationBlock:(ObjectType _Nullable (^)(void))creationBlock;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 47 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m

@@ -0,0 +1,47 @@
+// Copyright 2017 Google
+//
+// 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 "FirebaseCore/Sources/FIRAppAssociationRegistration.h"
+
+#import <objc/runtime.h>
+
+@implementation FIRAppAssociationRegistration
+
++ (nullable id)registeredObjectWithHost:(id)host
+                                    key:(NSString *)key
+                          creationBlock:(id _Nullable (^)(void))creationBlock {
+  @synchronized(self) {
+    SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:);
+    NSMutableDictionary<NSString *, id> *objectsByKey = objc_getAssociatedObject(host, dictKey);
+    if (!objectsByKey) {
+      objectsByKey = [[NSMutableDictionary alloc] init];
+      objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    id obj = objectsByKey[key];
+    NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey];
+    if (obj) {
+      if ([creationBlockBeingCalled isEqual:obj]) {
+        [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed"
+                    format:@"host: %@ key: %@", host, key];
+      }
+      return obj;
+    }
+    objectsByKey[key] = creationBlockBeingCalled;
+    obj = creationBlock();
+    objectsByKey[key] = obj;
+    return obj;
+  }
+}
+
+@end

+ 53 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h

@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+/**
+ * This class provides utilities for accessing resources in bundles.
+ */
+@interface FIRBundleUtil : NSObject
+
+/**
+ * Finds all relevant bundles, starting with [NSBundle mainBundle].
+ */
++ (NSArray *)relevantBundles;
+
+/**
+ * Reads the options dictionary from one of the provided bundles.
+ *
+ * @param resourceName The resource name, e.g. @"GoogleService-Info".
+ * @param fileType The file type (extension), e.g. @"plist".
+ * @param bundles The bundles to expect, in priority order. See also
+ * +[FIRBundleUtil relevantBundles].
+ */
++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName
+                                        andFileType:(NSString *)fileType
+                                          inBundles:(NSArray *)bundles;
+
+/**
+ * Finds URL schemes defined in all relevant bundles, starting with those from
+ * [NSBundle mainBundle].
+ */
++ (NSArray *)relevantURLSchemes;
+
+/**
+ * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension
+ * suffixes).
+ */
++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles;
+
+@end

+ 79 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m

@@ -0,0 +1,79 @@
+// Copyright 2017 Google
+//
+// 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 "FirebaseCore/Sources/FIRBundleUtil.h"
+
+#import <GoogleUtilities/GULAppEnvironmentUtil.h>
+
+@implementation FIRBundleUtil
+
++ (NSArray *)relevantBundles {
+  return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ];
+}
+
++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName
+                                        andFileType:(NSString *)fileType
+                                          inBundles:(NSArray *)bundles {
+  // Loop through all bundles to find the config dict.
+  for (NSBundle *bundle in bundles) {
+    NSString *path = [bundle pathForResource:resourceName ofType:fileType];
+    // Use the first one we find.
+    if (path) {
+      return path;
+    }
+  }
+  return nil;
+}
+
++ (NSArray *)relevantURLSchemes {
+  NSMutableArray *result = [[NSMutableArray alloc] init];
+  for (NSBundle *bundle in [[self class] relevantBundles]) {
+    NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"];
+    for (NSDictionary *urlType in urlTypes) {
+      [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]];
+    }
+  }
+  return result;
+}
+
++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles {
+  for (NSBundle *bundle in bundles) {
+    if ([bundle.bundleIdentifier isEqualToString:bundleIdentifier]) {
+      return YES;
+    }
+
+    if ([GULAppEnvironmentUtil isAppExtension]) {
+      // A developer could be using the same `FIROptions` for both their app and extension. Since
+      // extensions have a suffix added to the bundleID, we consider a matching prefix as valid.
+      NSString *appBundleIDFromExtension =
+          [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier];
+      if ([appBundleIDFromExtension isEqualToString:bundleIdentifier]) {
+        return YES;
+      }
+    }
+  }
+  return NO;
+}
+
++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier {
+  NSString *bundleIDComponentsSeparator = @".";
+
+  NSMutableArray<NSString *> *bundleIDComponents =
+      [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy];
+  [bundleIDComponents removeLastObject];
+
+  return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator];
+}
+
+@end

+ 65 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m

@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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 "FirebaseCore/Sources/Private/FIRComponent.h"
+
+#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
+#import "FirebaseCore/Sources/Private/FIRDependency.h"
+
+@interface FIRComponent ()
+
+- (instancetype)initWithProtocol:(Protocol *)protocol
+             instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+                    dependencies:(NSArray<FIRDependency *> *)dependencies
+                   creationBlock:(FIRComponentCreationBlock)creationBlock;
+
+@end
+
+@implementation FIRComponent
+
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+                        creationBlock:(FIRComponentCreationBlock)creationBlock {
+  return [[FIRComponent alloc] initWithProtocol:protocol
+                            instantiationTiming:FIRInstantiationTimingLazy
+                                   dependencies:@[]
+                                  creationBlock:creationBlock];
+}
+
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+                  instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+                         dependencies:(NSArray<FIRDependency *> *)dependencies
+                        creationBlock:(FIRComponentCreationBlock)creationBlock {
+  return [[FIRComponent alloc] initWithProtocol:protocol
+                            instantiationTiming:instantiationTiming
+                                   dependencies:dependencies
+                                  creationBlock:creationBlock];
+}
+
+- (instancetype)initWithProtocol:(Protocol *)protocol
+             instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+                    dependencies:(NSArray<FIRDependency *> *)dependencies
+                   creationBlock:(FIRComponentCreationBlock)creationBlock {
+  self = [super init];
+  if (self) {
+    _protocol = protocol;
+    _instantiationTiming = instantiationTiming;
+    _dependencies = [dependencies copy];
+    _creationBlock = creationBlock;
+  }
+  return self;
+}
+
+@end

+ 214 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m

@@ -0,0 +1,214 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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 "FirebaseCore/Sources/Private/FIRComponentContainer.h"
+
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIRComponent.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+#import "FirebaseCore/Sources/Private/FIRLogger.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRComponentContainer ()
+
+/// The dictionary of components that are registered for a particular app. The key is an `NSString`
+/// of the protocol.
+@property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
+
+/// Cached instances of components that requested to be cached.
+@property(nonatomic, strong) NSMutableDictionary<NSString *, id> *cachedInstances;
+
+/// Protocols of components that have requested to be eagerly instantiated.
+@property(nonatomic, strong, nullable) NSMutableArray<Protocol *> *eagerProtocolsToInstantiate;
+
+@end
+
+@implementation FIRComponentContainer
+
+// Collection of all classes that register to provide components.
+static NSMutableSet<Class> *sFIRComponentRegistrants;
+
+#pragma mark - Public Registration
+
++ (void)registerAsComponentRegistrant:(Class<FIRLibrary>)klass {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    sFIRComponentRegistrants = [[NSMutableSet<Class> alloc] init];
+  });
+
+  [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants];
+}
+
++ (void)registerAsComponentRegistrant:(Class<FIRLibrary>)klass
+                                inSet:(NSMutableSet<Class> *)allRegistrants {
+  [allRegistrants addObject:klass];
+}
+
+#pragma mark - Internal Initialization
+
+- (instancetype)initWithApp:(FIRApp *)app {
+  return [self initWithApp:app registrants:sFIRComponentRegistrants];
+}
+
+- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet<Class> *)allRegistrants {
+  self = [super init];
+  if (self) {
+    _app = app;
+    _cachedInstances = [NSMutableDictionary<NSString *, id> dictionary];
+    _components = [NSMutableDictionary<NSString *, FIRComponentCreationBlock> dictionary];
+
+    [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app];
+  }
+  return self;
+}
+
+- (void)populateComponentsFromRegisteredClasses:(NSSet<Class> *)classes forApp:(FIRApp *)app {
+  // Keep track of any components that need to eagerly instantiate after all components are added.
+  self.eagerProtocolsToInstantiate = [[NSMutableArray alloc] init];
+
+  // Loop through the verified component registrants and populate the components array.
+  for (Class<FIRLibrary> klass in classes) {
+    // Loop through all the components being registered and store them as appropriate.
+    // Classes which do not provide functionality should use a dummy FIRComponentRegistrant
+    // protocol.
+    for (FIRComponent *component in [klass componentsToRegister]) {
+      // Check if the component has been registered before, and error out if so.
+      NSString *protocolName = NSStringFromProtocol(component.protocol);
+      if (self.components[protocolName]) {
+        FIRLogError(kFIRLoggerCore, @"I-COR000029",
+                    @"Attempted to register protocol %@, but it already has an implementation.",
+                    protocolName);
+        continue;
+      }
+
+      // Store the creation block for later usage.
+      self.components[protocolName] = component.creationBlock;
+
+      // Queue any protocols that should be eagerly instantiated. Don't instantiate them yet
+      // because they could depend on other components that haven't been added to the components
+      // array yet.
+      BOOL shouldInstantiateEager =
+          (component.instantiationTiming == FIRInstantiationTimingAlwaysEager);
+      BOOL shouldInstantiateDefaultEager =
+          (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp &&
+           [app isDefaultApp]);
+      if (shouldInstantiateEager || shouldInstantiateDefaultEager) {
+        [self.eagerProtocolsToInstantiate addObject:component.protocol];
+      }
+    }
+  }
+}
+
+#pragma mark - Instance Creation
+
+- (void)instantiateEagerComponents {
+  // After all components are registered, instantiate the ones that are requesting eager
+  // instantiation.
+  @synchronized(self) {
+    for (Protocol *protocol in self.eagerProtocolsToInstantiate) {
+      // Get an instance for the protocol, which will instantiate it since it couldn't have been
+      // cached yet. Ignore the instance coming back since we don't need it.
+      __unused id unusedInstance = [self instanceForProtocol:protocol];
+    }
+
+    // All eager instantiation is complete, clear the stored property now.
+    self.eagerProtocolsToInstantiate = nil;
+  }
+}
+
+/// Instantiate an instance of a class that conforms to the specified protocol.
+/// This will:
+///   - Call the block to create an instance if possible,
+///   - Validate that the instance returned conforms to the protocol it claims to,
+///   - Cache the instance if the block requests it
+///
+/// Note that this method assumes the caller already has @sychronized on self.
+- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol
+                                    withBlock:(FIRComponentCreationBlock)creationBlock {
+  if (!creationBlock) {
+    return nil;
+  }
+
+  // Create an instance using the creation block.
+  BOOL shouldCache = NO;
+  id instance = creationBlock(self, &shouldCache);
+  if (!instance) {
+    return nil;
+  }
+
+  // An instance was created, validate that it conforms to the protocol it claims to.
+  NSString *protocolName = NSStringFromProtocol(protocol);
+  if (![instance conformsToProtocol:protocol]) {
+    FIRLogError(kFIRLoggerCore, @"I-COR000030",
+                @"An instance conforming to %@ was requested, but the instance provided does not "
+                @"conform to the protocol",
+                protocolName);
+  }
+
+  // The instance is ready to be returned, but check if it should be cached first before returning.
+  if (shouldCache) {
+    self.cachedInstances[protocolName] = instance;
+  }
+
+  return instance;
+}
+
+#pragma mark - Internal Retrieval
+
+- (nullable id)instanceForProtocol:(Protocol *)protocol {
+  // Check if there is a cached instance, and return it if so.
+  NSString *protocolName = NSStringFromProtocol(protocol);
+
+  id cachedInstance;
+  @synchronized(self) {
+    cachedInstance = self.cachedInstances[protocolName];
+    if (!cachedInstance) {
+      // Use the creation block to instantiate an instance and return it.
+      FIRComponentCreationBlock creationBlock = self.components[protocolName];
+      cachedInstance = [self instantiateInstanceForProtocol:protocol withBlock:creationBlock];
+    }
+  }
+  return cachedInstance;
+}
+
+#pragma mark - Lifecycle
+
+- (void)removeAllCachedInstances {
+  @synchronized(self) {
+    // Loop through the cache and notify each instance that is a maintainer to clean up after
+    // itself.
+    for (id instance in self.cachedInstances.allValues) {
+      if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] &&
+          [instance respondsToSelector:@selector(appWillBeDeleted:)]) {
+        [instance appWillBeDeleted:self.app];
+      }
+    }
+
+    // Empty the cache.
+    [self.cachedInstances removeAllObjects];
+  }
+}
+
+- (void)removeAllComponents {
+  @synchronized(self) {
+    [self.components removeAllObjects];
+  }
+}
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 49 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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/Foundation.h>
+
+#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+
+@class FIRApp;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRComponentContainer (Private)
+
+/// Initializes a container for a given app. This should only be called by the app itself.
+- (instancetype)initWithApp:(FIRApp *)app;
+
+/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the
+/// protocol wasn't registered, or if the instance couldn't be instantiated for the provided app.
+- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:));
+
+/// Instantiates all the components that have registered as "eager" after initialization.
+- (void)instantiateEagerComponents;
+
+/// Remove all of the cached instances stored and allow them to clean up after themselves.
+- (void)removeAllCachedInstances;
+
+/// Removes all the components. After calling this method no new instances will be created.
+- (void)removeAllComponents;
+
+/// Register a class to provide components for the interoperability system. The class should conform
+/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects.
++ (void)registerAsComponentRegistrant:(Class<FIRLibrary>)klass;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 28 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m

@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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 "FirebaseCore/Sources/Private/FIRComponentType.h"
+
+#import "FirebaseCore/Sources/FIRComponentContainerInternal.h"
+
+@implementation FIRComponentType
+
++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container {
+  // Forward the call to the container.
+  return [container instanceForProtocol:protocol];
+}
+
+@end

+ 46 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m

@@ -0,0 +1,46 @@
+// Copyright 2017 Google
+//
+// 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 "FirebaseCore/Sources/FIRConfigurationInternal.h"
+
+#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
+
+extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
+
+@implementation FIRConfiguration
+
++ (instancetype)sharedInstance {
+  static FIRConfiguration *sharedInstance = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    sharedInstance = [[FIRConfiguration alloc] init];
+  });
+  return sharedInstance;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance];
+  }
+  return self;
+}
+
+- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel {
+  NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin,
+           @"Invalid logger level, %ld", (long)loggerLevel);
+  FIRSetLoggerLevel(loggerLevel);
+}
+
+@end

+ 29 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h

@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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 "FirebaseCore/Sources/Public/FirebaseCore/FIRConfiguration.h"
+
+@class FIRAnalyticsConfiguration;
+
+@interface FIRConfiguration ()
+
+/**
+ * The configuration class for Firebase Analytics. This should be removed once the logic for
+ * enabling and disabling Analytics is moved to Analytics.
+ */
+@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
+
+@end

+ 61 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m

@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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 "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h"
+
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h"
+
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIROptions.h"
+
+#import "FirebaseCore/Sources/FIRDiagnosticsData.h"
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
+
+// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop.
+Class<FIRCoreDiagnosticsInterop> FIRCoreDiagnosticsImplementation;
+
+@implementation FIRCoreDiagnosticsConnector
+
++ (void)initialize {
+  if (!FIRCoreDiagnosticsImplementation) {
+    FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics");
+    if (FIRCoreDiagnosticsImplementation) {
+      NSAssert([FIRCoreDiagnosticsImplementation
+                   conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)],
+               @"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol.");
+      NSAssert(
+          [FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)],
+          @"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData.");
+    }
+  }
+}
+
++ (void)logCoreTelemetryWithOptions:(FIROptions *)options {
+  if (FIRCoreDiagnosticsImplementation) {
+    FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init];
+    [diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey];
+    [diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey];
+    [diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey];
+    [diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey];
+    [diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey];
+    [diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist)
+                          forKey:kFIRCDUsingOptionsFromDefaultPlistKey];
+    [diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey];
+    [FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData];
+  }
+}
+
+@end

+ 44 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m

@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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 "FirebaseCore/Sources/Private/FIRDependency.h"
+
+@interface FIRDependency ()
+
+- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
+
+@end
+
+@implementation FIRDependency
+
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol {
+  return [[self alloc] initWithProtocol:protocol isRequired:YES];
+}
+
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required {
+  return [[self alloc] initWithProtocol:protocol isRequired:required];
+}
+
+- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required {
+  self = [super init];
+  if (self) {
+    _protocol = protocol;
+    _isRequired = required;
+  }
+  return self;
+}
+
+@end

+ 35 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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/Foundation.h>
+
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */
+@interface FIRDiagnosticsData : NSObject <FIRCoreDiagnosticsData>
+
+/** Inserts values into the diagnosticObjects dictionary if the value isn't nil.
+ *
+ * @param value The value to insert if it's not nil.
+ * @param key The key to associate it with.
+ */
+- (void)insertValue:(nullable id)value forKey:(NSString *)key;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 66 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m

@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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 "FirebaseCore/Sources/FIRDiagnosticsData.h"
+
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRApp.h"
+
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
+
+@implementation FIRDiagnosticsData {
+  /** Backing ivar for the diagnosticObjects property. */
+  NSMutableDictionary<NSString *, id> *_diagnosticObjects;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _diagnosticObjects = [[NSMutableDictionary alloc] init];
+  }
+  return self;
+}
+
+- (void)insertValue:(nullable id)value forKey:(NSString *)key {
+  if (key) {
+    _diagnosticObjects[key] = value;
+  }
+}
+
+#pragma mark - FIRCoreDiagnosticsData
+
+- (NSDictionary<NSString *, id> *)diagnosticObjects {
+  if (!_diagnosticObjects[kFIRCDllAppsCountKey]) {
+    _diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count);
+  }
+  if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) {
+    _diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] =
+        @([[FIRApp defaultApp] isDataCollectionDefaultEnabled]);
+  }
+  if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) {
+    _diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent];
+  }
+  return _diagnosticObjects;
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+- (void)setDiagnosticObjects:(NSDictionary<NSString *, id> *)diagnosticObjects {
+  NSAssert(NO, @"Please use -insertValue:forKey:");
+}
+#pragma clang diagnostic pop
+
+@end

+ 36 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRFirebaseUserAgent.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRFirebaseUserAgent : NSObject
+
+/** Returns the firebase user agent which consists of environment part and the components added via
+ * `setValue:forComponent` method. */
+- (NSString *)firebaseUserAgent;
+
+/** Sets value associated with the specified component. If value is `nil` then the component is
+ * removed. */
+- (void)setValue:(nullable NSString *)value forComponent:(NSString *)componentName;
+
+/** Resets manually added components. */
+- (void)reset;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 98 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRFirebaseUserAgent.m

@@ -0,0 +1,98 @@
+/*
+ * Copyright 2020 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 "FirebaseCore/Sources/FIRFirebaseUserAgent.h"
+
+#import <GoogleUtilities/GULAppEnvironmentUtil.h>
+
+@interface FIRFirebaseUserAgent ()
+
+@property(nonatomic, readonly) NSMutableDictionary<NSString *, NSString *> *valuesByComponent;
+@property(nonatomic, readonly) NSString *firebaseUserAgent;
+
+@end
+
+@implementation FIRFirebaseUserAgent
+
+@synthesize firebaseUserAgent = _firebaseUserAgent;
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _valuesByComponent = [[[self class] environmentComponents] mutableCopy];
+  }
+  return self;
+}
+
+- (NSString *)firebaseUserAgent {
+  @synchronized(self) {
+    if (_firebaseUserAgent == nil) {
+      __block NSMutableArray<NSString *> *components =
+          [[NSMutableArray<NSString *> alloc] initWithCapacity:self.valuesByComponent.count];
+      [self.valuesByComponent
+          enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value,
+                                              BOOL *_Nonnull stop) {
+            [components addObject:[NSString stringWithFormat:@"%@/%@", name, value]];
+          }];
+      [components sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
+      _firebaseUserAgent = [components componentsJoinedByString:@" "];
+    }
+    return _firebaseUserAgent;
+  }
+}
+
+- (void)setValue:(nullable NSString *)value forComponent:(NSString *)componentName {
+  @synchronized(self) {
+    self.valuesByComponent[componentName] = value;
+    // Reset cached user agent string.
+    _firebaseUserAgent = nil;
+  }
+}
+
+- (void)reset {
+  @synchronized(self) {
+    // Reset components.
+    _valuesByComponent = [[[self class] environmentComponents] mutableCopy];
+    // Reset cached user agent string.
+    _firebaseUserAgent = nil;
+  }
+}
+
+#pragma mark - Environment components
+
++ (NSDictionary<NSString *, NSString *> *)environmentComponents {
+  NSMutableDictionary<NSString *, NSString *> *components = [NSMutableDictionary dictionary];
+
+  NSDictionary<NSString *, id> *info = [[NSBundle mainBundle] infoDictionary];
+  NSString *xcodeVersion = info[@"DTXcodeBuild"];
+  NSString *appleSdkVersion = info[@"DTSDKBuild"];
+
+  NSString *swiftFlagValue = [GULAppEnvironmentUtil hasSwiftRuntime] ? @"true" : @"false";
+  NSString *isFromAppstoreFlagValue = [GULAppEnvironmentUtil isFromAppStore] ? @"true" : @"false";
+
+  components[@"apple-platform"] = [GULAppEnvironmentUtil applePlatform];
+  components[@"apple-sdk"] = appleSdkVersion;
+  components[@"appstore"] = isFromAppstoreFlagValue;
+  components[@"deploy"] = [GULAppEnvironmentUtil deploymentType];
+  components[@"device"] = [GULAppEnvironmentUtil deviceModel];
+  components[@"os-version"] = [GULAppEnvironmentUtil systemVersion];
+  components[@"swift"] = swiftFlagValue;
+  components[@"xcode"] = xcodeVersion;
+
+  return [components copy];
+}
+
+@end

+ 61 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m

@@ -0,0 +1,61 @@
+// Copyright 2019 Google
+//
+// 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 "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h"
+#import <GoogleUtilities/GULHeartbeatDateStorage.h>
+#import <GoogleUtilities/GULLogger.h>
+
+const static long secondsInDay = 86400;
+@implementation FIRHeartbeatInfo : NSObject
+
+/** Updates the storage with the heartbeat information corresponding to this tag.
+ * @param heartbeatTag Tag which could either be sdk specific tag or the global tag.
+ * @return Boolean representing whether the heartbeat needs to be sent for this tag or not.
+ */
++ (BOOL)updateIfNeededHeartbeatDateForTag:(NSString *)heartbeatTag {
+  @synchronized(self) {
+    NSString *const kHeartbeatStorageFile = @"HEARTBEAT_INFO_STORAGE";
+    GULHeartbeatDateStorage *dataStorage =
+        [[GULHeartbeatDateStorage alloc] initWithFileName:kHeartbeatStorageFile];
+    NSDate *heartbeatTime = [dataStorage heartbeatDateForTag:heartbeatTag];
+    NSDate *currentDate = [NSDate date];
+    if (heartbeatTime != nil) {
+      NSTimeInterval secondsBetween = [currentDate timeIntervalSinceDate:heartbeatTime];
+      if (secondsBetween < secondsInDay) {
+        return false;
+      }
+    }
+    return [dataStorage setHearbeatDate:currentDate forTag:heartbeatTag];
+  }
+}
+
++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag {
+  NSString *globalTag = @"GLOBAL";
+  BOOL isSdkHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:heartbeatTag];
+  BOOL isGlobalHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:globalTag];
+  if (!isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) {
+    // Both sdk and global heartbeat not needed.
+    return FIRHeartbeatInfoCodeNone;
+  } else if (isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) {
+    // Only SDK heartbeat needed.
+    return FIRHeartbeatInfoCodeSDK;
+  } else if (!isSdkHeartbeatNeeded && isGlobalHeartbeatNeeded) {
+    // Only global heartbeat needed.
+    return FIRHeartbeatInfoCodeGlobal;
+  } else {
+    // Both sdk and global heartbeat are needed.
+    return FIRHeartbeatInfoCodeCombined;
+  }
+}
+@end

+ 176 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m

@@ -0,0 +1,176 @@
+// Copyright 2017 Google
+//
+// 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 "FirebaseCore/Sources/Private/FIRLogger.h"
+
+#import <GoogleUtilities/GULAppEnvironmentUtil.h>
+#import <GoogleUtilities/GULLogger.h>
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRLoggerLevel.h"
+
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h"
+
+FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]";
+
+// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones!
+FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]";
+FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]";
+FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]";
+FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]";
+FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]";
+
+/// Arguments passed on launch.
+NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled";
+NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled";
+NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR";
+
+/// Key for the debug mode bit in NSUserDefaults.
+NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode";
+
+/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults`
+/// will be used.
+static NSUserDefaults *sFIRLoggerUserDefaults;
+
+static dispatch_once_t sFIRLoggerOnceToken;
+
+// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled
+// flags used by Analytics. Users who use those flags expect Analytics to log verbosely,
+// while the rest of Firebase logs at the default level. This flag is introduced to support
+// that behavior.
+static BOOL sFIRAnalyticsDebugMode;
+
+#ifdef DEBUG
+/// The regex pattern for the message code.
+static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$";
+static NSRegularExpression *sMessageCodeRegex;
+#endif
+
+void FIRLoggerInitializeASL() {
+  dispatch_once(&sFIRLoggerOnceToken, ^{
+    // Register Firebase Version with GULLogger.
+    GULLoggerRegisterVersion(FIRFirebaseVersion());
+
+    // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in.
+    NSArray *arguments = [NSProcessInfo processInfo].arguments;
+    BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument];
+
+    // Use the standard NSUserDefaults if it hasn't been explicitly set.
+    if (sFIRLoggerUserDefaults == nil) {
+      sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults];
+    }
+
+    BOOL forceDebugMode = NO;
+    BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey];
+    if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) {  // Default mode
+      [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey];
+    } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] ||
+               debugMode) {  // Debug mode
+      [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey];
+      forceDebugMode = YES;
+    }
+    GULLoggerInitializeASL();
+    if (overrideSTDERR) {
+      GULLoggerEnableSTDERR();
+    }
+    if (forceDebugMode) {
+      GULLoggerForceDebug();
+    }
+  });
+}
+
+__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) {
+  sFIRAnalyticsDebugMode = analyticsDebugMode;
+}
+
+void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) {
+  FIRLoggerInitializeASL();
+  GULSetLoggerLevel((GULLoggerLevel)loggerLevel);
+}
+
+#ifdef DEBUG
+void FIRResetLogger() {
+  extern void GULResetLogger(void);
+  sFIRLoggerOnceToken = 0;
+  [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey];
+  sFIRLoggerUserDefaults = nil;
+  GULResetLogger();
+}
+
+void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) {
+  sFIRLoggerUserDefaults = defaults;
+}
+#endif
+
+/**
+ * Check if the level is high enough to be loggable.
+ *
+ * Analytics can override the log level with an intentional race condition.
+ * Add the attribute to get a clean thread sanitizer run.
+ */
+__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel,
+                                                               BOOL analyticsComponent) {
+  FIRLoggerInitializeASL();
+  if (sFIRAnalyticsDebugMode && analyticsComponent) {
+    return YES;
+  }
+  return GULIsLoggableLevel((GULLoggerLevel)loggerLevel);
+}
+
+void FIRLogBasic(FIRLoggerLevel level,
+                 FIRLoggerService service,
+                 NSString *messageCode,
+                 NSString *message,
+                 va_list args_ptr) {
+  FIRLoggerInitializeASL();
+  GULLogBasic((GULLoggerLevel)level, service,
+              sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode,
+              message, args_ptr);
+}
+
+/**
+ * Generates the logging functions using macros.
+ *
+ * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows:
+ * yyyy-mm-dd hh:mm:ss.SSS sender[PID] <Error> [Firebase/Core][I-COR000001] Configure blah failed.
+ * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows:
+ * yyyy-mm-dd hh:mm:ss.SSS sender[PID] <Debug> [Firebase/Core][I-COR000001] Configure succeed.
+ */
+#define FIR_LOGGING_FUNCTION(level)                                                             \
+  void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \
+    va_list args_ptr;                                                                           \
+    va_start(args_ptr, message);                                                                \
+    FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr);                \
+    va_end(args_ptr);                                                                           \
+  }
+
+FIR_LOGGING_FUNCTION(Error)
+FIR_LOGGING_FUNCTION(Warning)
+FIR_LOGGING_FUNCTION(Notice)
+FIR_LOGGING_FUNCTION(Info)
+FIR_LOGGING_FUNCTION(Debug)
+
+#undef FIR_MAKE_LOGGER
+
+#pragma mark - FIRLoggerWrapper
+
+@implementation FIRLoggerWrapper
+
++ (void)logWithLevel:(FIRLoggerLevel)level
+         withService:(FIRLoggerService)service
+            withCode:(NSString *)messageCode
+         withMessage:(NSString *)message
+            withArgs:(va_list)args {
+  FIRLogBasic(level, service, messageCode, message, args);
+}
+
+@end

+ 498 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m

@@ -0,0 +1,498 @@
+// Copyright 2017 Google
+//
+// 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 "FirebaseCore/Sources/FIRBundleUtil.h"
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIRLogger.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"
+#import "FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h"
+
+// Keys for the strings in the plist file.
+NSString *const kFIRAPIKey = @"API_KEY";
+NSString *const kFIRTrackingID = @"TRACKING_ID";
+NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID";
+NSString *const kFIRClientID = @"CLIENT_ID";
+NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID";
+NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID";
+NSString *const kFIRDatabaseURL = @"DATABASE_URL";
+NSString *const kFIRStorageBucket = @"STORAGE_BUCKET";
+// The key to locate the expected bundle identifier in the plist file.
+NSString *const kFIRBundleID = @"BUNDLE_ID";
+// The key to locate the project identifier in the plist file.
+NSString *const kFIRProjectID = @"PROJECT_ID";
+
+NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED";
+NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED";
+NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED";
+
+NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED";
+NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED";
+
+// Library version ID formatted like:
+// @"5"     // Major version (one or more digits)
+// @"04"    // Minor version (exactly 2 digits)
+// @"01"    // Build number (exactly 2 digits)
+// @"000";  // Fixed "000"
+NSString *kFIRLibraryVersionID;
+
+// Plist file name.
+NSString *const kServiceInfoFileName = @"GoogleService-Info";
+// Plist file type.
+NSString *const kServiceInfoFileType = @"plist";
+
+// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp.
+NSString *const kFIRExceptionBadModification =
+    @"Attempted to modify options after it's set on FIRApp. Please modify all properties before "
+    @"initializing FIRApp.";
+
+@interface FIROptions ()
+
+/**
+ * This property maintains the actual configuration key-value pairs.
+ */
+@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary;
+
+/**
+ * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary.
+ * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist.
+ * Values which are present in the main plist override values from the GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary;
+
+/**
+ * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist.
+ * Values which are present in the infoDictionary override values from the GoogleService-Info.plist.
+ */
+- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary;
+
+/**
+ * Throw exception if editing is locked when attempting to modify an option.
+ */
+- (void)checkEditingLocked;
+
+@end
+
+@implementation FIROptions {
+  /// Backing variable for self.analyticsOptionsDictionary.
+  NSDictionary *_analyticsOptionsDictionary;
+}
+
+static FIROptions *sDefaultOptions = nil;
+static NSDictionary *sDefaultOptionsDictionary = nil;
+static dispatch_once_t sDefaultOptionsOnceToken;
+static dispatch_once_t sDefaultOptionsDictionaryOnceToken;
+
+#pragma mark - Public only for internal class methods
+
++ (FIROptions *)defaultOptions {
+  dispatch_once(&sDefaultOptionsOnceToken, ^{
+    NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary];
+    if (defaultOptionsDictionary != nil) {
+      sDefaultOptions =
+          [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary];
+    }
+  });
+
+  return sDefaultOptions;
+}
+
+#pragma mark - Private class methods
+
++ (NSDictionary *)defaultOptionsDictionary {
+  dispatch_once(&sDefaultOptionsDictionaryOnceToken, ^{
+    NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName];
+    if (plistFilePath == nil) {
+      return;
+    }
+    sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
+    if (sDefaultOptionsDictionary == nil) {
+      FIRLogError(kFIRLoggerCore, @"I-COR000011",
+                  @"The configuration file is not a dictionary: "
+                  @"'%@.%@'.",
+                  kServiceInfoFileName, kServiceInfoFileType);
+    }
+  });
+
+  return sDefaultOptionsDictionary;
+}
+
+// Returns the path of the plist file with a given file name.
++ (NSString *)plistFilePathWithName:(NSString *)fileName {
+  NSArray *bundles = [FIRBundleUtil relevantBundles];
+  NSString *plistFilePath =
+      [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName
+                                               andFileType:kServiceInfoFileType
+                                                 inBundles:bundles];
+  if (plistFilePath == nil) {
+    FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.",
+                fileName, kServiceInfoFileType);
+  }
+  return plistFilePath;
+}
+
++ (void)resetDefaultOptions {
+  sDefaultOptions = nil;
+  sDefaultOptionsDictionary = nil;
+  sDefaultOptionsOnceToken = 0;
+  sDefaultOptionsDictionaryOnceToken = 0;
+}
+
+#pragma mark - Private instance methods
+
+- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary {
+  self = [super init];
+  if (self) {
+    _optionsDictionary = [optionsDictionary mutableCopy];
+    _usingOptionsFromDefaultPlist = YES;
+  }
+  return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  FIROptions *newOptions = [(FIROptions *)[[self class] allocWithZone:zone]
+      initInternalWithOptionsDictionary:self.optionsDictionary];
+  if (newOptions) {
+    newOptions.deepLinkURLScheme = self.deepLinkURLScheme;
+    newOptions.appGroupID = self.appGroupID;
+    newOptions.editingLocked = self.isEditingLocked;
+    newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist;
+  }
+  return newOptions;
+}
+
+#pragma mark - Public instance methods
+
+- (instancetype)init {
+  // Unavailable.
+  [self doesNotRecognizeSelector:_cmd];
+  return nil;
+}
+
+- (instancetype)initWithContentsOfFile:(NSString *)plistPath {
+  self = [super init];
+  if (self) {
+    if (plistPath == nil) {
+      FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil.");
+      return nil;
+    }
+    _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy];
+    if (_optionsDictionary == nil) {
+      FIRLogError(kFIRLoggerCore, @"I-COR000014",
+                  @"The configuration file at %@ does not exist or "
+                  @"is not a well-formed plist file.",
+                  plistPath);
+      return nil;
+    }
+    // TODO: Do we want to validate the dictionary here? It says we do that already in
+    // the public header.
+  }
+  return self;
+}
+
+- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID {
+  self = [super init];
+  if (self) {
+    NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary];
+    [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID];
+    [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID];
+    [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID];
+    self.optionsDictionary = mutableOptionsDict;
+  }
+  return self;
+}
+
+- (NSString *)APIKey {
+  return self.optionsDictionary[kFIRAPIKey];
+}
+
+- (void)checkEditingLocked {
+  if (self.isEditingLocked) {
+    [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification];
+  }
+}
+
+- (void)setAPIKey:(NSString *)APIKey {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRAPIKey] = [APIKey copy];
+}
+
+- (NSString *)clientID {
+  return self.optionsDictionary[kFIRClientID];
+}
+
+- (void)setClientID:(NSString *)clientID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRClientID] = [clientID copy];
+}
+
+- (NSString *)trackingID {
+  return self.optionsDictionary[kFIRTrackingID];
+}
+
+- (void)setTrackingID:(NSString *)trackingID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRTrackingID] = [trackingID copy];
+}
+
+- (NSString *)GCMSenderID {
+  return self.optionsDictionary[kFIRGCMSenderID];
+}
+
+- (void)setGCMSenderID:(NSString *)GCMSenderID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy];
+}
+
+- (NSString *)projectID {
+  return self.optionsDictionary[kFIRProjectID];
+}
+
+- (void)setProjectID:(NSString *)projectID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRProjectID] = [projectID copy];
+}
+
+- (NSString *)androidClientID {
+  return self.optionsDictionary[kFIRAndroidClientID];
+}
+
+- (void)setAndroidClientID:(NSString *)androidClientID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy];
+}
+
+- (NSString *)googleAppID {
+  return self.optionsDictionary[kFIRGoogleAppID];
+}
+
+- (void)setGoogleAppID:(NSString *)googleAppID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy];
+}
+
+- (NSString *)libraryVersionID {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    // The unit tests are set up to catch anything that does not properly convert.
+    NSString *version = FIRFirebaseVersion();
+    NSArray *components = [version componentsSeparatedByString:@"."];
+    NSString *major = [components objectAtIndex:0];
+    NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]];
+    NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]];
+    kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch];
+  });
+  return kFIRLibraryVersionID;
+}
+
+- (void)setLibraryVersionID:(NSString *)libraryVersionID {
+  _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy];
+}
+
+- (NSString *)databaseURL {
+  return self.optionsDictionary[kFIRDatabaseURL];
+}
+
+- (void)setDatabaseURL:(NSString *)databaseURL {
+  [self checkEditingLocked];
+
+  _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy];
+}
+
+- (NSString *)storageBucket {
+  return self.optionsDictionary[kFIRStorageBucket];
+}
+
+- (void)setStorageBucket:(NSString *)storageBucket {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRStorageBucket] = [storageBucket copy];
+}
+
+- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme {
+  [self checkEditingLocked];
+  _deepLinkURLScheme = [deepLinkURLScheme copy];
+}
+
+- (NSString *)bundleID {
+  return self.optionsDictionary[kFIRBundleID];
+}
+
+- (void)setBundleID:(NSString *)bundleID {
+  [self checkEditingLocked];
+  _optionsDictionary[kFIRBundleID] = [bundleID copy];
+}
+
+- (void)setAppGroupID:(NSString *)appGroupID {
+  [self checkEditingLocked];
+  _appGroupID = [appGroupID copy];
+}
+
+#pragma mark - Equality
+
+- (BOOL)isEqual:(id)object {
+  if (!object || ![object isKindOfClass:[FIROptions class]]) {
+    return NO;
+  }
+
+  return [self isEqualToOptions:(FIROptions *)object];
+}
+
+- (BOOL)isEqualToOptions:(FIROptions *)options {
+  // Skip any non-FIROptions classes.
+  if (![options isKindOfClass:[FIROptions class]]) {
+    return NO;
+  }
+
+  // Check the internal dictionary and custom properties for differences.
+  if (![options.optionsDictionary isEqualToDictionary:self.optionsDictionary]) {
+    return NO;
+  }
+
+  // Validate extra properties not contained in the dictionary. Only validate it if one of the
+  // objects has the property set.
+  if ((options.deepLinkURLScheme != nil || self.deepLinkURLScheme != nil) &&
+      ![options.deepLinkURLScheme isEqualToString:self.deepLinkURLScheme]) {
+    return NO;
+  }
+
+  if ((options.appGroupID != nil || self.appGroupID != nil) &&
+      ![options.appGroupID isEqualToString:self.appGroupID]) {
+    return NO;
+  }
+
+  // Validate the Analytics options haven't changed with the Info.plist.
+  if (![options.analyticsOptionsDictionary isEqualToDictionary:self.analyticsOptionsDictionary]) {
+    return NO;
+  }
+
+  // We don't care about the `editingLocked` or `usingOptionsFromDefaultPlist` properties since
+  // those relate to lifecycle and construction, we only care if the contents of the options
+  // themselves are equal.
+  return YES;
+}
+
+- (NSUInteger)hash {
+  // This is strongly recommended for any object that implements a custom `isEqual:` method to
+  // ensure that dictionary and set behavior matches other `isEqual:` checks.
+  // Note: `self.analyticsOptionsDictionary` was left out here since it solely relies on the
+  // contents of the main bundle's `Info.plist`. We should avoid reading that file and the contents
+  // should be identical.
+  return self.optionsDictionary.hash ^ self.deepLinkURLScheme.hash ^ self.appGroupID.hash;
+}
+
+#pragma mark - Internal instance methods
+
+- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary {
+  if (_analyticsOptionsDictionary == nil) {
+    NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init];
+    NSArray *measurementKeys = @[
+      kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled,
+      kFIRIsAnalyticsCollectionDeactivated
+    ];
+    for (NSString *key in measurementKeys) {
+      id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil;
+      if (!value) {
+        continue;
+      }
+      tempAnalyticsOptions[key] = value;
+    }
+    _analyticsOptionsDictionary = tempAnalyticsOptions;
+  }
+  return _analyticsOptionsDictionary;
+}
+
+- (NSDictionary *)analyticsOptionsDictionary {
+  return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary];
+}
+
+/**
+ * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
+ * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still
+ * be supported.
+ */
+- (BOOL)isMeasurementEnabled {
+  if (self.isAnalyticsCollectionDeactivated) {
+    return NO;
+  }
+  NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled];
+  if (value == nil) {
+    // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have
+    //       to check if it's the default app. The FIROptions instance can't be modified after
+    //       `+configure` is called, so it's not a good place to copy it either in case the flag is
+    //       changed at runtime.
+
+    // If no values are set for Analytics, fall back to the global collection switch in FIRApp.
+    // Analytics only supports the default FIRApp, so check that first.
+    if (![FIRApp isDefaultAppConfigured]) {
+      return NO;
+    }
+
+    // Fall back to the default app's collection switch when the key is not in the dictionary.
+    return [FIRApp defaultApp].isDataCollectionDefaultEnabled;
+  }
+  return [value boolValue];
+}
+
+- (BOOL)isAnalyticsCollectionExplicitlySet {
+  // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication
+  // that the developer wants FirebaseAnalytics enabled so continue checking.
+  if (self.isAnalyticsCollectionDeactivated) {
+    return YES;
+  }
+
+  // Check if the current Analytics flag is set.
+  id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled];
+  if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) {
+    // It doesn't matter what the value is, it's explicitly set.
+    return YES;
+  }
+
+  // Check if the old measurement flag is set.
+  id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled];
+  if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) {
+    // It doesn't matter what the value is, it's explicitly set.
+    return YES;
+  }
+
+  // No flags are set to explicitly enable or disable FirebaseAnalytics.
+  return NO;
+}
+
+- (BOOL)isAnalyticsCollectionEnabled {
+  if (self.isAnalyticsCollectionDeactivated) {
+    return NO;
+  }
+  NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled];
+  if (value == nil) {
+    return self.isMeasurementEnabled;  // Fall back to older plist flag.
+  }
+  return [value boolValue];
+}
+
+- (BOOL)isAnalyticsCollectionDeactivated {
+  NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated];
+  if (value == nil) {
+    return NO;  // Analytics Collection is not deactivated when the key is not in the dictionary.
+  }
+  return [value boolValue];
+}
+
+- (BOOL)isAnalyticsEnabled {
+  return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue];
+}
+
+- (BOOL)isSignInEnabled {
+  return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue];
+}
+
+@end

+ 32 - 0
Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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 "FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h"
+
+#ifndef Firebase_VERSION
+#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation"
+#endif
+
+// The following two macros supply the incantation so that the C
+// preprocessor does not try to parse the version as a floating
+// point number. See
+// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/
+#define STR(x) STR_EXPAND(x)
+#define STR_EXPAND(x) #x
+
+NSString* FIRFirebaseVersion(void) {
+  return [NSString stringWithUTF8String:(const char* const)STR(Firebase_VERSION)];
+}

+ 155 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h

@@ -0,0 +1,155 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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 <FirebaseCore/FIRApp.h>
+
+@class FIRComponentContainer;
+@protocol FIRLibrary;
+
+/**
+ * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive
+ * FIRApp notifications, log info about the success or failure of their configuration, and access
+ * other internal functionality of FIRApp.
+ *
+ * TODO(b/28296561): Restructure this header.
+ */
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, FIRConfigType) {
+  FIRConfigTypeCore = 1,
+  FIRConfigTypeSDK = 2,
+};
+
+extern NSString *const kFIRDefaultAppName;
+extern NSString *const kFIRAppReadyToConfigureSDKNotification;
+extern NSString *const kFIRAppDeleteNotification;
+extern NSString *const kFIRAppIsDefaultAppKey;
+extern NSString *const kFIRAppNameKey;
+extern NSString *const kFIRGoogleAppIDKey;
+extern NSString *const kFirebaseCoreErrorDomain;
+
+/**
+ * The format string for the User Defaults key used for storing the data collection enabled flag.
+ * This includes formatting to append the Firebase App's name.
+ */
+extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat;
+
+/**
+ * The plist key used for storing the data collection enabled flag.
+ */
+extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey;
+
+/**
+ * A notification fired containing diagnostic information when SDK errors occur.
+ */
+extern NSString *const kFIRAppDiagnosticsNotification;
+
+/** @var FIRAuthStateDidChangeInternalNotification
+ @brief The name of the @c NSNotificationCenter notification which is posted when the auth state
+ changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
+ the notification is a dictionary possibly containing the key:
+ @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
+ contain this key it indicates a sign-out event took place.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotification;
+
+/** @var FIRAuthStateDidChangeInternalNotificationTokenKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the new access token.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;
+
+/** @var FIRAuthStateDidChangeInternalNotificationAppKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the FIRApp associated with the auth instance.
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey;
+
+/** @var FIRAuthStateDidChangeInternalNotificationUIDKey
+ @brief A key present in the dictionary object parameter of the
+ @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
+ key will contain the new user's UID (or nil if there is no longer a user signed in).
+ */
+extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
+
+@interface FIRApp ()
+
+/**
+ * A flag indicating if this is the default app (has the default app name).
+ */
+@property(nonatomic, readonly) BOOL isDefaultApp;
+
+/*
+ * The container of interop SDKs for this app.
+ */
+@property(nonatomic) FIRComponentContainer *container;
+
+/**
+ * Checks if the default app is configured without trying to configure it.
+ */
++ (BOOL)isDefaultAppConfigured;
+
+/**
+ * Registers a given third-party library with the given version number to be reported for
+ * analytics.
+ *
+ * @param name Name of the library.
+ * @param version Version of the library.
+ */
++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version;
+
+/**
+ * Registers a given internal library to be reported for analytics.
+ *
+ * @param library Optional parameter for component registration.
+ * @param name Name of the library.
+ */
++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
+                       withName:(nonnull NSString *)name;
+
+/**
+ * Registers a given internal library with the given version number to be reported for
+ * analytics. This should only be used for non-Firebase libraries that have their own versioning
+ * scheme.
+ *
+ * @param library Optional parameter for component registration.
+ * @param name Name of the library.
+ * @param version Version of the library.
+ */
++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
+                       withName:(nonnull NSString *)name
+                    withVersion:(nonnull NSString *)version;
+
+/**
+ * A concatenated string representing all the third-party libraries and version numbers.
+ */
++ (NSString *)firebaseUserAgent;
+
+/**
+ * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe.
+ */
++ (void)resetApps;
+
+/**
+ * Can be used by the unit tests in each SDK to set customized options.
+ */
+- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 91 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h

@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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/Foundation.h>
+
+@class FIRApp;
+@class FIRComponentContainer;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Provides a system to clean up cached instances returned from the component system.
+NS_SWIFT_NAME(ComponentLifecycleMaintainer)
+@protocol FIRComponentLifecycleMaintainer
+/// The associated app will be deleted, clean up any resources as they are about to be deallocated.
+- (void)appWillBeDeleted:(FIRApp *)app;
+@end
+
+typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container,
+                                                  BOOL *isCacheable)
+    NS_SWIFT_NAME(ComponentCreationBlock);
+
+@class FIRDependency;
+
+/// Describes the timing of instantiation. Note: new components should default to lazy unless there
+/// is a strong reason to be eager.
+typedef NS_ENUM(NSInteger, FIRInstantiationTiming) {
+  FIRInstantiationTimingLazy,
+  FIRInstantiationTimingAlwaysEager,
+  FIRInstantiationTimingEagerInDefaultApp
+} NS_SWIFT_NAME(InstantiationTiming);
+
+/// A component that can be used from other Firebase SDKs.
+NS_SWIFT_NAME(Component)
+@interface FIRComponent : NSObject
+
+/// The protocol describing functionality provided from the Component.
+@property(nonatomic, strong, readonly) Protocol *protocol;
+
+/// The timing of instantiation.
+@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming;
+
+/// An array of dependencies for the component.
+@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies;
+
+/// A block to instantiate an instance of the component with the appropriate dependencies.
+@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock;
+
+// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format
+// for the next two methods.
+// clang-format off
+
+/// Creates a component with no dependencies that will be lazily initialized.
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+                        creationBlock:(FIRComponentCreationBlock)creationBlock
+NS_SWIFT_NAME(init(_:creationBlock:));
+
+/// Creates a component to be registered with the component container.
+///
+/// @param protocol - The protocol describing functionality provided by the component.
+/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's
+///                              a good reason to be instantiated earlier.
+/// @param dependencies - Any dependencies the `implementingClass` has, optional or required.
+/// @param creationBlock - A block to instantiate the component with a container, and if
+/// @return A component that can be registered with the component container.
++ (instancetype)componentWithProtocol:(Protocol *)protocol
+                  instantiationTiming:(FIRInstantiationTiming)instantiationTiming
+                         dependencies:(NSArray<FIRDependency *> *)dependencies
+                        creationBlock:(FIRComponentCreationBlock)creationBlock
+NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:));
+
+// clang-format on
+
+/// Unavailable.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 41 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A type-safe macro to retrieve a component from a container. This should be used to retrieve
+/// components instead of using the container directly.
+#define FIR_COMPONENT(type, container) \
+  [FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container]
+
+@class FIRApp;
+
+/// A container that holds different components that are registered via the
+/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant`
+/// in order to properly register components for Core.
+NS_SWIFT_NAME(FirebaseComponentContainer)
+@interface FIRComponentContainer : NSObject
+
+/// A weak reference to the app that an instance of the container belongs to.
+@property(nonatomic, weak, readonly) FIRApp *app;
+
+/// Unavailable. Use the `container` property on `FIRApp`.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 34 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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/Foundation.h>
+
+@class FIRComponentContainer;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Do not use directly. A placeholder type in order to provide a macro that will warn users of
+/// mis-matched protocols.
+NS_SWIFT_NAME(ComponentType)
+@interface FIRComponentType<__covariant T> : NSObject
+
+/// Do not use directly. A factory method to retrieve an instance that provides a specific
+/// functionality.
++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 35 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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/Foundation.h>
+
+@class FIRDiagnosticsData;
+@class FIROptions;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Connects FIRCore with the CoreDiagnostics library. */
+@interface FIRCoreDiagnosticsConnector : NSObject
+
+/** Logs FirebaseCore  related data.
+ *
+ * @param options The options object containing data to log.
+ */
++ (void)logCoreTelemetryWithOptions:(FIROptions *)options;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 45 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// A dependency on a specific protocol's functionality.
+NS_SWIFT_NAME(Dependency)
+@interface FIRDependency : NSObject
+
+/// The protocol describing functionality being depended on.
+@property(nonatomic, strong, readonly) Protocol *protocol;
+
+/// A flag to specify if the dependency is required or not.
+@property(nonatomic, readonly) BOOL isRequired;
+
+/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for
+/// the required parameter.
+/// Creates a required dependency on the specified protocol's functionality.
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol;
+
+/// Creates a dependency on the specified protocol's functionality and specify if it's required for
+/// the class's functionality.
++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required;
+
+/// Use `dependencyWithProtocol:isRequired:` instead.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 39 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h

@@ -0,0 +1,39 @@
+// Copyright 2019 Google
+//
+// 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRHeartbeatInfo : NSObject
+
+// Enum representing the different heartbeat codes.
+typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) {
+  FIRHeartbeatInfoCodeNone = 0,
+  FIRHeartbeatInfoCodeSDK = 1,
+  FIRHeartbeatInfoCodeGlobal = 2,
+  FIRHeartbeatInfoCodeCombined = 3,
+};
+
+/**
+ * Get heartbeat code requred for the sdk.
+ * @param heartbeatTag String representing the sdk heartbeat tag.
+ * @return Heartbeat code indicating whether or not an sdk/global heartbeat
+ * needs to be sent
+ */
++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 44 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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.
+ */
+
+#ifndef FIRLibrary_h
+#define FIRLibrary_h
+
+#import <Foundation/Foundation.h>
+
+@class FIRApp;
+@class FIRComponent;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// Provide an interface to register a library for userAgent logging and availability to others.
+NS_SWIFT_NAME(Library)
+@protocol FIRLibrary
+
+/// Returns one or more FIRComponents that will be registered in
+/// FIRApp and participate in dependency resolution and injection.
++ (NSArray<FIRComponent *> *)componentsToRegister;
+
+@optional
+/// Implement this method if the library needs notifications for lifecycle events. This method is
+/// called when the developer calls `FirebaseApp.configure()`.
++ (void)configureWithApp:(FIRApp *)app;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif /* FIRLibrary_h */

+ 148 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h

@@ -0,0 +1,148 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+#import <FirebaseCore/FIRLoggerLevel.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * The Firebase services used in Firebase logger.
+ */
+typedef NSString *const FIRLoggerService;
+
+extern FIRLoggerService kFIRLoggerAnalytics;
+extern FIRLoggerService kFIRLoggerCrash;
+extern FIRLoggerService kFIRLoggerCore;
+extern FIRLoggerService kFIRLoggerMLKit;
+extern FIRLoggerService kFIRLoggerPerf;
+extern FIRLoggerService kFIRLoggerRemoteConfig;
+
+/**
+ * The key used to store the logger's error count.
+ */
+extern NSString *const kFIRLoggerErrorCountKey;
+
+/**
+ * The key used to store the logger's warning count.
+ */
+extern NSString *const kFIRLoggerWarningCountKey;
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+/**
+ * Enables or disables Analytics debug mode.
+ * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug.
+ * Enabling the debug mode has no effect if the app is running from App Store.
+ * (required) analytics debug mode flag.
+ */
+void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode);
+
+/**
+ * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level.
+ * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ */
+void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
+
+/**
+ * Checks if the specified logger level is loggable given the current settings.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) whether or not this function is called from the Analytics component.
+ */
+BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
+
+/**
+ * Logs a message to the Xcode console and the device log. If running from AppStore, will
+ * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming.
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting with "I-" which means iOS, followed by a capitalized
+ *            three-character service identifier and a six digit integer message ID that is unique
+ *            within the service.
+ *            An example of the message code is @"I-COR000001".
+ * (required) message string which can be a format string.
+ * (optional) variable arguments list obtained from calling va_start, used when message is a format
+ *            string.
+ */
+extern void FIRLogBasic(FIRLoggerLevel level,
+                        FIRLoggerService service,
+                        NSString *messageCode,
+                        NSString *message,
+// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable
+// See: http://stackoverflow.com/q/29095469
+#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX
+                        va_list args_ptr
+#else
+                        va_list _Nullable args_ptr
+#endif
+);
+
+/**
+ * The following functions accept the following parameters in order:
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting from "I-" which means iOS, followed by a capitalized
+ *            three-character service identifier and a six digit integer message ID that is unique
+ *            within the service.
+ *            An example of the message code is @"I-COR000001".
+ *            See go/firebase-log-proposal for details.
+ * (required) message string which can be a format string.
+ * (optional) the list of arguments to substitute into the format string.
+ * Example usage:
+ * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name);
+ */
+extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+    NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+    NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+    NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+    NS_FORMAT_FUNCTION(3, 4);
+extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...)
+    NS_FORMAT_FUNCTION(3, 4);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif  // __cplusplus
+
+@interface FIRLoggerWrapper : NSObject
+
+/**
+ * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger
+ * (required) log level (one of the FIRLoggerLevel enum values).
+ * (required) service name of type FIRLoggerService.
+ * (required) message code starting with "I-" which means iOS, followed by a capitalized
+ *            three-character service identifier and a six digit integer message ID that is unique
+ *            within the service.
+ *            An example of the message code is @"I-COR000001".
+ * (required) message string which can be a format string.
+ * (optional) variable arguments list obtained from calling va_start, used when message is a format
+ *            string.
+ */
+
++ (void)logWithLevel:(FIRLoggerLevel)level
+         withService:(FIRLoggerService)service
+            withCode:(NSString *)messageCode
+         withMessage:(NSString *)message
+            withArgs:(va_list)args;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 115 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h

@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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 <FirebaseCore/FIROptions.h>
+
+/**
+ * Keys for the strings in the plist file.
+ */
+extern NSString *const kFIRAPIKey;
+extern NSString *const kFIRTrackingID;
+extern NSString *const kFIRGoogleAppID;
+extern NSString *const kFIRClientID;
+extern NSString *const kFIRGCMSenderID;
+extern NSString *const kFIRAndroidClientID;
+extern NSString *const kFIRDatabaseURL;
+extern NSString *const kFIRStorageBucket;
+extern NSString *const kFIRBundleID;
+extern NSString *const kFIRProjectID;
+
+/**
+ * Keys for the plist file name
+ */
+extern NSString *const kServiceInfoFileName;
+
+extern NSString *const kServiceInfoFileType;
+
+/**
+ * This header file exposes the initialization of FIROptions to internal use.
+ */
+@interface FIROptions ()
+
+/**
+ * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests.
+ */
++ (void)resetDefaultOptions;
+
+/**
+ * Initializes the options with dictionary. The above strings are the keys of the dictionary.
+ * This is the designated initializer.
+ */
+- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary
+    NS_DESIGNATED_INITIALIZER;
+
+/**
+ * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and
+ * other first party services.
+ */
++ (FIROptions *)defaultOptions;
+
++ (NSDictionary *)defaultOptionsDictionary;
+
+/**
+ * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at
+ * runtime.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet;
+
+/**
+ * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless
+ * explicitly disabled in GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled;
+
+/**
+ * Whether or not Analytics Collection was completely disabled. If YES, then
+ * isAnalyticsCollectionEnabled will be NO.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated;
+
+/**
+ * The version ID of the client library, e.g. @"1100000".
+ */
+@property(nonatomic, readonly, copy) NSString *libraryVersionID;
+
+/**
+ * The flag indicating whether this object was constructed with the values in the default plist
+ * file.
+ */
+@property(nonatomic) BOOL usingOptionsFromDefaultPlist;
+
+/**
+ * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
+ * GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) BOOL isMeasurementEnabled;
+
+/**
+ * Whether or not Analytics was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsEnabled;
+
+/**
+ * Whether or not SignIn was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isSignInEnabled;
+
+/**
+ * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp.
+ */
+@property(nonatomic, getter=isEditingLocked) BOOL editingLocked;
+
+@end

+ 28 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h

@@ -0,0 +1,28 @@
+// Copyright 2020 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.
+
+// An umbrella header, for any other libraries in this repo to access Firebase Public and Private
+// headers. Any package manager complexity should be handled here.
+
+#import <FirebaseCore/FirebaseCore.h>
+
+#import "FirebaseCore/Sources/Private/FIRAppInternal.h"
+#import "FirebaseCore/Sources/Private/FIRComponent.h"
+#import "FirebaseCore/Sources/Private/FIRComponentContainer.h"
+#import "FirebaseCore/Sources/Private/FIRComponentType.h"
+#import "FirebaseCore/Sources/Private/FIRDependency.h"
+#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h"
+#import "FirebaseCore/Sources/Private/FIRLibrary.h"
+#import "FirebaseCore/Sources/Private/FIRLogger.h"
+#import "FirebaseCore/Sources/Private/FIROptionsInternal.h"

+ 127 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRApp.h

@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+@class FIROptions;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** A block that takes a BOOL and has no return value. */
+typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback);
+
+/**
+ * The entry point of Firebase SDKs.
+ *
+ * Initialize and configure FIRApp using +[FIRApp configure]
+ * or other customized ways as shown below.
+ *
+ * The logging system has two modes: default mode and debug mode. In default mode, only logs with
+ * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent
+ * to device. The log levels that Firebase uses are consistent with the ASL log levels.
+ *
+ * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this
+ * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled,
+ * further executions of the application will also be in debug mode. In order to return to default
+ * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled.
+ *
+ * It is also possible to change the default logging level in code by calling setLoggerLevel: on
+ * the FIRConfiguration interface.
+ */
+NS_SWIFT_NAME(FirebaseApp)
+@interface FIRApp : NSObject
+
+/**
+ * Configures a default Firebase app. Raises an exception if any configuration step fails. The
+ * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched
+ * and before using Firebase services. This method should be called from the main thread and
+ * contains synchronous file I/O (reading GoogleService-Info.plist from disk).
+ */
++ (void)configure;
+
+/**
+ * Configures the default Firebase app with the provided options. The default app is named
+ * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method should be
+ * called from the main thread.
+ *
+ * @param options The Firebase application options used to configure the service.
+ */
++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:));
+
+/**
+ * Configures a Firebase app with the given name and options. Raises an exception if any
+ * configuration step fails. This method should be called from the main thread.
+ *
+ * @param name The application's name given by the developer. The name should should only contain
+               Letters, Numbers and Underscore.
+ * @param options The Firebase application options used to configure the services.
+ */
+// clang-format off
++ (void)configureWithName:(NSString *)name
+                  options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:));
+// clang-format on
+
+/**
+ * Returns the default app, or nil if the default app does not exist.
+ */
++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app());
+
+/**
+ * Returns a previously created FIRApp instance with the given name, or nil if no such app exists.
+ * This method is thread safe.
+ */
++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:));
+
+/**
+ * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This
+ * method is thread safe.
+ */
+@property(class, readonly, nullable) NSDictionary<NSString *, FIRApp *> *allApps;
+
+/**
+ * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for
+ * future use. This method is thread safe.
+ */
+- (void)deleteApp:(FIRAppVoidBoolCallback)completion;
+
+/**
+ * FIRApp instances should not be initialized directly. Call +[FIRApp configure],
+ * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Gets the name of this app.
+ */
+@property(nonatomic, copy, readonly) NSString *name;
+
+/**
+ * Gets a copy of the options for this app. These are non-modifiable.
+ */
+@property(nonatomic, copy, readonly) FIROptions *options;
+
+/**
+ * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES`
+ * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value
+ * is persisted across runs of the app so that it can be set once when users have consented to
+ * collection.
+ */
+@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled)
+    BOOL dataCollectionDefaultEnabled;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 45 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRConfiguration.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+#import "FIRLoggerLevel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * This interface provides global level properties that the developer can tweak.
+ */
+NS_SWIFT_NAME(FirebaseConfiguration)
+@interface FIRConfiguration : NSObject
+
+/** Returns the shared configuration object. */
+@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared);
+
+/**
+ * Sets the logging level for internal Firebase logging. Firebase will only log messages
+ * that are logged at or below loggerLevel. The messages are logged both to the Xcode
+ * console and to the device's log. Note that if an app is running from AppStore, it will
+ * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose)
+ * setting.
+ *
+ * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice.
+ */
+- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 38 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRLoggerLevel.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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.
+ */
+
+// Note that importing GULLoggerLevel.h will lead to a non-modular header
+// import error.
+
+/**
+ * The log levels used by internal logging.
+ */
+typedef NS_ENUM(NSInteger, FIRLoggerLevel) {
+  /** Error level, matches ASL_LEVEL_ERR. */
+  FIRLoggerLevelError = 3,
+  /** Warning level, matches ASL_LEVEL_WARNING. */
+  FIRLoggerLevelWarning = 4,
+  /** Notice level, matches ASL_LEVEL_NOTICE. */
+  FIRLoggerLevelNotice = 5,
+  /** Info level, matches ASL_LEVEL_INFO. */
+  FIRLoggerLevelInfo = 6,
+  /** Debug level, matches ASL_LEVEL_DEBUG. */
+  FIRLoggerLevelDebug = 7,
+  /** Minimum log level. */
+  FIRLoggerLevelMin = FIRLoggerLevelError,
+  /** Maximum log level. */
+  FIRLoggerLevelMax = FIRLoggerLevelDebug
+} NS_SWIFT_NAME(FirebaseLoggerLevel);

+ 126 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIROptions.h

@@ -0,0 +1,126 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * This class provides constant fields of Google APIs.
+ */
+NS_SWIFT_NAME(FirebaseOptions)
+@interface FIROptions : NSObject <NSCopying>
+
+/**
+ * Returns the default options. The first time this is called it synchronously reads
+ * GoogleService-Info.plist from disk.
+ */
++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions());
+
+/**
+ * An iOS API key used for authenticating requests from your app, e.g.
+ * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers.
+ */
+@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey);
+
+/**
+ * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set
+ * manually or in a plist.
+ */
+@property(nonatomic, copy) NSString *bundleID;
+
+/**
+ * The OAuth2 client ID for iOS application used to authenticate Google users, for example
+ * @"12345.apps.googleusercontent.com", used for signing in with Google.
+ */
+@property(nonatomic, copy, nullable) NSString *clientID;
+
+/**
+ * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics.
+ */
+@property(nonatomic, copy, nullable) NSString *trackingID;
+
+/**
+ * The Project Number from the Google Developer's console, for example @"012345678901", used to
+ * configure Google Cloud Messaging.
+ */
+@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID);
+
+/**
+ * The Project ID from the Firebase console, for example @"abc-xyz-123".
+ */
+@property(nonatomic, copy, nullable) NSString *projectID;
+
+/**
+ * The Android client ID used in Google AppInvite when an iOS app has its Android version, for
+ * example @"12345.apps.googleusercontent.com".
+ */
+@property(nonatomic, copy, nullable) NSString *androidClientID;
+
+/**
+ * The Google App ID that is used to uniquely identify an instance of an app.
+ */
+@property(nonatomic, copy) NSString *googleAppID;
+
+/**
+ * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com".
+ */
+@property(nonatomic, copy, nullable) NSString *databaseURL;
+
+/**
+ * The URL scheme used to set up Durable Deep Link service.
+ */
+@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme;
+
+/**
+ * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com".
+ */
+@property(nonatomic, copy, nullable) NSString *storageBucket;
+
+/**
+ * The App Group identifier to share data between the application and the application extensions.
+ * The App Group must be configured in the application and on the Apple Developer Portal. Default
+ * value `nil`.
+ */
+@property(nonatomic, copy, nullable) NSString *appGroupID;
+
+/**
+ * Initializes a customized instance of FIROptions from the file at the given plist file path. This
+ * will read the file synchronously from disk.
+ * For example,
+ * NSString *filePath =
+ *     [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
+ * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
+ * Returns nil if the plist file does not exist or is invalid.
+ */
+- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a customized instance of FIROptions with required fields. Use the mutable properties
+ * to modify fields for configuring specific services.
+ */
+// clang-format off
+- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
+                        GCMSenderID:(NSString *)GCMSenderID
+    NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)) NS_DESIGNATED_INITIALIZER;
+// clang-format on
+
+/** Unavailable. Please use `init(contentsOfFile:)` or `init(googleAppID:gcmSenderID:)` instead. */
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 24 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright 2020 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+NS_SWIFT_NAME(FirebaseVersion())
+NSString* FIRFirebaseVersion(void);
+
+NS_ASSUME_NONNULL_END

+ 21 - 0
Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore/FirebaseCore.h

@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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 "FIRApp.h"
+#import "FIRConfiguration.h"
+#import "FIRLoggerLevel.h"
+#import "FIROptions.h"
+#import "FIRVersion.h"

+ 61 - 0
Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey"
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey"
+
+/** If present, is an NSString. */
+#define kFIRCDSdkNameKey @"FIRCDSdkNameKey"
+
+/** If present, is an NSString. */
+#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey"
+
+/** If present, is an int32_t wrapped in an NSNumber. */
+#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey"
+
+/** If present, is an NSString. */
+#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey"
+
+/** If present, is an NSString. */
+#define kFIRCDBundleIDKey @"FIRCDBundleID"
+
+/** If present, is a BOOL wrapped in an NSNumber. */
+#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey"
+
+/** If present, is an NSString. */
+#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey"
+
+/** If present, is an NSString. */
+#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey"
+
+/** Defines the interface of a data object needed to log diagnostics data. */
+@protocol FIRCoreDiagnosticsData <NSObject>
+
+@required
+
+/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */
+@property(nonatomic) NSDictionary<NSString *, id> *diagnosticObjects;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 34 - 0
Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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/Foundation.h>
+
+#import "FIRCoreDiagnosticsData.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
+@protocol FIRCoreDiagnosticsInterop <NSObject>
+
+/** Sends the given diagnostics data.
+ *
+ * @param diagnosticsData The diagnostics data object to send.
+ */
++ (void)sendDiagnosticsData:(id<FIRCoreDiagnosticsData>)diagnosticsData;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 202 - 0
Pods/FirebaseCore/LICENSE

@@ -0,0 +1,202 @@
+
+                                 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 2020 Firebase, Inc.
+
+   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.

+ 300 - 0
Pods/FirebaseCore/README.md

@@ -0,0 +1,300 @@
+[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
+
+[![Actions Status][gh-abtesting-badge]][gh-actions]
+[![Actions Status][gh-appdistribution-badge]][gh-actions]
+[![Actions Status][gh-auth-badge]][gh-actions]
+[![Actions Status][gh-core-badge]][gh-actions]
+[![Actions Status][gh-crashlytics-badge]][gh-actions]
+[![Actions Status][gh-database-badge]][gh-actions]
+[![Actions Status][gh-datatransport-badge]][gh-actions]
+[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
+[![Actions Status][gh-firebasepod-badge]][gh-actions]
+[![Actions Status][gh-firestore-badge]][gh-actions]
+[![Actions Status][gh-functions-badge]][gh-actions]
+[![Actions Status][gh-inappmessaging-badge]][gh-actions]
+[![Actions Status][gh-interop-badge]][gh-actions]
+[![Actions Status][gh-messaging-badge]][gh-actions]
+[![Actions Status][gh-remoteconfig-badge]][gh-actions]
+[![Actions Status][gh-storage-badge]][gh-actions]
+[![Actions Status][gh-symbolcollision-badge]][gh-actions]
+[![Actions Status][gh-zip-badge]][gh-actions]
+[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
+
+# Firebase Apple Open Source Development
+
+This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics,
+FirebasePerformance, and FirebaseML.
+
+Firebase is an app development platform with tools to help you build, grow and
+monetize your app. More information about Firebase can be found at
+[https://firebase.google.com](https://firebase.google.com).
+
+The repository also includes GoogleUtilities and GoogleDataTransport source
+which are utilities used by Firebase and other Google products.
+
+## Installation
+
+See the subsections below for details about the different installation methods.
+1. [Standard pod install](README.md#standard-pod-install)
+1. [Swift Package Manager (Beta)](SwiftPackageManager.md)
+1. [Installing from the GitHub repo](README.md#installing-from-github)
+1. [Experimental Carthage](README.md#carthage-ios-only)
+
+### Standard pod install
+
+Go to
+[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup).
+
+### Swift Package Manager (Beta)
+
+Instructions for the Beta of [Swift Package Manager](https://swift.org/package-manager/)
+support can be found at [SwiftPackageManager.md](SwiftPackageManager.md).
+
+### Installing from GitHub
+
+For releases starting with 5.0.0, the source for each release is also deployed
+to CocoaPods master and available via standard
+[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod).
+
+These instructions can be used to access the Firebase repo at other branches,
+tags, or commits.
+
+#### Background
+
+See
+[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod)
+for instructions and options about overriding pod source locations.
+
+#### Accessing Firebase Source Snapshots
+
+All of the official releases are tagged in this repo and available via CocoaPods. To access a local
+source snapshot or unreleased branch, use Podfile directives like the following:
+
+To access FirebaseFirestore via a branch:
+```
+pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
+pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master'
+```
+
+To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do:
+
+```
+pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk'
+pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk'
+```
+
+### Carthage (iOS only)
+
+Instructions for the experimental Carthage distribution are at
+[Carthage](Carthage.md).
+
+### Using Firebase from a Framework or a library
+
+[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md)
+
+## Development
+
+To develop Firebase software in this repository, ensure that you have at least
+the following software:
+
+  * Xcode 11.0 (or later)
+  * CocoaPods 1.9.0 (or later)
+  * [CocoaPods generate](https://github.com/square/cocoapods-generate)
+
+For the pod that you want to develop:
+
+`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios`
+
+Note: If the CocoaPods cache is out of date, you may need to run
+`pod repo update` before the `pod gen` command.
+
+Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for
+those platforms. Since 10.2, Xcode does not properly handle multi-platform
+CocoaPods workspaces.
+
+Firestore has a self contained Xcode project. See
+[Firestore/README.md](Firestore/README.md).
+
+### Development for Catalyst
+* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios`
+* Check the Mac box in the App-iOS Build Settings
+* Sign the App in the Settings Signing & Capabilities tab
+* Click Pods in the Project Manager
+* Add Signing to the iOS host app and unit test targets
+* Select the Unit-unit scheme
+* Run it to build and test
+
+### Adding a New Firebase Pod
+
+See [AddNewPod.md](AddNewPod.md).
+
+### Managing Headers and Imports
+
+See [HeadersImports.md](HeadersImports.md).
+
+### Code Formatting
+
+To ensure that the code is formatted consistently, run the script
+[./scripts/check.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/check.sh)
+before creating a PR.
+
+GitHub Actions will verify that any code changes are done in a style compliant
+way. Install `clang-format` and `mint`:
+
+```
+brew install clang-format@11
+brew install mint
+```
+
+### Running Unit Tests
+
+Select a scheme and press Command-u to build a component and run its unit tests.
+
+#### Viewing Code Coverage (Deprecated)
+
+First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`.
+
+After running the `AllUnitTests_iOS` scheme in Xcode, execute
+`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output`
+at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results.
+
+### Running Sample Apps
+In order to run the sample apps and integration tests, you'll need a valid
+`GoogleService-Info.plist` file. The Firebase Xcode project contains dummy plist
+files without real values, but can be replaced with real plist files. To get your own
+`GoogleService-Info.plist` files:
+
+1. Go to the [Firebase Console](https://console.firebase.google.com/)
+2. Create a new Firebase project, if you don't already have one
+3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
+identifier (e.g. `com.google.Database-Example`)
+4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project.
+
+## Specific Component Instructions
+See the sections below for any special instructions for those components.
+
+### Firebase Auth
+
+If you're doing specific Firebase Auth development, see
+[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about
+building and running the FirebaseAuth pod along with various samples and tests.
+
+### Firebase Database
+
+The Firebase Database Integration tests can be run against a locally running Database Emulator
+or against a production instance.
+
+To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
+running the integration test.
+
+To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
+`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to
+[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
+running.
+
+### Firebase Storage
+
+To run the Storage Integration tests, follow the instructions in
+[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m).
+
+#### Push Notifications
+
+Push notifications can only be delivered to specially provisioned App IDs in the developer portal.
+In order to actually test receiving push notifications, you will need to:
+
+1. Change the bundle identifier of the sample app to something you own in your Apple Developer
+account, and enable that App ID for push notifications.
+2. You'll also need to
+[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs)
+at **Project Settings > Cloud Messaging > [Your Firebase App]**.
+3. Ensure your iOS device is added to your Apple Developer portal as a test device.
+
+#### iOS Simulator
+
+The iOS Simulator cannot register for remote notifications, and will not receive push notifications.
+In order to receive push notifications, you'll have to follow the steps above and run the app on a
+physical device.
+
+## Community Supported Efforts
+
+We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are
+very grateful!  We'd like to empower as many developers as we can to be able to use Firebase and
+participate in the Firebase community.
+
+### tvOS, macOS, watchOS and Catalyst
+Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on
+tvOS, macOS, watchOS and Catalyst.
+
+For tvOS, checkout the [Sample](Example/tvOSSample).
+For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the
+[Independent Watch App Sample](Example/watchOSSample).
+
+Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this
+repository is actively developed primarily for iOS. While we can catch basic unit test issues with
+Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you
+encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues).
+
+During app setup in the console, you may get to a step that mentions something like "Checking if the app
+has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst.
+**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected.
+
+To install, add a subset of the following to the Podfile:
+
+```
+pod 'Firebase/ABTesting'     # No watchOS support yet
+pod 'Firebase/Auth'          # Limited watchOS support
+pod 'Firebase/Crashlytics'
+pod 'Firebase/Database'      # No watchOS support yet
+pod 'Firebase/Firestore'     # No watchOS support yet
+pod 'Firebase/Functions'     # No watchOS support yet
+pod 'Firebase/Messaging'
+pod 'Firebase/RemoteConfig'  # No watchOS support yet
+pod 'Firebase/Storage'
+```
+
+#### Additional Catalyst Notes
+
+* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability`
+to Build Settings.
+* FirebaseFirestore requires signing the
+[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681).
+
+## Roadmap
+
+See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source
+plans and directions.
+
+## Contributing
+
+See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase
+iOS SDK.
+
+## License
+
+The contents of this repository is licensed under the
+[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
+
+Your use of Firebase is governed by the
+[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
+
+[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
+[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
+[gh-appdistribution-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/appdistribution/badge.svg
+[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
+[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
+[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
+[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
+[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
+[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
+[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
+[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
+[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
+[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
+[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
+[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
+[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
+[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
+[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
+[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg

+ 575 - 0
Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m

@@ -0,0 +1,575 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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 <objc/runtime.h>
+#include <sys/utsname.h>
+
+#import "GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h"
+
+#import <GoogleUtilities/GULAppEnvironmentUtil.h>
+#import <GoogleUtilities/GULHeartbeatDateStorage.h>
+#import <GoogleUtilities/GULLogger.h>
+
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h"
+#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h"
+
+#import <nanopb/pb.h>
+#import <nanopb/pb_decode.h>
+#import <nanopb/pb_encode.h>
+
+#import "Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h"
+
+/** The logger service string to use when printing to the console. */
+static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]";
+
+#ifdef FIREBASE_BUILD_ZIP_FILE
+static BOOL kUsingZipFile = YES;
+#else  // FIREBASE_BUILD_ZIP_FILE
+static BOOL kUsingZipFile = NO;
+#endif  // FIREBASE_BUILD_ZIP_FILE
+
+#if SWIFT_PACKAGE
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM
+#elif FIREBASE_BUILD_CARTHAGE
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE
+#elif FIREBASE_BUILD_ZIP_FILE
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE
+#else
+#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS
+#endif
+
+static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter";
+
+static NSString *const kFIRServiceAdMob = @"AdMob";
+static NSString *const kFIRServiceAuth = @"Auth";
+static NSString *const kFIRServiceAuthUI = @"AuthUI";
+static NSString *const kFIRServiceCrash = @"Crash";
+static NSString *const kFIRServiceDatabase = @"Database";
+static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks";
+static NSString *const kFIRServiceFirestore = @"Firestore";
+static NSString *const kFIRServiceFunctions = @"Functions";
+static NSString *const kFIRServiceIAM = @"InAppMessaging";
+static NSString *const kFIRServiceInstanceID = @"InstanceID";
+static NSString *const kFIRServiceInvites = @"Invites";
+static NSString *const kFIRServiceMessaging = @"Messaging";
+static NSString *const kFIRServiceMeasurement = @"Measurement";
+static NSString *const kFIRServicePerformance = @"Performance";
+static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig";
+static NSString *const kFIRServiceStorage = @"Storage";
+static NSString *const kGGLServiceAnalytics = @"Analytics";
+static NSString *const kGGLServiceSignIn = @"SignIn";
+static NSString *const kFIRAppDiagnosticsConfigurationTypeKey =
+    @"FIRAppDiagnosticsConfigurationTypeKey";
+static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey";
+static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey";
+static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey";
+static NSString *const kFIRCoreDiagnosticsHeartbeatTag = @"FIRCoreDiagnostics";
+
+/**
+ * The file name to the recent heartbeat date.
+ */
+NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE";
+
+/**
+ * @note This should implement the GDTCOREventDataObject protocol, but can't because of
+ * weak-linking.
+ */
+@interface FIRCoreDiagnosticsLog : NSObject
+
+/** The config that will be converted to proto bytes. */
+@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config;
+
+@end
+
+@implementation FIRCoreDiagnosticsLog
+
+- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config {
+  self = [super init];
+  if (self) {
+    _config = config;
+  }
+  return self;
+}
+
+// Provided and required by the GDTCOREventDataObject protocol.
+- (NSData *)transportBytes {
+  pb_ostream_t sizestream = PB_OSTREAM_SIZING;
+
+  // Encode 1 time to determine the size.
+  if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
+    GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s",
+                   PB_GET_ERROR(&sizestream));
+  }
+
+  // Encode a 2nd time to actually get the bytes from it.
+  size_t bufferSize = sizestream.bytes_written;
+  CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize);
+  CFDataSetLength(dataRef, bufferSize);
+  pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize);
+  if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) {
+    GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for bytes: %s",
+                   PB_GET_ERROR(&ostream));
+  }
+  CFDataSetLength(dataRef, ostream.bytes_written);
+
+  return CFBridgingRelease(dataRef);
+}
+
+- (void)dealloc {
+  pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config);
+}
+
+@end
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** This class produces a protobuf containing diagnostics and usage data to be logged. */
+@interface FIRCoreDiagnostics : NSObject <FIRCoreDiagnosticsInterop>
+
+/** The queue on which all diagnostics collection will occur. */
+@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue;
+
+/** The transport object used to send data. */
+@property(nonatomic, readonly) GDTCORTransport *transport;
+
+/** The storage to store the date of the last sent heartbeat. */
+@property(nonatomic, readonly) GULHeartbeatDateStorage *heartbeatDateStorage;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+@implementation FIRCoreDiagnostics
+
++ (instancetype)sharedInstance {
+  static FIRCoreDiagnostics *sharedInstance;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    sharedInstance = [[FIRCoreDiagnostics alloc] init];
+  });
+  return sharedInstance;
+}
+
+- (instancetype)init {
+  GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"137"
+                                                             transformers:nil
+                                                                   target:kGDTCORTargetFLL];
+
+  GULHeartbeatDateStorage *dateStorage =
+      [[GULHeartbeatDateStorage alloc] initWithFileName:kFIRCoreDiagnosticsHeartbeatDateFileName];
+
+  return [self initWithTransport:transport heartbeatDateStorage:dateStorage];
+}
+
+/** Initializer for unit tests.
+ *
+ * @param transport A `GDTCORTransport` instance which that be used to send event.
+ * @param heartbeatDateStorage An instanse of date storage to track heartbeat sending.
+ * @return Returns the initialized `FIRCoreDiagnostics` instance.
+ */
+- (instancetype)initWithTransport:(GDTCORTransport *)transport
+             heartbeatDateStorage:(GULHeartbeatDateStorage *)heartbeatDateStorage {
+  self = [super init];
+  if (self) {
+    _diagnosticsQueue =
+        dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL);
+    _transport = transport;
+    _heartbeatDateStorage = heartbeatDateStorage;
+  }
+  return self;
+}
+
+#pragma mark - nanopb helper functions
+
+/** Callocs a pb_bytes_array and copies the given NSString's bytes into the bytes array.
+ *
+ * @note Memory needs to be free manually, through pb_free or pb_release.
+ * @param string The string to encode as pb_bytes.
+ */
+pb_bytes_array_t *FIREncodeString(NSString *string) {
+  NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
+  return FIREncodeData(stringBytes);
+}
+
+/** Callocs a pb_bytes_array and copies the given NSData bytes into the bytes array.
+ *
+ * @note Memory needs to be free manually, through pb_free or pb_release.
+ * @param data The data to copy into the new bytes array.
+ */
+pb_bytes_array_t *FIREncodeData(NSData *data) {
+  pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
+  if (pbBytesArray != NULL) {
+    [data getBytes:pbBytesArray->bytes length:data.length];
+    pbBytesArray->size = (pb_size_t)data.length;
+  }
+  return pbBytesArray;
+}
+
+/** Maps a service string to the representative nanopb enum.
+ *
+ * @param serviceString The SDK service string to convert.
+ * @return The representative nanopb enum.
+ */
+logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum(
+    NSString *serviceString) {
+  static NSDictionary<NSString *, NSNumber *> *serviceStringToTypeEnum;
+  if (serviceStringToTypeEnum == nil) {
+    serviceStringToTypeEnum = @{
+      kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB),
+      kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING),
+      kFIRServiceMeasurement :
+          @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT),
+      kFIRServiceRemoteConfig :
+          @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG),
+      kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE),
+      kFIRServiceDynamicLinks :
+          @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS),
+      kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH),
+      kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI),
+      kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE),
+      kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS),
+      kFIRServicePerformance :
+          @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE),
+      kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE),
+      kFIRServiceMLModelInterpreter :
+          @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER),
+      kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS),
+      kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN),
+      kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING),
+    };
+  }
+  if (serviceStringToTypeEnum[serviceString] != nil) {
+    return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue;
+  }
+  return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE;
+}
+
+#pragma mark - Proto population functions
+
+/** Populates the given proto with data related to an SDK logDiagnostics call from the
+ * diagnosticObjects dictionary.
+ *
+ * @param config The proto to populate
+ * @param diagnosticObjects The dictionary of diagnostics objects.
+ */
+void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
+                                                NSDictionary<NSString *, id> *diagnosticObjects) {
+  NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey];
+  if (configurationType != nil) {
+    switch (configurationType.integerValue) {
+      case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE:
+        config->configuration_type =
+            logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE;
+        config->has_configuration_type = 1;
+        break;
+      case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK:
+        config->configuration_type =
+            logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK;
+        config->has_configuration_type = 1;
+        break;
+      default:
+        break;
+    }
+  }
+
+  NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey];
+  if (sdkName) {
+    config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName);
+    config->has_sdk_name = 1;
+  }
+
+  NSString *version = diagnosticObjects[kFIRCDSdkVersionKey];
+  if (version) {
+    config->sdk_version = FIREncodeString(version);
+  }
+}
+
+/** Populates the given proto with data from the calling FIRApp using the given
+ * diagnosticObjects dictionary.
+ *
+ * @param config The proto to populate
+ * @param diagnosticObjects The dictionary of diagnostics objects.
+ */
+void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config,
+                                           NSDictionary<NSString *, id> *diagnosticObjects) {
+  config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE;
+  config->has_pod_name = 1;
+
+  if (!diagnosticObjects[kFIRCDllAppsCountKey]) {
+    GDTCORLogError(GDTCORMCEGeneralError, @"%@",
+                   @"App count is a required value in the data dict.");
+  }
+  config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue];
+  config->has_app_count = 1;
+
+  NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey];
+  if (googleAppID.length) {
+    config->app_id = FIREncodeString(googleAppID);
+  }
+
+  NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey];
+  if (bundleID.length) {
+    config->bundle_id = FIREncodeString(bundleID);
+  }
+
+  NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey];
+  if (firebaseUserAgent.length) {
+    config->platform_info = FIREncodeString(firebaseUserAgent);
+  }
+
+  NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey];
+  if (usingOptionsFromDefaultPlist != nil) {
+    config->use_default_app = [usingOptionsFromDefaultPlist boolValue];
+    config->has_use_default_app = 1;
+  }
+
+  NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey];
+  if (libraryVersionID) {
+    config->icore_version = FIREncodeString(libraryVersionID);
+  }
+
+  NSString *deviceModel = [GULAppEnvironmentUtil deviceModel];
+  if (deviceModel.length) {
+    config->device_model = FIREncodeString(deviceModel);
+  }
+
+  NSString *osVersion = [GULAppEnvironmentUtil systemVersion];
+  if (osVersion.length) {
+    config->os_version = FIREncodeString(osVersion);
+  }
+
+  config->using_zip_file = kUsingZipFile;
+  config->has_using_zip_file = 1;
+  config->deployment_type = kDeploymentType;
+  config->has_deployment_type = 1;
+  config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore];
+  config->has_deployed_in_app_store = 1;
+}
+
+/** Populates the given proto with installed services data.
+ *
+ * @param config The proto to populate
+ */
+void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+  NSMutableArray<NSNumber *> *sdkServiceInstalledArray = [NSMutableArray array];
+
+  // AdMob
+  if (NSClassFromString(@"GADBannerView") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))];
+  }
+  // CloudMessaging
+  if (NSClassFromString(@"FIRMessaging") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))];
+  }
+  // RemoteConfig
+  if (NSClassFromString(@"FIRRemoteConfig") != nil) {
+    [sdkServiceInstalledArray
+        addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))];
+  }
+  // Measurement/Analtyics
+  if (NSClassFromString(@"FIRAnalytics") != nil) {
+    [sdkServiceInstalledArray
+        addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))];
+  }
+  // ML Model Interpreter
+  if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) {
+    [sdkServiceInstalledArray
+        addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))];
+  }
+  // Database
+  if (NSClassFromString(@"FIRDatabase") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))];
+  }
+  // DynamicDeepLink
+  if (NSClassFromString(@"FIRDynamicLinks") != nil) {
+    [sdkServiceInstalledArray
+        addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))];
+  }
+  // Auth
+  if (NSClassFromString(@"FIRAuth") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))];
+  }
+  // AuthUI
+  if (NSClassFromString(@"FUIAuth") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))];
+  }
+  // Firestore
+  if (NSClassFromString(@"FIRFirestore") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))];
+  }
+  // Functions
+  if (NSClassFromString(@"FIRFunctions") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))];
+  }
+  // Performance
+  if (NSClassFromString(@"FIRPerformance") != nil) {
+    [sdkServiceInstalledArray
+        addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))];
+  }
+  // Storage
+  if (NSClassFromString(@"FIRStorage") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))];
+  }
+  // SignIn via Google pod
+  if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))];
+  }
+  // Analytics via Google pod
+  if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))];
+  }
+
+  // In-App Messaging
+  if (NSClassFromString(@"FIRInAppMessaging") != nil) {
+    [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))];
+  }
+
+  logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled =
+      calloc(sdkServiceInstalledArray.count,
+             sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType));
+  if (servicesInstalled == NULL) {
+    return;
+  }
+  for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) {
+    NSNumber *typeEnum = sdkServiceInstalledArray[i];
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType =
+        (int32_t)typeEnum.integerValue;
+    servicesInstalled[i] = serviceType;
+  }
+
+  config->sdk_service_installed = servicesInstalled;
+  config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count;
+}
+
+/** Populates the proto with the number of linked frameworks.
+ *
+ * @param config The proto to populate.
+ */
+void FIRPopulateProtoWithNumberOfLinkedFrameworks(
+    logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+  int numFrameworks = -1;  // Subtract the app binary itself.
+  unsigned int numImages;
+  const char **imageNames = objc_copyImageNames(&numImages);
+  for (unsigned int i = 0; i < numImages; i++) {
+    NSString *imageName = [NSString stringWithUTF8String:imageNames[i]];
+    if ([imageName rangeOfString:@"System/Library"].length != 0        // Apple .frameworks
+        || [imageName rangeOfString:@"Developer/Library"].length != 0  // Xcode debug .frameworks
+        || [imageName rangeOfString:@"usr/lib"].length != 0) {         // Public .dylibs
+      continue;
+    }
+    numFrameworks++;
+  }
+  free(imageNames);
+  config->dynamic_framework_count = numFrameworks;
+  config->has_dynamic_framework_count = 1;
+}
+
+/** Populates the proto with Info.plist values.
+ *
+ * @param config The proto to populate.
+ */
+void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
+  NSDictionary<NSString *, id> *info = [[NSBundle mainBundle] infoDictionary];
+
+  NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @"";
+  NSString *sdkVersion = info[@"DTSDKBuild"] ?: @"";
+  NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion];
+  config->apple_framework_version = FIREncodeString(combinedVersions);
+
+  NSString *minVersion = info[@"MinimumOSVersion"];
+  if (minVersion) {
+    config->min_supported_ios_version = FIREncodeString(minVersion);
+  }
+
+  // Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and
+  // report it. It's enabled by default.
+  NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"];
+  BOOL appDelegateSwizzled = YES;
+  if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) {
+    appDelegateSwizzled = [appDelegateSwizzledNum boolValue];
+  }
+  config->swizzling_enabled = appDelegateSwizzled;
+  config->has_swizzling_enabled = 1;
+}
+
+#pragma mark - FIRCoreDiagnosticsInterop
+
++ (void)sendDiagnosticsData:(nonnull id<FIRCoreDiagnosticsData>)diagnosticsData {
+  FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance];
+  [diagnostics sendDiagnosticsData:diagnosticsData];
+}
+
+- (void)sendDiagnosticsData:(nonnull id<FIRCoreDiagnosticsData>)diagnosticsData {
+  dispatch_async(self.diagnosticsQueue, ^{
+    NSDictionary<NSString *, id> *diagnosticObjects = diagnosticsData.diagnosticObjects;
+    NSNumber *isDataCollectionDefaultEnabled =
+        diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey];
+    if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) {
+      return;
+    }
+
+    // Create the proto.
+    logs_proto_mobilesdk_ios_ICoreConfiguration icore_config =
+        logs_proto_mobilesdk_ios_ICoreConfiguration_init_default;
+
+    icore_config.using_gdt = 1;
+    icore_config.has_using_gdt = 1;
+
+    // Populate the proto with information.
+    FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects);
+    FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects);
+    FIRPopulateProtoWithInstalledServices(&icore_config);
+    FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config);
+    FIRPopulateProtoWithInfoPlistValues(&icore_config);
+    [self setHeartbeatFlagIfNeededToConfig:&icore_config];
+
+    // This log object is capable of converting the proto to bytes.
+    FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config];
+
+    // Send the log as a telemetry event.
+    GDTCOREvent *event = [self.transport eventForTransport];
+    event.dataObject = (id<GDTCOREventDataObject>)log;
+    [self.transport sendTelemetryEvent:event];
+  });
+}
+
+#pragma mark - Heartbeat
+
+- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config {
+  // Check if need to send a heartbeat.
+  NSDate *currentDate = [NSDate date];
+  NSDate *lastCheckin =
+      [self.heartbeatDateStorage heartbeatDateForTag:kFIRCoreDiagnosticsHeartbeatTag];
+  if (lastCheckin) {
+    // Ensure the previous checkin was on a different date in the past.
+    if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) {
+      return;
+    }
+  }
+
+  // Update heartbeat sent date.
+  [self.heartbeatDateStorage setHearbeatDate:currentDate forTag:kFIRCoreDiagnosticsHeartbeatTag];
+  // Set the flag.
+  config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE;
+  config->has_sdk_name = 1;
+}
+
+- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 {
+  return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] ||
+         [date1 compare:date2] == NSOrderedAscending;
+}
+
+@end

+ 60 - 0
Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c

@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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.
+ */
+
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.9.6 */
+
+#include "firebasecore.nanopb.h"
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22] = {
+    PB_FIELD(  1, UENUM   , OPTIONAL, STATIC  , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0),
+    PB_FIELD(  7, UENUM   , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, configuration_type, 0),
+    PB_FIELD(  9, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0),
+    PB_FIELD( 10, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0),
+    PB_FIELD( 12, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, app_id, 0),
+    PB_FIELD( 16, UENUM   , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, bundle_id, 0),
+    PB_FIELD( 18, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0),
+    PB_FIELD( 19, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0),
+    PB_FIELD( 20, UENUM   , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0),
+    PB_FIELD( 21, INT32   , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0),
+    PB_FIELD( 22, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0),
+    PB_FIELD( 24, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, os_version, 0),
+    PB_FIELD( 25, BOOL    , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0),
+    PB_FIELD( 26, BOOL    , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0),
+    PB_FIELD( 27, INT32   , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0),
+    PB_FIELD( 28, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0),
+    PB_FIELD( 29, BOOL    , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0),
+    PB_FIELD( 30, UENUM   , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0),
+    PB_FIELD( 31, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0),
+    PB_FIELD( 33, BOOL    , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, platform_info, 0),
+    PB_FIELD( 36, BOOL    , OPTIONAL, STATIC  , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, swizzling_enabled, 0),
+    PB_LAST_FIELD
+};
+
+
+
+
+
+
+
+/* @@protoc_insertion_point(eof) */

+ 193 - 0
Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h

@@ -0,0 +1,193 @@
+/*
+ * Copyright 2019 Google
+ *
+ * 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.
+ */
+
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.9.6 */
+
+#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
+#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED
+#include <nanopb/pb.h>
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+/* Enum definitions */
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType {
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2
+} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType {
+    logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3
+} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType {
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35
+} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName {
+    logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2
+} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1))
+
+typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType {
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3,
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4
+} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType;
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM
+#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1))
+
+/* Struct definitions */
+typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration {
+    bool has_configuration_type;
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type;
+    pb_size_t sdk_service_installed_count;
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed;
+    pb_bytes_array_t *device_model;
+    pb_bytes_array_t *app_id;
+    pb_bytes_array_t *bundle_id;
+    bool has_pod_name;
+    logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name;
+    pb_bytes_array_t *icore_version;
+    pb_bytes_array_t *sdk_version;
+    bool has_sdk_name;
+    logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name;
+    bool has_app_count;
+    int32_t app_count;
+    pb_bytes_array_t *os_version;
+    pb_bytes_array_t *min_supported_ios_version;
+    bool has_use_default_app;
+    bool use_default_app;
+    bool has_deployed_in_app_store;
+    bool deployed_in_app_store;
+    bool has_dynamic_framework_count;
+    int32_t dynamic_framework_count;
+    pb_bytes_array_t *apple_framework_version;
+    bool has_using_zip_file;
+    bool using_zip_file;
+    bool has_deployment_type;
+    logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type;
+    pb_bytes_array_t *platform_info;
+    bool has_swizzling_enabled;
+    bool swizzling_enabled;
+    bool has_using_gdt;
+    bool using_gdt;
+/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */
+} logs_proto_mobilesdk_ios_ICoreConfiguration;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0}
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33
+#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22];
+
+/* Maximum encoded size of messages (where known) */
+/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define FIREBASECORE_MESSAGES \
+
+
+#endif
+
+/* @@protoc_insertion_point(eof) */
+
+#endif

+ 18 - 0
Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Public/FIRCoreDiagnostics.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright 2020 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.
+ */
+
+// There are no actual public headers in the lib. This is a dummy public header to prevent Cocoapods
+// from adding all internal headers as public.

+ 0 - 0
Pods/FirebaseCoreDiagnostics/GoogleDataTransport/GDTCORLibrary/Internal/GDTCORAssert.h


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.