EncoderDecoder.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright 2022 Google LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #if SWIFT_PACKAGE
  17. @_exported import FirebaseFirestoreInternalWrapper
  18. #else
  19. @_exported import FirebaseFirestoreInternal
  20. #endif // SWIFT_PACKAGE
  21. import FirebaseSharedSwift
  22. import Foundation
  23. public extension Firestore {
  24. class Encoder {
  25. /// The strategy to use in encoding dates. Defaults to `.timestamp`.
  26. public var dateEncodingStrategy: FirebaseDataEncoder.DateEncodingStrategy = .timestamp
  27. /// Firestore encodes Data as `NSData` blobs versus the default .base64 strings.
  28. public var dataEncodingStrategy: FirebaseDataEncoder.DataEncodingStrategy = .blob
  29. /// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
  30. public var nonConformingFloatEncodingStrategy: FirebaseDataEncoder
  31. .NonConformingFloatEncodingStrategy = .throw
  32. /// The strategy to use for encoding keys. Defaults to `.useDefaultKeys`.
  33. public var keyEncodingStrategy: FirebaseDataEncoder.KeyEncodingStrategy = .useDefaultKeys
  34. /// Contextual user-provided information for use during encoding.
  35. public var userInfo: [CodingUserInfoKey: Any] = [:]
  36. public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
  37. let encoder = FirebaseDataEncoder()
  38. encoder.dateEncodingStrategy = dateEncodingStrategy
  39. encoder.dataEncodingStrategy = dataEncodingStrategy
  40. encoder.nonConformingFloatEncodingStrategy = nonConformingFloatEncodingStrategy
  41. encoder.keyEncodingStrategy = keyEncodingStrategy
  42. encoder.passthroughTypeResolver = FirestorePassthroughTypes.self
  43. encoder.userInfo = userInfo
  44. let encoded = try encoder.encode(value)
  45. guard let dictionaryValue = encoded as? [String: Any] else {
  46. throw EncodingError
  47. .invalidValue(value,
  48. EncodingError
  49. .Context(codingPath: [],
  50. debugDescription: "Top-level \(T.self) is not allowed."))
  51. }
  52. return dictionaryValue
  53. }
  54. public init() {}
  55. }
  56. class Decoder {
  57. /// The strategy to use in decoding dates. Defaults to `.timestamp`.
  58. public var dateDecodingStrategy: FirebaseDataDecoder.DateDecodingStrategy = .timestamp
  59. /// Firestore decodes Data from `NSData` blobs versus the default .base64 strings.
  60. public var dataDecodingStrategy: FirebaseDataDecoder.DataDecodingStrategy = .blob
  61. /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
  62. public var nonConformingFloatDecodingStrategy: FirebaseDataDecoder
  63. .NonConformingFloatDecodingStrategy = .throw
  64. /// The strategy to use for decoding keys. Defaults to `.useDefaultKeys`.
  65. public var keyDecodingStrategy: FirebaseDataDecoder.KeyDecodingStrategy = .useDefaultKeys
  66. /// Contextual user-provided information for use during decoding.
  67. public var userInfo: [CodingUserInfoKey: Any] = [:]
  68. public func decode<T: Decodable>(_ t: T.Type, from data: Any) throws -> T {
  69. let decoder = FirebaseDataDecoder()
  70. decoder.dateDecodingStrategy = dateDecodingStrategy
  71. decoder.dataDecodingStrategy = dataDecodingStrategy
  72. decoder.nonConformingFloatDecodingStrategy = nonConformingFloatDecodingStrategy
  73. decoder.keyDecodingStrategy = keyDecodingStrategy
  74. decoder.passthroughTypeResolver = FirestorePassthroughTypes.self
  75. decoder.userInfo = userInfo
  76. // configure for firestore
  77. return try decoder.decode(t, from: data)
  78. }
  79. public func decode<T: Decodable>(_ t: T.Type, from data: Any,
  80. in reference: DocumentReference?) throws -> T {
  81. if let reference {
  82. userInfo[CodingUserInfoKey.documentRefUserInfoKey] = reference
  83. }
  84. return try decode(T.self, from: data)
  85. }
  86. public init() {}
  87. }
  88. }