ObjectiveCSupport+BSON.swift 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2020 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. import Realm
  19. /**
  20. :nodoc:
  21. **/
  22. public extension ObjectiveCSupport {
  23. // FIXME: remove these and rename convertBson to convert on the next major
  24. // version bump
  25. static func convert(object: AnyBSON?) -> RLMBSON? {
  26. if let converted = object.map(self.convertBson), !(converted is NSNull) {
  27. return converted
  28. }
  29. return nil
  30. }
  31. static func convert(object: RLMBSON?) -> AnyBSON? {
  32. if let object = object {
  33. let converted = convertBson(object: object)
  34. if converted == .null {
  35. return nil
  36. }
  37. return converted
  38. }
  39. return nil
  40. }
  41. static func convert(_ object: Document) -> [String: RLMBSON] {
  42. object.reduce(into: Dictionary<String, RLMBSON>()) { (result: inout [String: RLMBSON], kvp) in
  43. result[kvp.key] = kvp.value.map(convertBson) ?? NSNull()
  44. }
  45. }
  46. /// Convert an `AnyBSON` to a `RLMBSON`.
  47. static func convertBson(object: AnyBSON) -> RLMBSON {
  48. switch object {
  49. case .int32(let val):
  50. return val as NSNumber
  51. case .int64(let val):
  52. return val as NSNumber
  53. case .double(let val):
  54. return val as NSNumber
  55. case .string(let val):
  56. return val as NSString
  57. case .binary(let val):
  58. return val as NSData
  59. case .datetime(let val):
  60. return val as NSDate
  61. case .timestamp(let val):
  62. return val as NSDate
  63. case .decimal128(let val):
  64. return val as RLMDecimal128
  65. case .objectId(let val):
  66. return val as RLMObjectId
  67. case .document(let val):
  68. return convert(val) as NSDictionary
  69. case .array(let val):
  70. return val.map { $0.map(convertBson) } as NSArray
  71. case .maxKey:
  72. return MaxKey()
  73. case .minKey:
  74. return MinKey()
  75. case .regex(let val):
  76. return val
  77. case .bool(let val):
  78. return val as NSNumber
  79. case .uuid(let val):
  80. return val as NSUUID
  81. case .null:
  82. return NSNull()
  83. }
  84. }
  85. static func convert(_ object: [String: RLMBSON]) -> Document {
  86. object.mapValues { convert(object: $0) }
  87. }
  88. /// Convert a `RLMBSON` to an `AnyBSON`.
  89. static func convertBson(object bson: RLMBSON) -> AnyBSON? {
  90. switch bson.__bsonType {
  91. case .null:
  92. return .null
  93. case .int32:
  94. guard let val = bson as? NSNumber else {
  95. return nil
  96. }
  97. return .int32(Int32(val.intValue))
  98. case .int64:
  99. guard let val = bson as? NSNumber else {
  100. return nil
  101. }
  102. return .int64(Int64(val.int64Value))
  103. case .bool:
  104. guard let val = bson as? NSNumber else {
  105. return nil
  106. }
  107. return .bool(val.boolValue)
  108. case .double:
  109. guard let val = bson as? NSNumber else {
  110. return nil
  111. }
  112. return .double(val.doubleValue)
  113. case .string:
  114. guard let val = bson as? NSString else {
  115. return nil
  116. }
  117. return .string(val as String)
  118. case .binary:
  119. guard let val = bson as? NSData else {
  120. return nil
  121. }
  122. return .binary(val as Data)
  123. case .timestamp:
  124. guard let val = bson as? NSDate else {
  125. return nil
  126. }
  127. return .timestamp(val as Date)
  128. case .datetime:
  129. guard let val = bson as? NSDate else {
  130. return nil
  131. }
  132. return .datetime(val as Date)
  133. case .objectId:
  134. guard let val = bson as? RLMObjectId,
  135. let oid = try? ObjectId(string: val.stringValue) else {
  136. return nil
  137. }
  138. return .objectId(oid)
  139. case .decimal128:
  140. guard let val = bson as? RLMDecimal128 else {
  141. return nil
  142. }
  143. return .decimal128(Decimal128(stringLiteral: val.stringValue))
  144. case .regularExpression:
  145. guard let val = bson as? NSRegularExpression else {
  146. return nil
  147. }
  148. return .regex(val)
  149. case .maxKey:
  150. return .maxKey
  151. case .minKey:
  152. return .minKey
  153. case .document:
  154. guard let val = bson as? Dictionary<String, RLMBSON> else {
  155. return nil
  156. }
  157. return .document(convert(val))
  158. case .array:
  159. guard let val = bson as? Array<RLMBSON?> else {
  160. return nil
  161. }
  162. return .array(val.compactMap {
  163. if let value = $0 {
  164. return convertBson(object: value)
  165. }
  166. return .null
  167. }.map { (v: AnyBSON) -> AnyBSON? in v == .null ? nil : v })
  168. case .UUID:
  169. guard let val = bson as? NSUUID else {
  170. return nil
  171. }
  172. return .uuid(val as UUID)
  173. default:
  174. return nil
  175. }
  176. }
  177. }