EncoderDecoder.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. import FirebaseFirestore
  17. import FirebaseSharedSwift
  18. import Foundation
  19. public extension Firestore {
  20. class Encoder {
  21. /// The strategy to use in encoding dates. Defaults to `.timestamp`.
  22. public var dateEncodingStrategy: FirebaseDataEncoder.DateEncodingStrategy = .timestamp
  23. /// Firestore encodes Data as `NSData` blobs versus the default .base64 strings.
  24. public var dataEncodingStrategy: FirebaseDataEncoder.DataEncodingStrategy = .blob
  25. /// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
  26. public var nonConformingFloatEncodingStrategy: FirebaseDataEncoder
  27. .NonConformingFloatEncodingStrategy = .throw
  28. /// The strategy to use for encoding keys. Defaults to `.useDefaultKeys`.
  29. public var keyEncodingStrategy: FirebaseDataEncoder.KeyEncodingStrategy = .useDefaultKeys
  30. /// Contextual user-provided information for use during encoding.
  31. public var userInfo: [CodingUserInfoKey: Any] = [:]
  32. public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
  33. let encoder = FirebaseDataEncoder()
  34. encoder.dateEncodingStrategy = dateEncodingStrategy
  35. encoder.dataEncodingStrategy = dataEncodingStrategy
  36. encoder.nonConformingFloatEncodingStrategy = nonConformingFloatEncodingStrategy
  37. encoder.keyEncodingStrategy = keyEncodingStrategy
  38. encoder.passthroughTypeResolver = FirestorePassthroughTypes.self
  39. encoder.userInfo = userInfo
  40. let encoded = try encoder.encode(value)
  41. guard let dictionaryValue = encoded as? [String: Any] else {
  42. throw EncodingError
  43. .invalidValue(value,
  44. EncodingError
  45. .Context(codingPath: [],
  46. debugDescription: "Top-level \(T.self) is not allowed."))
  47. }
  48. return dictionaryValue
  49. }
  50. public init() {}
  51. }
  52. class Decoder {
  53. /// The strategy to use in decoding dates. Defaults to `.timestamp`.
  54. public var dateDecodingStrategy: FirebaseDataDecoder.DateDecodingStrategy = .timestamp
  55. /// Firestore decodes Data from `NSData` blobs versus the default .base64 strings.
  56. public var dataDecodingStrategy: FirebaseDataDecoder.DataDecodingStrategy = .blob
  57. /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
  58. public var nonConformingFloatDecodingStrategy: FirebaseDataDecoder
  59. .NonConformingFloatDecodingStrategy = .throw
  60. /// The strategy to use for decoding keys. Defaults to `.useDefaultKeys`.
  61. public var keyDecodingStrategy: FirebaseDataDecoder.KeyDecodingStrategy = .useDefaultKeys
  62. /// Contextual user-provided information for use during decoding.
  63. public var userInfo: [CodingUserInfoKey: Any] = [:]
  64. public func decode<T: Decodable>(_ t: T.Type, from data: Any) throws -> T {
  65. let decoder = FirebaseDataDecoder()
  66. decoder.dateDecodingStrategy = dateDecodingStrategy
  67. decoder.dataDecodingStrategy = dataDecodingStrategy
  68. decoder.nonConformingFloatDecodingStrategy = nonConformingFloatDecodingStrategy
  69. decoder.keyDecodingStrategy = keyDecodingStrategy
  70. decoder.passthroughTypeResolver = FirestorePassthroughTypes.self
  71. decoder.userInfo = userInfo
  72. // configure for firestore
  73. return try decoder.decode(t, from: data)
  74. }
  75. public func decode<T: Decodable>(_ t: T.Type, from data: Any,
  76. in reference: DocumentReference?) throws -> T {
  77. if let reference = reference {
  78. userInfo[CodingUserInfoKey.documentRefUserInfoKey] = reference
  79. }
  80. return try decode(T.self, from: data)
  81. }
  82. public init() {}
  83. }
  84. }